Using 2-dimensional or 1-dimensional, which is fastest? - c++

I've been searching the web (and stackoverflow) for opinions on whether or not 1-dimensional arrays (or vectors) are faster than their 2-dimensional counterparts. And the general conclusion seems to be that 1-dimensional are the fastest. However, I wrote a short test program to see for myself, and it shows that 2-dimensional are the best. Can anyone find a bug in my test, or at least explain why I get this result?
I use it for storing matrices, and thus need to index the 1-dimensional arrays with both row and column.
#include <iostream>
#include <chrono>
#include <vector>
uint64_t timestamp()
{
namespace sc = std::chrono;
static auto start = sc::high_resolution_clock::now();
return sc::duration_cast<sc::duration<uint64_t, std::micro>>(sc::high_resolution_clock::now() - start).count();
}
int main(int argc, char** argv)
{
if (argc < 3)
return 0;
size_t size = atoi(argv[1]);
size_t repeat = atoi(argv[2]);
int** d2 = (int**)malloc(size*sizeof(int*));
for (size_t i = 0; i < size; ++i)
d2[i] = (int*)malloc(size*sizeof(int));
int* d1 = (int*)malloc(size*size*sizeof(int));
std::vector<std::vector<int> > d2v(size);
for (auto& i : d2v)
i.resize(size);
std::vector<int> d1v(size*size);
uint64_t start, end;
timestamp();
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t r = 0; r < size; ++r)
{
for (size_t c = 0; c < size; ++c)
{
if (r == 0)
d2[r][c] = 0;
else
d2[r][c] = d2[r-1][c] + 1;
}
}
}
end = timestamp();
std::cout << "2D array\t" << size << "\t" << end - start << std::endl;
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t c = 0; c < size; ++c)
{
for (size_t r = 0; r < size; ++r)
{
if (r == 0)
d2[r][c] = 0;
else
d2[r][c] = d2[r-1][c] + 1;
}
}
}
end = timestamp();
std::cout << "2D array C\t" << size << "\t" << end - start << std::endl;
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t r = 0; r < size; ++r)
{
for (size_t c = 0; c < size; ++c)
{
if (r == 0)
d1[r + c*size] = 0;
else
d1[r + c*size] = d1[r-1 + c*size] + 1;
}
}
}
end = timestamp();
std::cout << "1D array\t" << size << "\t" << end - start << std::endl;
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t c = 0; c < size; ++c)
{
for (size_t r = 0; r < size; ++r)
{
if (r == 0)
d1[r + c*size] = 0;
else
d1[r + c*size] = d1[r-1 + c*size] + 1;
}
}
}
end = timestamp();
std::cout << "1D array C\t" << size << "\t" << end - start << std::endl;
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t r = 0; r < size; ++r)
{
for (size_t c = 0; c < size; ++c)
{
if (r == 0)
d2v[r][c] = 0;
else
d2v[r][c] = d2v[r-1][c] + 1;
}
}
}
end = timestamp();
std::cout << "2D vector\t" << size << "\t" << end - start << std::endl;
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t c = 0; c < size; ++c)
{
for (size_t r = 0; r < size; ++r)
{
if (r == 0)
d2v[r][c] = 0;
else
d2v[r][c] = d2v[r-1][c] + 1;
}
}
}
end = timestamp();
std::cout << "2D vector C\t" << size << "\t" << end - start << std::endl;
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t r = 0; r < size; ++r)
{
for (size_t c = 0; c < size; ++c)
{
if (r == 0)
d1v[r + c*size] = 0;
else
d1v[r + c*size] = d1v[r-1 + c*size] + 1;
}
}
}
end = timestamp();
std::cout << "1D vector\t" << size << "\t" << end - start << std::endl;
start = timestamp();
for (size_t n = 0; n < repeat; ++n)
{
for (size_t c = 0; c < size; ++c)
{
for (size_t r = 0; r < size; ++r)
{
if (r == 0)
d1v[r + c*size] = 0;
else
d1v[r + c*size] = d1v[r-1 + c*size] + 1;
}
}
}
end = timestamp();
std::cout << "1D vector C\t" << size << "\t" << end - start << std::endl;
return 0;
}
I get the following output:
user#user-debian64:~/matrix$ ./build/test/index_test 1000 100
2D array 1000 79593
2D array C 1000 326695
1D array 1000 440695
1D array C 1000 262251
2D vector 1000 73648
2D vector C 1000 418287
1D vector 1000 371433
1D vector C 1000 269355
user#user-debian64:~/matrix$ ./build/test/index_test 10000 1
2D array 10000 149748
2D array C 10000 3507346
1D array 10000 2754570
1D array C 10000 257997
2D vector 10000 92041
2D vector C 10000 3791745
1D vector 10000 3384403
1D vector C 10000 266811

