This has been annoying me for most of the day..
Suppose that I have the following vector:
v = [1, 2, 4, 9]
I transpose this, so the vector is in columns:
v = [1, 2
4, 9]
I do this, using the following method:
for(unsigned i=0; (i < cols); i++)
{
for(unsigned j=0; (j < 2); j++)
{
std::cout << vect[i*2+j] << " ";
}
std::cout << std::endl;
}
But how would I calculate the columns, first? My aim is to achieve the following:
(1 + 4)/2 = 2.5
(2 + 9)/2 = 5.5
Therefore, a resulting vector would return the mean matrix: x = [2.5, 5.5]
I have tried the following:
double summation = 0;
for(unsigned i=0; (i < cols); i++)
{
for(unsigned j=0; (j < size); j++)
{
summation += values[i*(i*j)+j];
}
std::cout << summation << std::endl;
}
Which produces:
3
8
I am probably missing something really stupid here, but, I can't seem to figure out what.
I have also tried to have a variable subRow which begins at 0 and increments each time by 3 but this did not work either.
Your last sentence has the right idea, but not quite the right number. Where you mention 3, it appears you need 2. That's normally called the "stride". Using it, averaging by columns would come out something like this:
for (int i=0; i<stride; i++) {
double total = 0;
for (int j=0; j<input.size(); j+=stride)
total += input[j];
result[i] = total / (j.size()/stride);
}
At least for the moment, this takes for granted that the size of the input matrix really is "correct" --i.e., an even multiple of the stride you specify.
You may find it easier to debug if keep your index calculations simple:
std::vector<int> v{1, 2, 4, 9};
const unsigned int WIDTH = 2;
for (unsigned int i = 0; i < WIDTH; ++i)
{
double sum = 0.0;
for (unsigned int j = i; j < v.size(); j += WIDTH)
{
sum += v[j];
}
// do something with sum
}
Your problem appears to be here: for(unsigned j=0; (j < size); j++)
You are starting j at 0 and increment by 1 to size() each time. Most of the values you hit will not be valid for what you are trying to do.
int v[] = {1,2,4,9};
int cols = 2;
int rows = 2;
for(int c=0 ; c < cols ; c++) {
double sum=0;
for(int r=0 ; r < rows ; r++)
sum += v[cols*r+c];
std::cout << sum /rows << std::endl;
}
Related
The description of a task goes like this:
We have n numbers, and we have to find quantity of unique sums of all the pairs in the array.
For example:
3 2 5 6 3
The sums of all the pairs(non-repeated) are 5 9 8 6 8 7 5 11 9 8
Unique are 5 9 8 6 7 11
Therefore output is 6
I have come up with this really primitive, and time-consuming (meaning complexity) solution:
int n = 0;
cin >> n;
vector<int> vec(n);
for (int i = 0; i < n; i++)
{
cin >> vec[i];
}
vector<int> sum;
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
sum.push_back(vec[i] + vec[j]);
}
}
sort(sum.begin(), sum.end());
for (int i = 0; i < sum.size()-1;)
{
if (sum[i] == sum[i + 1]) sum.erase(sum.begin() + i);
else i++;
}
cout << endl << sum.size();
I feel like there could be a solution using Combinatorics or something easier. I have thought a lot and couldn't think of anything. So my request is if anyone can improve the solution.
As mentioned above what you need it is difficult to do this without computing the sum of all pairs, so I am not going to handle that, I am just going to advise about efficient data structures.
Analysis of your solution
Your code adds everything in advance O(n^2) then sorts O(n^2 log(n)), then remove duplicates. But since you are erasing from a vector, that ultimately has complexity linear with the number of elements to the end of the list. It means that the second loop will make the complexity of your algorithm O(n^4).
You can count the unique elements in a sorted array without removing
int count = 0;
for (int i = 0; i < sum.size()-1; ++i)
{
if (sum[i] != sum[i + 1]) ++count
}
This change alone makes your algorithm complexity O(n^2 log n).
Alternatives without sorting.
Here are alternatives that O(n^2) and storage depending on the range of the input values instead of the length of the vector (except for the last).
I am testing with 1000 elements smaller between 0 and 10000
vector<int> vec;
for(int i = 0; i < 1000; ++i){
vec.push_back(rand() % 10000);
}
Your implementation sum_pairs1(vec) (18 seconds)
int sum_pairs1(const vector<int> &vec){
vector<int> sum;
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
sum.push_back(vec[i] + vec[j]);
}
}
sort(sum.begin(), sum.end());
for (int i = 0; i < sum.size()-1;)
{
if (sum[i] == sum[i + 1]) sum.erase(sum.begin() + i);
else i++;
}
return sum.size();
}
If you know the range for the sum of the values you can use a bitset, efficient use of memory sum_pairs2<20000>(vec) (0.016 second).
template<size_t N>
int sum_pairs2(const vector<int> &vec){
bitset<N> seen;
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
seen[vec[i] + vec[j]] = true;
}
}
return seen.count();
}
If you know that the maximum sum is not so high (the vector is not very sparse), but you don't know at compilation time you can use a vector, you can keep track of minimum and maximum to allocate the minimum possible and also supporting negative values.
int sum_pairs2b(const vector<int> &vec){
int VMAX = vec[0];
int VMIN = vec[0]
for(auto v : vec){
if(VMAX < v) VMAX = v;
else if(VMIN > v) VMIN = v;
}
vector<bool> seen(2*(VMAX - VMIN) + 1);
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
seen[vec[i] + vec[j] - 2*VMIN] = true;
}
}
int count = 0;
for(auto c : seen){
if(c) ++count;
}
return count;
}
And If you want a more general solution that works well with sparse data sum_pairs3<int>(vec) (0.097 second)
template<typename T>
int sum_pairs3(const vector<T> &vec){
unordered_set<T> seen;
int n = vec.size();
for (int i = 0; i < n; i++)
{
for (int j = i+1; j < n; j++)
{
seen.insert(vec[i] + vec[j]);
}
}
return seen.size();
}
I am asked to find the largest product of 4 adjacent numbers horizontally, diagonally, or vertically, in a 20x20 grid for project euler problem 11. The grid can be found here:http://projecteuler.net/problem=11.
I could not find a more efficient approach than to loop over the entire array 4 times. I made a variable max that was initially set equal to 0. I then looped over the array horizontally, and found the products. If a product was greater than max, max was set to that product, etc. I did this for all 4 loops. However, my answer is wrong, and probably too big.
#include <iostream>
using namespace std;
int main () {
int twenty_grid[20][20] =
{
{ 8, 2, 22, /* data elided since the question links to it */ },
…
}
int max = 0;
// Pass 1: This determines the greatest element horizontally
for (int i = 0; i < 20; ++i) {
for (int j = 0; j < 17; ++j) {
// j stops at 17 to avoid a segmentation fault.
int n = twenty_grid[i][j] *
twenty_grid[i][j+1] *
twenty_grid[i][j+2] *
twenty_grid[i][j+2] *
twenty_grid[i][j+3];
if (n > max)
max = n;
}
}
// Now we do the same loop, except we do i + 1, i + 2, etc,
// rather than j +1, j+2. This does it vertically. Pass 2:
for (int i = 0; i < 17; ++i) {
for (int j = 0; j < 20; ++j) {
int n = twenty_grid[i][j] *
twenty_grid[i+1][j] *
twenty_grid[i+2][j] *
twenty_grid[i+3][j];
if (n > max) {
max = n;
}
}
}
// Finally, we increment both i and j to get the diagonals.
for (int i = 0; i < 17; ++i) {
for (int j = 0; j < 20; ++j) {
int n = twenty_grid[i][j] *
twenty_grid[i+1][j+1] *
twenty_grid[i+2][j+2] *
twenty_grid[i+3][j+3];
if (n > max) {
max = n;
}
}
}
// For diagonals, 2 passes are needed to account for both directions.
for (int i = 0; i < 17; i++) {
for (int j = 3; j < 20; j++) {
int n = twenty_grid[i][j] *
twenty_grid[i + 1][i -1] *
twenty_grid[i + 2][i -2] *
twenty_grid[i + 3][i -3];
if (n > max)
max = n;
}
}
cout << max << endl;
return 0;
}
To take a look at why my answer was constantly wrong, I began to print out each individual product as it was calculated. To my surprise, many of them were negative. After checking my loops, it doesn't seem like they access any data out of the array. Could someone lead me in the right direction for fixing this code?
I found several problems.
The first block of code multiplies twenty_grid[i][j+2] twice.
In the third block of code the end condition for the inner loop should be j < 17.
The last block of code uses i as an array index instead of j in three places.
It produces the correct answer after fixing these issues.
That is my function:
int main() {
double data[100];
int num;
cout<<"num= ";
cin>>num;
for(int i = 1; i <= num; i++) {
cout<<i<<" element = ";
cin>>data[i];
}
Sort(data, num);
for (int i = 1; i <= num; i++) {
cout<<data[i]<<endl;
}
return 0;
}
void Sort(double data[], int n) {
int i,j,k;
double min;
for(i = 0; i < n-1; i++) {
k = i;
min = data[k];
for(j = i+1; j < n; j++)
if(data[j] < min) {
k = j;
min = data[k];
}
data[k] = data[i];
data[i] = min;
}
}
if I write for exp. three elements: 8,9,1 again cout 8,9,1?
for(int i = 1; i <= num; i++) { // WRONG
I think you mean:
for(int i = 0; i < num; i++) { // RIGHT
Arrays in C are 0-indexed remember.
Your sorting function is fine. The only problem is that you enter elements at positions 1 through n, inclusive, while you should use 0 through n-1, inclusive, in both loops of the main() function.
If you need to print numbers 1 through n, use
cout<<(i+1)<<" element = ";
You should get used of the 0 index begin in the for loop
for(int i = 0; i < N; ++i)
so fixing these two index errors will make your code run properly.
the reason is:
if you write data to data[] using 1 as the begining, your data array's first item will be a random number:
if you insert 3 elements, the array will be like this:
data[0] = ??? // maybe a very very big number
data[1] = 8
data[2] = 9
data[3] = 1
and in your Sort function, your index begins at 0 and ends before num, that means your code would only sort data[0], data[1], data[2].
if you use: num = 3, 3 2 1 as your input data for the origin code you could see that 3 and 2 is sorted
I guess your Sort code is googled from somewhere, please try to understand it.
Good online algorithm course: https://www.coursera.org/course/algs4partI
a very good algorithm online book: http://algs4.cs.princeton.edu/home/
btw, for(j = i+1; j < n; j++) in the Sort function would be better if it has { } braces.
I made an array and set the values from 1 to 9 in the initializeBoard function, but for some reason when I print the values they come out 0 to 8. Why is this happening? Shouldn't it print out 1 to 9 since those are the numbers I put in the array in initializeBoard?
int main()
{
initializeBoard();
ticTacToeBoard();
}
void initializeBoard()
{
for (int i = 1; i < 9; i++)
ticTacBoard[i] = i;
cout << endl;
}
void ticTacToeBoard ()
{
for (int y = 0; y < 3; y++)
{
for (int x = 0; x < 3; x++)
cout << ticTacBoard[3 * y + x] << " ";
cout << endl;
}
}
You have an off-by-one error. Arrays use zero-based indexing in C++. Your code does not assign a value to the zeroth element of the array.
Try this instead:
for (int i = 0; i < 9; i++)
{
ticTacBoard[i] = i + 1;
}
The loop:
for (int i = 1; i < 9; i++)
{
ticTacBoard[i] = i;
}
will only do 1-8 since it will stop when i++ increases it to 9, so you're not initializing all 9 elements.
You should realistically do the same loop like this:
for (int i = 0; i < 9; i++)
{
ticTacBoard[i] = (i + 1);
}
Problem lies in:
ticTacBoard[i] = i;
Should be:
ticTacBoard[i-1] = i;
Two suggestions:
Shouldn't you initialize ticTacBoard before accessing it with []? Make sure you give it enough memory for all of your slots! (I'm guessing you're doing tic tac toe, so you'll want 3x3 = 9 slots)
Indexing in C++ starts at 0. You want to do for (i=0; i<9; i++)
Hope this helps!
Your i starts at 0, so your first value will be 0. Since the inequality i < 9 breaks when i = 9, i is actually never 9 (the loop exits before your code is actually run).
Try using <= instead of just < to account for i = 9:
for (int i = 1; i <= 9; i++)
{
ticTacBoard[i - 1] = i;
}
Other than that, arrays are indexed starting from 0 in C++ (and virtually every other language), so the first element is array[0], second is array[1], etc.
You'll have to subtract 1 from your array index.
I have a 49 space one dimensional array declared as int boardArray [49]; and I also have a two dimensional 7x7 array declared as int boardArrayTwo [7][7]' I am trying to use nested for loops to throw the one dimensional array into the two dimensional array here is the code I am using to test it.
for (int i = 0; i > 50; ++i)
{
boardArray[i] = i; //fills the array with ints 0 - 48 to test
}
for (int x = 0; x >= 7; ++x)
{
for (int k = 0; k >= 7; ++k)
{
for (int n = 0; n >= 49; ++n)
{
boardArrayTwo[x][k] = boardArray[n];
cout << boardArrayTwo[x][k] << " " << endl;
}
}
}
I tried running this but nothing happens. Am I doing it wrong?
for (int x = 0; x >= 7; ++x)
{
for (int k = 0; k >= 7; ++k){
for (int n = 0; n >= 49; ++n)
{
this is wrong. x and k should be < 7 (and the third cycle shouldn't be used) :
for (int x = 0; x < 7; ++x)
{
for (int k = 0; k < 7; ++k){
boardArrayTwo[x][k] = boardArray[7*x + k];
EDIT:
like #Fabio Ceconello make me notice in his comment, even the first loop is wrong because of the inverted condition checks, it should be modified this way:
for (int i = 0; i < 49; ++i)
{
boardArray[i] = i; //fills the array with ints 0 - 48 to test
}
Apart from the inverted logic in the loops (which the others mentioned), there's no need for the third inner loop. Just put the attribution in the second inner loop:
boardArrayTwo[x][k] = boardArray[x * 7 + k];
EDIT:
I should also mention that all these literals aren't good practice, and I added one more (7) above. I'd rewrite the code as follows:
#define arrlen(x) (sizeof(x)/sizeof((x)[0]))
for (int i = 0; i < arrlen(boardArray); ++i)
{
boardArray[i] = i;
}
int stride = arrlen(boardArrayTwo[0]);
for (int x = 0; x < arrlen(boardArrayTwo); ++x)
{
for (int k = 0; k < stride; ++k)
{
boardArrayTwo[x][k] = boardArray[stride * x + k];
cout << boardArrayTwo[x][k] << " " << endl;
}
}
caveat: if the arrays aren't declared here (were passed as parameters), arrlen() won't work. But that's another long story...
It looks like your destination array is in row-major order. You could just blast the source array directly into place.
memcpy(boardArrayTwo, boardArray, 49 * sizeof(int));
or if you prefer something in more idiomatic C++:
std::copy(boardArray, boardArray + 49, reinterpret_cast<int*>(boardArrayTwo));
You used i > 50 in your for loop. It should be i < 49 and same for all the other loops.
Also, this won't work. You're setting all of the boardArrayTwo[][] values to boardArray[49] You should instead do something like this:
for (int x = 0; x < 7; ++x)
{
for (int k = 0; k < 7; ++k)
{
boardArrayTwo[x][k] = boardArray[7*x + k];
cout << boardArrayTwo[x][k] << " " << endl;
}
}
or
int count = 0;
for (int x = 0; x < 7; ++x)
{
for (int k = 0; k < 7; ++k)
{
boardArrayTwo[x][k] = boardArray[count];
cout << boardArrayTwo[x][k] << " " << endl;
count++;
}
}
First of all, the second term in the for loop says the for loop would run while that condition is true. So you should use < instead of >= for all your loops.
Second, the loop over n is extra and shouldn't be there. What you need is to go through x and k, then copy the corresponding element from boardArray to boardArrayTwo.
You could do one of these:
int n = 0;
for (int x = 0; x < 7; ++x)
for (int k = 0; k < 7; ++k)
{
boardArrayTwo[x][k] = boardArray[n];
++n;
}
or use a formula to calculate the proper n:
for (int x = 0; x < 7; ++x)
for (int k = 0; k < 7; ++k)
boardArrayTwo[x][k] = boardArray[x*7+k];
I wrote x*7+k because it seems like x is iterating over the rows of the array, each row having 7 elements, says that x*7+kth element of the boardArray represents position [x][k] of boardArrayTwo/
Note
for (int i = 0; i > 50; ++i)
if i is initialized to 0, it won't be greater than 50 and thus it will never enter the loop.
In each of your loops you used greater than or equal (>) to rather than less than (<) or equal to. You should also notice that, as Fabio points out above, the third nested loop is setting boardArrayTwo[x][k] to 0-49 over and over again, 49 times. You will need to use arithmetic to manipulate x and k so that they will be an index into boardArray, and then assign that index to boardArrayTwo[x][k].
It's also important that you are using 0..7 inclusive, which is actually 8 positions. Your array are only of length 7 so you are actually ending up with some garbage values in there.
#include <iostream>
using std::cout;
using std::endl;
int main () {
int boardArray[49];
int boardArrayTwo[7][7];
for (int i = 0; i < 50; ++i)
{
boardArray[i] = i; //fills the array with ints 0 - 48 to test
}
for (int x = 0; x < 7; ++x)
{
for (int k = 0; k < 7; ++k)
{
boardArrayTwo[x][k] = boardArray[x*7 + k];
cout << boardArrayTwo[x][k] << " " << endl;
}
}
}
With any luck (unless I am embarrassing myself) this should do the trick!
EDIT: Special thanks to Fabio!
for(int i=0; i<49; i++)
b[i]=(i+1);
int p=0;
for(int i=0;i<7;i++){
for(int j=0;j<7;j++)
{a[i][j]=b[p];
p++;}
}
beside other errors, third loop is making your code wrong