The root of the problem is that your storage order is different between the two schemes.
Your 2D structures are stored row-major. By dereferencing the row first, you arrive at a single buffer which can be directly indexed by column. Neighboring columns are in adjacent memory locations.
Your 1D structures are stored column-major. Neighboring columns are size elements apart in memory.
Trying both orders of iteration covers almost all of the effect. But what's left is the data dependence. By referring to D(r-1,c), the access patterns are completely different between row- and column- major.
Sure enough, changing the 1D indexing to d1[r*size + c] and d1[(r-1)*size + c] produces the following timing:
2D array 1000 78099
2D array C 1000 878527
1D array 1000 19661
1D array C 1000 729280
2D vector 1000 61641
2D vector C 1000 741249
1D vector 1000 18348
1D vector C 1000 726231
So, we still have to explain it. I'm going with the "loop-carried dependency". When you iterated the column-major 1D array in column-major order (good idea), each element depended on the element computed in the previous iteration. That means the loop can't be fully pipelined, as the result has to be fully computed and written back to cache, before it can be read again to compute the next element. In row-major, the dependence is now an element that was computed long ago, which means the loop can be unrolled and pipelined.

The way you are iterating through the 1D array is wrong. You don't need a nested loop in a 1D array. It not only is unnecessary, but brings extra math work to calcualte the index. Instead of this part,
for (size_t c = 0; c < size; ++c)
{
for (size_t r = 0; r < size; ++r)
{
if (r == 0)
d1[r + c*size] = 0;
else
d1[r + c*size] = d1[r-1 + c*size] + 1;
}
}
you should write
for (size_t r = 0; r < size*size; ++r)
{
if (r == 0)
d1[r] = 0;
else
d1[r] = d1[r-1] + 1;
}
and it will be fine.

Related

dynamically allocating memory to matrices

I am trying to convert an array to a matrix, so I dynamically allocated memory to the matrix, but I'm getting an error:
CRT detected that the application wrote to memory after end of heap buffer
int main() {
float a[9] = { 1, 3, 5, 6,4,6,5,6,8};
int b = sizeof(a)/sizeof(a[0]);
int r = sqrt(b) - 1;
float **A_mat = new float*[r];
//A_mat = ;
for (int i = 0; i <= r; i++)
A_mat[i] = new float[r];
for (int j = 0; j <= r; j++) {
for (int i = 0; i <= r; i++) {
A_mat[j][i] = a[i + j * (r+1)];
}
}
cout << "a[0,0] is " << A_mat[0][0] << endl;
cout << "a[0,2] is " << A_mat[0][2] << endl;
cout << "a[1,0] is " << A_mat[1][0] << endl;
cout << "a[2,0] is " << A_mat[2][0] << endl;
for (int i = 0; i <= r; i++) {
delete[] A_mat[i];
}
delete[] A_mat;
system("pause");
}
Your code has two major issues:
Issue 1:
float **A_mat = new float*[r]; // allocating memory for 2 rows because r = sqrt(9) - 1 => r = 2
for (int i = 0; i <= r; i++)
A_mat[i] = new float[r]; // Usage of A_mat[r] for r = 2 is out of bounds. Also, memory is allocated for 2 columns.
Issue 2:
for (int j = 0; j <= r; j++) {
for (int i = 0; i <= r; i++) {
A_mat[j][i] = a[i + j * (r+1)]; // accessing indices (0, 2), (1, 2), (2, 0), (2, 1), (2, 2) are out of bounds
}
}
Instead, you should allocate (r + 1) size memory. Like this:
int main() {
float a[9] = { 1, 3, 5, 6,4,6,5,6,8};
int b = sizeof(a)/sizeof(a[0]);
int r = sqrt(b) - 1;
float **A_mat = new float*[r + 1];
//A_mat = ;
for (int i = 0; i <= r; i++)
A_mat[i] = new float[r + 1];
for (int j = 0; j <= r; j++) {
for (int i = 0; i <= r; i++) {
A_mat[j][i] = a[i + j * (r+1)];
}
}
cout << "a[0,0] is " << A_mat[0][0] << endl;
cout << "a[0,2] is " << A_mat[0][2] << endl;
cout << "a[1,0] is " << A_mat[1][0] << endl;
cout << "a[2,0] is " << A_mat[2][0] << endl;
for (int i = 0; i <= r; i++) {
delete[] A_mat[i];
}
delete[] A_mat;
system("pause");
}
Suggestions:
1) Never use raw pointers. Always look for safer alternatives. In this case, you should go for std::vector.
2) Never use naked new. It is generally the major source of Memory leaks. Though currently, its not the case for you. But it might become an issue in the future.
3) Always remember that array starts from 0-indexing in C++.
You have problem with for loop. The index is from 0 to (r-1). But your for loop from 0 to r. It made out of bound of your array.
1> So please replace this for loop
for (int i = 0; i <= r; i++)
by
for (int i = 0; i < r; i++)
2> And replace this statements
for (int j = 0; j <= r; j++) {
for (int i = 0; i <= r; i++) {
A_mat[j][i] = a[i + j * (r+1)];
}
}
by
for (int j = 0; j < r; j++) {
for (int i = 0; i < r; i++) {
A_mat[j][i] = a[i + j * r];
}
}

Apply memmove function to a 3d array

I am trying to achieve the fftshift function (from MATLAB) in c++ with for loop and it's really time-consuming. here is my code:
const int a = 3;
const int b = 4;
const int c = 5;
int i, j, k;
int aa = a / 2;
int bb = b / 2;
int cc = c / 2;
double ***te, ***tempa;
te = new double **[a];
tempa = new double **[a];
for (i = 0; i < a; i++)
{
te[i] = new double *[b];
tempa[i] = new double *[b];
for (j = 0; j < b; j++)
{
te[i][j] = new double [c];
tempa[i][j] = new double [c];
for (k = 0; k < c; k++)
{
te[i][j][k] = i + j+k;
}
}
}
/*for the row*/
if (c % 2 == 1)
{
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < cc; k++)
{
tempa[i][j][k] = te[i][j][k + cc + 1];
tempa[i][j][k + cc] = te[i][j][k];
tempa[i][j][c - 1] = te[i][j][cc];
}
}
}
}
else
{
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < cc; k++)
{
tempa[i][j][k] = te[i][j][k + cc];
tempa[i][j][k + cc] = te[i][j][k];
}
}
}
}
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
te[i][j][k] = tempa[i][j][k];
}
}
}
/*for the column*/
if (b % 2 == 1)
{
for (i = 0; i < a; i++)
{
for (j = 0; j < bb; j++)
{
for (k = 0; k < c; k++)
{
tempa[i][j][k] = te[i][j + bb + 1][k];
tempa[i][j + bb][k] = te[i][j][k];
tempa[i][b - 1][k] = te[i][bb][k];
}
}
}
}
else
{
for (i = 0; i < a; i++)
{
for (j = 0; j < bb; j++)
{
for (k = 0; k < c; k++)
{
tempa[i][j][k] = te[i][j + bb][k];
tempa[i][j + bb][k] = te[i][j][k];
}
}
}
}
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
te[i][j][k] = tempa[i][j][k];
}
}
}
/*for the third dimension*/
if (a % 2 == 1)
{
for ( i = 0; i < aa; i++)
{
for (j = 0; j < b; j++)
{
for ( k = 0; k < c; k++)
{
tempa[i][j][k] = te[i + aa + 1][j][k];
tempa[i + aa][j][k] = te[i][j][k];
tempa[a - 1][j][k] = te[aa][j][k];
}
}
}
}
else
{
for (i = 0; i < aa; i++)
{
for ( j = 0; j < b; j++)
{
for ( k = 0; k < c; k++)
{
tempa[i][j][k] = te[i + aa][j][k];
tempa[i + aa][j][k] = te[i][j][k];
}
}
}
}
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
cout << te[i][j][k] << ' ';
}
cout << endl;
}
cout << "\n";
}
cout << "and then" << endl;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
cout << tempa[i][j][k] << ' ';
}
cout << endl;
}
cout << "\n";
}
now I want to rewrite it with memmove to improve the running efficiency.
For the 3rd dimension, I use:
memmove(tempa, te + aa, sizeof(double)*(a - aa));
memmove(tempa + aa+1, te, sizeof(double)* aa);
this code can works well with 1d and 2d array, but doesn't work for the 3d array. Also, I do not know how to move the column and row elements with memmove. Anyone can help me with all of these? thanks so much!!
Now I have modified the code as below:
double ***te, ***tempa1,***tempa2, ***tempa3;
te = new double **[a];
tempa1 = new double **[a];
tempa2 = new double **[a];
tempa3 = new double **[a];
for (i = 0; i < a; i++)
{
te[i] = new double *[b];
tempa1[i] = new double *[b];
tempa2[i] = new double *[b];
tempa3[i] = new double *[b];
for (j = 0; j < b; j++)
{
te[i][j] = new double [c];
tempa1[i][j] = new double [c];
tempa2[i][j] = new double [c];
tempa3[i][j] = new double [c];
for (k = 0; k < c; k++)
{
te[i][j][k] = i + j+k;
}
}
}
/*for the third dimension*/
memmove(tempa1, te + (a-aa), sizeof(double**)*aa);
memmove(tempa1 + aa, te, sizeof(double**)* (a-aa));
//memmove(te, tempa, sizeof(double)*a);
/*for the row*/
for (i = 0; i < a; i++)
{
memmove(tempa2[i], tempa1[i] + (b - bb), sizeof(double*)*bb);
memmove(tempa2[i] + bb, tempa1[i], sizeof(double*)*(b - bb));
}
/*for the column*/
for (j = 0; i < a; i++)
{
for (k = 0; j < b; j++)
{
memmove(tempa3[i][j], tempa2[i][j] + (c - cc), sizeof(double)*cc);
memmove(tempa3[i][j] + cc, tempa2[i][j], sizeof(double)*(c-cc));
}
}
but the problem is that I define too much new dynamic arrays and also the results for tempa3 are incorrect. could anyone give some suggestions?
I believe you want something like that:
memmove(tempa, te + (a - aa), sizeof(double**) * aa);
memmove(tempa + aa, te, sizeof(double**) * (a - aa));
or
memmove(tempa, te + aa, sizeof(double**) * (a - aa));
memmove(tempa + (a - aa), te, sizeof(double**) * aa);
depending on whether you want to swap the first half "rounded up or down" (I assume you want it rounded up, it's the first version then).
I don't really like your code's design though:
First and foremost, avoid dynamic allocation and use std::vector or std::array when possible.
You could argue it would prevent you from safely using memmove instead of swap for the first dimensions (well, it should work, but I'm not 100% sure it isn't implementation defined) but I don't think that would improve that much the efficiency.
Besides, if you want to have a N-dimensional array, I usually prefer avoiding "chaining pointers" (although with your algorithm, you can actually use this structure, so it's not that bad).
For instance, if you're adamant about dynamically allocating your array with new, you might use something like that instead to reduce memory usage (the difference might be neglectible though; it's also probably slightly faster but again, probably neglectible):
#include <cstddef>
#include <iostream>
typedef std::size_t index_t;
constexpr index_t width = 3;
constexpr index_t height = 4;
constexpr index_t depth = 5;
// the cells (i, j, k) and (i, j, k+1) are adjacent in memory
// the rows (i, j, _) and (i, j+1, _) are adjacent in memory
// the "slices" (i, _, _) and (i+1, _, _) are adjacent in memory
constexpr index_t cell_index(index_t i, index_t j, index_t k) {
return (i * height + j) * depth + k;
}
int main() {
int* array = new int[width * height * depth]();
for( index_t i = 0 ; i < width ; ++i )
for( index_t j = 0 ; j < height ; ++j )
for( index_t k = 0 ; k < depth ; ++k ) {
// do something on the cell (i, j, k)
array[cell_index(i, j, k)] = i + j + k;
std::cout << array[cell_index(i, j, k)] << ' ';
}
std::cout << '\n';
// alternatively you can do this:
//*
for( index_t index = 0 ; index < width * height * depth ; ++index) {
index_t i = index / (height * depth);
index_t j = (index / depth) % height;
index_t k = index % depth;
array[index] = i + j + k;
std::cout << array[index] << ' ';
}
std::cout << '\n';
//*/
delete[] array;
}
The difference is the organization in memory. Here you have a big block of 60*sizeof(int) bytes (usually 240 or 480 bytes), whereas with your method you would have:
- 1 block of 3*sizeof(int**) bytes
- 3 blocks of 4*sizeof(int*) bytes
- 12 blocks of 5*sizeof(int) bytes
(120 more bytes on a 64 bit architecture, two additional indirections for each cell access, and more code for allocating/deallocating all that memory)
Granted, you can't do array[i][j][k] anymore, but still...
The same stands with vectors (you can either make an std::vector<std::vector<std::vector<int>>> or a std::vector<int>)
There is also a bit too much code repetition: your algorithm basically swaps the two halves of your table three times (once for each dimension), but you rewrote 3 times the same thing with a few differences.
There is also too much memory allocation/copy (your algorithm works and can exploit the structure of array of pointers by simply swapping pointers to swap whole rows/slices, in that specific case, you can exploit this data structure to avoid copies with your algorithm... but you don't)
You should choose more explicit variable names, that helps. For instance use width, height, depth instead of a, b, c.
For instance, here is an implementation with vectors (I didn't know matlab's fftshift function though, but according to your code and this page, I assume it's basically "swapping the corners"):
(also, compile with -std=c++11)
#include <cstddef>
#include <iostream>
#include <vector>
#include <algorithm>
typedef std::size_t index_t;
typedef double element_t;
typedef std::vector<element_t> row_t;
typedef std::vector<row_t> slice_t;
typedef std::vector<slice_t> array_3d_t;
// for one dimension
// you might overload this for a std::vector<double>& and use memmove
// as you originally wanted to do here
template<class T>
void fftshift_dimension(std::vector<T>& row)
{
using std::swap;
const index_t size = row.size();
if(size <= 1)
return;
const index_t halved_size = size / 2;
// swap the two halves
for(index_t i = 0, j = size - halved_size ; i < halved_size ; ++i, ++j)
swap(row[i], row[j]);
// if the size is odd, rotate the right part
if(size % 2)
{
swap(row[halved_size], row[size - 1]);
const index_t n = size - 2;
for(index_t i = halved_size ; i < n ; ++i)
swap(row[i], row[i + 1]);
}
}
// base case
template<class T>
void fftshift(std::vector<T>& array) {
fftshift_dimension(array);
}
// reduce the problem for a dimension N+1 to a dimension N
template<class T>
void fftshift(std::vector<std::vector<T>>& array) {
fftshift_dimension(array);
for(auto& slice : array)
fftshift(slice);
}
// overloads operator<< to print a 3-dimensional array
std::ostream& operator<<(std::ostream& output, const array_3d_t& input) {
const index_t width = input.size();
for(index_t i = 0; i < width ; i++)
{
const index_t height = input[i].size();
for(index_t j = 0; j < height ; j++)
{
const index_t depth = input[i][j].size();
for(index_t k = 0; k < depth; k++)
output << input[i][j][k] << ' ';
output << '\n';
}
output << '\n';
}
return output;
}
int main()
{
constexpr index_t width = 3;
constexpr index_t height = 4;
constexpr index_t depth = 5;
array_3d_t input(width, slice_t(height, row_t(depth)));
// initialization
for(index_t i = 0 ; i < width ; ++i)
for(index_t j = 0 ; j < height ; ++j)
for(index_t k = 0 ; k < depth ; ++k)
input[i][j][k] = i + j + k;
std::cout << input;
// in place fftshift
fftshift(input);
std::cout << "and then" << '\n' << input;
}
live example
You could probably make a slightly more efficient algorithm by avoiding to swap multiple times the same cell and/or using memmove, but I think it's already fast enough for many uses (on my machine fftshift takes roughly 130ms for a 1000x1000x100 table).

Dynamic 2D array C++98 vs C++11

Following this question "What is “cache-friendly” code?" I've created dynamic 2d array to check how much time would it take to access elements column-wise and row-wise.
When I create an array in the following way:
const int len = 10000;
int **mass = new int*[len];
for (int i = 0; i < len; ++i)
{
mass[i] = new int[len];
}
it takes 0.239 sec to traverse this array row-wise and 1.851 sec column-wise (in Release).
But when I create an array in this way:
auto mass = new int[len][len];
I get an opposite result: 0.204 sec to traverse this array row-wise and 0.088 sec column-wise.
My code:
const int len = 10000;
int **mass = new int*[len];
for (int i = 0; i < len; ++i)
{
mass[i] = new int[len];
}
// auto mass = new int[len][len]; // C++11 style
begin = std::clock();
for (int i = 0; i < len; ++i)
{
for (int j = 0; j < len; ++j)
{
mass[i][j] = i + j;
}
}
end = std::clock();
std::cout << "[i][j] " << static_cast<float>(end - begin) / 1000 << std::endl;
begin = std::clock();
for (int i = 0; i < len; ++i)
{
for (int j = 0; j < len; ++j)
{
mass[j][i] = i + j;
}
}
end = std::clock();
std::cout << "[j][i] " << static_cast<float>(end - begin) / 1000 << std::endl;
Please, can you explain what is the difference between these ways to allocate memory for two-dimentional dynamic array? Why does it faster to traverse array row-wise in first way and column-wise in second way?

Split a vector into n sub vectors (rebound)

I am trying to split a vector into n parts.
I checked the following solution How to split a vector into n "almost equal" parts
I came out with the following code based on this comment :
To get a base number for the size of each part, simply divide the total by the number of parts: 11/3 = 3. Obviously some of the parts will need to be bigger than that to get the proper total, but that's just the remainder: 11 % 3 = 2. So now you know that 2 of the parts will be size 3+1, and whatever's left over will be 3. (Mark Ransom)
int main()
{
std::vector<int> lines;
int size = 200;
for(int i = 0; i < size;i++)
{
lines.push_back(i);
}
int p = 6;
int right = round((double)size/(double)p);
for(int i = 0; i < p;i++)
{
if( i < size - left)
{
vector<int> v;
for(int j = 0; j < right; j++)
{
v.push_back(lines[j]);
}
cout << v.size() << endl;
}
else if (i > size - left)
{
vector<int> v;
for(int k = 0; k < right; k++)
{
v.push_back(lines[k]);
}
cout << v.size() << endl;
}
}
return 0;
}
Output with p = 6 and size = 200 is : 33,33,33,33,33,33 = 198
Output with p = 6 and size = 1000 is : 167,167,167,167,167,167 = 1002
both outputs are wrong. What am i missing?
After editing:
So Let me understand.
We increment i by right which represents the size of a chunk or sub-vector.
While i is less than the size-right we do nothing. When i becomes greater we have to deal with the Leftovers we change the size of the chunk by right = size - i.
int main()
{
std::vector<int> lines;
int size = 1000;
for(int i = 0; i < size;i++)
{
lines.push_back(i);
}
int p = 6;
int right = round((double)size/(double)p);
int left = size % p;
for(int i = 0; i < size; i+= right)
{
if(i < size - right)
{
vector<int> v;
//MAJOR CORRECTION
for(int j = i; j < (i+right); j++)
{
v.push_back(lines[j]);
}
cout << v.size() << endl;
}
else
{
right = size - i;
vector<int> v;
//Major Correction
for(int k =i; k < size; k++)
{
v.push_back(lines[k]);
}
cout << v.size() << endl;
}
return 0;
}
Thank you.
output: 33 33 33 33 33 33 2 = 200
int right = size/p; // don't round! this floors.
int left = size % p; // this one is correct.
for(int i = 0; i < p;i++)
{
if( i < size - left)
{
vector<int> v;
for(int j = 0; j < right; j++) // counters, you used i here.
{
v.push_back(lines[j]); // and here.
}
cout << v.size() << endl;
}
else if (i >= size - left)// sorry equal is here. try >= not > , comment with results.
{
vector<int> v;
for(int j = 0; j < right+1; j++) // and here
{
v.push_back(lines[j]); // and here
}
cout << v.size() << endl;
}
}
Think your idea in other way:
p (parts) = 3, size = 11, ceil(11/3) = 4 so 4+4+3 = 11
same for other
p = 6, size = 200 ceil(200/6) = 34 so, 34+34+34+34+34+30 = 200
int p = 6;
size_t nLimit = ceil((double)lines.size()/p);
// if you don't want to contain the leftover element within p elements, use floor
vector<int>::iterator start = lines.begin();
for(size_t i = 0; i < lines.size(); i+=nLimit){
// Just use the constructor/insert function
vector<int> v(start+i, start+std::min<size_t>(i+nLimit, lines.size()));
cout<<v.size()<<endl;
}
Working code here:
http://ideone.com/6V7rSX

Convert One Dimensional Arrary to Two Dimensional in C++

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