Getting specific elements in a vector - c++

I'm trying to get a specific element inside of a vector.
For example,
Lets say I have a vector.
std::vector<Tile> TileList;
The Vector is of size MAP_HEIGHT = 30, MAP_WIDTH = 200
So its total size is MAP_HEIGHT * MAP_WIDTH = 6000.
I use a double nested for loop to iterate through and create a vector full of tiles.
for(int Y = 0; Y < MAP_HEIGHT; Y++)
{
for(int X = 0; X < MAP_WIDTH; X++)
{
Tile TempTile;
fscanf(FileHandle, "%d:%d ", &TempTile.TileID, &TempTile.TypeID);
TileList.push_back(TempTile);
}
}
Now my questions is lets say I iterate through
int ID = 0;
for(int Y = 0; Y < MAP_HEIGHT; Y++)
{
for(int X = 0; X < MAP_WIDTH; X++)
{
TileList[ID].do stuff with it
//Check for the tile above this tile
// Find a way to calculate the ID of the tile above this tile
int IDoftilabove = ID - do something;
if(TileList[IDoftilabove].variable == TILE_SOMETHING)
{
do stuff
}
ID++;
}
How do I calculate the ID of an element above(well technically before this ID) inside the vector based on the current element I'm on.
Illustration:
say i have a matrix 5x5,
Lets say my current ID is 8. so I am on the second row number 3.
1 2 *3* 4 5
1 2 (3) 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
Now I want the ID of the element in vector that is directly above me which is the ID 3, first row number 3. and this is just assuming the the MAP_WIDTH = 5 and the MAP_HEIGHT = 5.

8 - 5 = 3
Current - MAP_WIDTH = Above

You can easily determine the (row,col) coordinates given the ID:
row = ID / MAP_WIDTH;
col = ID % MAP_WIDTH;
If you want to know what is the coordinate from the element above:
row--;
ID_above = row * MAP_WIDTH + col;
The same applies if you want to know what is the element below:
row++;
ID_below = row * MAP_WIDTH + col;

It seems like you want to map between linear and 2d indices. This is pretty straightforward.
int rect2lin(int w, int x, int y) { return y*w+x; }
void lin2rect(int w, int i, int * x, int * y) { *y = i/w; *x = i%w; }
So in your example, the ID of the element above (X,Y) would be rect2lin(MAP_WIDTH, X,Y-1), which is simply (Y-1)*MAP_WIDTH+X. This generalizes straightforwardly to higher numbers of dimension. For example, i=(z*h+y)*w+x for 3d, and so on.

Related

Multidimensional array printing wrong values in cpp

I've been struggling with a simple class representing a matrix in C++. Instead of using a multidimensional array, I've decided to use a flat array and access the values by calculating the index of the according cell by [row * x_dim + col]. I want to use 2D matrices only.
Ideally, I would also create getter and setter functions, but as I am already having troubles I skipped those for now.
The main problem is, that after setting values, those values seem to be corrupted somewhere along the way as when printing them out again, I'm reading different values then what I've actually stored.
Here's the (simplified) header MyMatrix.h:
class MyMatrix{
public:
int x_dim, y_dim;
float *my_matrix;
MyMatrix(int x, int y);
~MyMatrix();
};
Here is MyMatrix.cpp:
#include "MyMatrix.h"
MyMatrix::MyMatrix(int x, int y){
x_dim = x;
y_dim = y;
my_matrix = new float[x * y];
}
MyMatrix::~MyMatrix(){
delete[] my_matrix;
}
Now when creating a new instance of MyMatrix, filling the array with ascending numbers and then printing the values again, I am getting different values for some cells in the (flat) matrix. Here's what I did:
#include "MyMatrix.h"
#include <iostream>
int main(){
MyMatrix test(3, 4);
//filling the array in test with ascending numbers
for(int row = 0; row < test.x_dim; row++){
for(int col = 0; col < test.y_dim; col++){
test.my_matrix[row * test.x_dim + col] = col+1;
}
}
for(int row = 0; row < test.x_dim; row++){
std::cout << "Row " << row << ": ";
for(int col = 0; col < test.y_dim; col++){
std::cout << test.my_matrix[row * test.x_dim + col] << " ";
}
std::cout << std::endl;
}
}
So what my output should look like is this:
Row 0: 1 2 3 4
Row 1: 1 2 3 4
Row 2: 1 2 3 4
But instead, it looks like this:
Row 0: 1 2 3 1
Row 1: 1 2 3 1
Row 2: 1 2 3 4
As one can see, the first two rows have a 1 instead of a 4 in column 3.
I've really been struggling with identifying the underlying issue here and I can't figure it out so I would appreciate any help!
Thanks!
I am using clang version 13.0.0 on an M1 Pro and the g++ compiler.
This is the wrong index:
row * test.x_dim + col
Suppose you are in the last iteration of the outer loop then row == x_dim-1 and you get:
(x_dim-1) * x_dim + col
while it should be (supposed x is rows):
(y_dim-1) * x_dim + col
Tip: Your variable naming col vs x_dim and row vs y_dim can be made better. x, x_dim and y, y_dim or col, num_columns and row, num_rows would be less errorprone.

Wrapping 2d grid indices

I have this function which i prototyped in python for navigating grid indexes. It works perfectly in python but due to the way the modulo operator handles negative numbers it falls down in c++. Can anyone suggest a modification that will make this work?
The function fails when coordinates nx and ny are negative.
int wrap_grid(int index, int x, int y, int nx, int ny) {
//first calculate positon on row by adding nx -
//assuming an infinite grid of indices (no limits or wrap)
int a = (index + (y * nx));
//then wrap around the width (x) of the row
int b = a % (x * y);
//now do column, calculate the bottom index of the column
int start = b - b % y;
//and the top index
int limit = b - b % y + y;
//now wrap the ny value around the columns
return start + (b + ny) % (limit - start);
}
EDIT: To explain function arguments
index is the index of a rectangular grid, like this:
col1
col2
col3
5
11
17
4
10
16
3
9
15
2
8
14
1
7
13
0
6
12
x is the width of the grid, in this case 3.
y is the height of the grid, in this case 6.
nx is the coordinate grid square offset, so nx = 1 is one grid square to the right, similar for ny=1 is one grid square 'upwards'.
The return value is the new index number after transforming index with the coordinates nx and ny.
EDIT: updated function based on jwezorek's approach. Note, the only effective change (function factors aside) are the comparison operators which must allow zero values.
int wrap_grid(int index, int rows, int columns, int offset_x, int offset_y) {
//index to grid coordinates always positive
int x = (index / rows) + (offset_x);
x = x >= 0 ? x : x + columns;
int y = (index % rows) + (offset_y);
y = y >= 0 ? y : y + rows;
//grids to coords
int column = x % columns;
column = column >= 0 ? column : column + columns;
int row = y % rows;
row = row >= 0 ? row : row + rows;
int bottom_of_column_index = column * rows;
return bottom_of_column_index + row;
}
You just need a mod function that will only give you non-negative values. To just do it the straight-forward way is like below (after moving your code around for clarity).
#include <tuple>
#include <iostream>
int grid_coords_to_index(int cols, int rows, int x, int y) {
// wrap the coordinates...
int column = x % cols;
column = column >= 0 ? column : column + cols;
int row = y % rows;
row = row >= 0 ? row : row + rows;
int bottom_of_column_index = column * rows;
return bottom_of_column_index + row;
}
std::tuple<int,int> index_to_grid_coords(int cols, int rows, int index) {
// TODO: handle negatives correctly here too, if we cannot
// assume indices are positive.
return { index / rows, index % rows };
}
int wrap_grid(int initial_index, int cols, int rows, int x_offset, int y_offset) {
auto [x, y] = index_to_grid_coords(cols, rows, initial_index);
return grid_coords_to_index(cols, rows, x + x_offset, y + y_offset);
}
int main()
{
/*
5 11 17
4 10 16
3 9 15
2 8 14
1 7 13
0 6 12
index 9 is (1,3) so two to the left and one down should be 14 given wrapping
*/
std::cout << wrap_grid(9, 3, 6, -2, -1) << "\n";
}

Check if any value in array is equal to current value added to array

I have a 2D array initialized to Storage[100][3].
I insert a group values to each row of the array and move on to the next row and do the same,
for example:
1 1 3
2 5 6
3 1 3
(keeps going on to 100 rows)
After completing the insertion of 1 entire row I want to check if the values in this current insertion's column's 2 and 3 match the values in all the previous row's, column's 2 and 3.
for example in the above data set I look at column's 2 and 3 in each row and see that rows 1 and 3 have the same values in those columns.
I wrote a program that can compare the current insertion to the previous insertion. But I want to compare the current insertion with all the insertions in the array.
const int col=0;
//inserting the values//
for (int row= 0; row < 100; row++) {
storage[row][col] = t;
storage[row][col += 1] = xi;
storage[row][col += 2] = yi;
}
//trying to check if the values are same. need help here//
for (int row = 0; row < 100; row++) {
if (storage[row][col + 1]==storage[row + 1][col + 1]
&& storage[row][col + 2] == storage[row + 1][col + 2]) {
}
}
for (int row = 1; row < 100; row++) {
for (int prevRow = 0; prevRow < row; prevRow++) {
if (storage[row][1] == storage[prevRow][1]
&& storage[row][2] == storage[prevRow][2]) {
// do something...
}
}
}
Outer loop starts from row = 1 becuase row 0 doesn't have previous rows to compare.
If you want to create an algorithm that scales nicely O(log2n) rather than O(n^2) try using a Hash table to keep track of encountered numbers. My example numbers for the first iteration are 4, 2, 3.
You can get a count of how many times you've encountered your duplicate numbers and most importantly you don't have to do the heavy lifting of loop-searching yourself!
int main(array<System::String ^> ^args)
{
std::map<int, int> twoColsCounts;
int storage[100][3];
int ordinal1 = 4;
int ordinal2 = 2;
int ordinal3 = 3;
for (int i = 0; i < 100; i++)
{
storage[i][0] = ordinal1;
storage[i][1] = ordinal2;
storage[i][2] = ordinal3;
int lastTwoDigits = ordinal2 * 10 + ordinal3;
auto inMapRecord = twoColsCounts.find(lastTwoDigits);
if (inMapRecord != twoColsCounts.end())
{
// Number Already Found. Increment count for posterity!
twoColsCounts[lastTwoDigits]++;
}
else
{
// Not already encountered - Add it to record with count of 1
twoColsCounts[lastTwoDigits] = 1;
}
}
Console::WriteLine(L"Done 'big data' style!");
return 0;
}
Good luck!

Switching Matrix columns and rows in C++

I have a 6 x 6 matrix, and I am storing its values in a one dimensional array of size 36. I want to rearrange it so that the rows are the columns and the columns are the rows. My method is trying to copy the values into another array, but sorted properly. I am trying a for loop:
for (int i = 0; i < 6; ++i){
copyArray[i]= array[i*6];
}
This works fine for the first new row made up of the first column, but how do I continue to do all of them? I have tried nested for loops but cannot come up with the proper algorithm using iterators. I could do this manually, but would like to have this done by code.
I am coding in C++, but if anyone can do it in a similar language that would be fine. I feel this is a math problem.
The Question: How do I solve for switching out the rows and columns?
(Example: if I am denoting the first rows and columns as 0, in a 6x6 matrix, then both rows and columns go from 0 to 5. Therefore, by switching rows and columns, the value in row 2, column 5 would be switched with the value in row 5, column 2.)
Couldn't you just use a nested for loop and do something like this?
for (int i = 0; i < 6; ++i)
for (int j = 0; j < 6; ++j)
copyArray[i*6+j]= array[j*6+i];
Here's a test program you can run to show it works:
#include <stdio.h>
int main()
{
int array[36] = {1,1,1,1,1,1,
2,2,2,2,2,2,
3,3,3,3,3,3,
4,4,4,4,4,4,
5,5,5,5,5,5,
6,6,6,6,6,6};
int copyarray[36];
for (int i = 0; i < 6; ++i)
for (int j = 0; j < 6; ++j)
copyarray[i*6+j]= array[j*6+i];
for (int i = 0; i < 36; ++i)
{
if (i % 6 == 0)
printf("\n");
printf("%d ", array[i]);
}
printf("\n");
printf("\n");
for (int i = 0; i < 36; ++i)
{
if (i % 6 == 0)
printf("\n");
printf("%d ", copyarray[i]);
}
return 0;
}
Output:
1 1 1 1 1 1
2 2 2 2 2 2
3 3 3 3 3 3
4 4 4 4 4 4
5 5 5 5 5 5
6 6 6 6 6 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
You should keep your one-D array inside a class.
Then you can swap the dimensionality of the data without actually moving it.
class MySwapableArray
{
bool normal;
int array[36];
public:
int& operator()(int x, int y)
{
int h = normal ? x : y;
int v = normal ? y : x;
return array[h*6+v];
}
void swapRowsAndColumns()
{
normal = ! normal;
}
};
If you want to use operator[] like A[x][y] then see: How to overload array index operator for wrapper class of 2D array?
A template for doing so.
template<class X> std::unique_ptr<typename std::pointer_traits<X>::element_type[]>
transpose(const X& p, int x, int y) {
using T = std::pointer_traits<X>::element_type;
std::unique_ptr<T[]> r = new T[x*y];
for(int a = 0; a < x; ++a)
for(int b = 0; b < y; ++b)
r[x*a+b] = p[y*b+a];
return r;
}
If you want to avoid a double-for loop, you should be able to do it mathematically with something like
for (int i = 0; i < 36; ++i) {
copyarray[6 * (i % 6) + i / 6] = array[i]
}
Basically, 6 * (i % 6) aligns you to the right row in the transposed matrix, and the i / 6 (ab)uses integer division to translate the column value into a row value. floor (i / 6.0) is more correct if you can live with the clutter.
for( int i=0;i<6;i++)
for( int j=0;j<6;j++)
{ }//You can do whatever you want on original matrix here
Let's say that you want "transpose of matrix" and do some processing .Basically switch i and j
for( int j=0;j<6;j++) // replaceed i with j
for( int i=0;i<6;i++)
{ }//You can do whatever you want on transpose matrix here

Print a specific number on a weird table

I have a table which consists of nonnegative integers that are layed out in this manner: Each element in the table is the minimum value that does not appear to its left or above it. Here's an example of a 6x6 grid:
0 1 2 3 4 5
1 0 3 2 5 4
2 3 0 1 6 7
3 2 1 0 7 6
4 5 6 7 0 1
5 4 7 6 1 0
The first row and column begin with 0 1 2 3 4 5... In coordinates (x,x) is always a 0, as you can see. On each tile after that, you have to place the smallest positive number that doesn't already exist on the same row or column. Much like in a sudoku-puzzle: There cannot be a number twice on the same row and column.
Now I have to print the number in the given coordinates (y,x). For example [2, 5] = 5
I came up with a working solution, but it takes way too much memory and time, and I just know there's another way of doing this. My time limit is 1 second, and the coordinates I have to find the number at can go up to (1000000, 1000000).
Here's my code at the moment:
#include <iostream>
#include <vector>
int main()
{
int y, x, grid_size;
std::vector< std::vector<int> > grid;
std::cin >> y >> x; // input the coordinates we're looking for
grid.resize(y, std::vector<int>(x, 0)); // resize the vector and initialize every tile to 0
for(int i = 0; i < y; i++)
for(int j = 0; j < x; j++)
{
int num = 1;
if(i != j) { // to keep the zero-diagonal
for(int h = 0; h < y; h++)
for(int k = 0; k < x; k++) { // scan the current row and column
if(grid[h][j] == num || grid[i][k] == num) { // if we encounter the current num
num++; // on the same row or column, increment num
h = -1; // scan the same row and column again
break;
}
}
grid[i][j] = num; // assign the smallest number possible to the current tile
}
}
/*for(int i = 0; i < y; i++) { // print the grid
for(int j = 0; j < x; j++) // for debugging
std::cout << grid[i][j] << " "; // reasons
std::cout << std::endl;
}*/
std::cout << grid[y-1][x-1] << std::endl; // print the tile number at the requested coordinates
//system("pause");
return 0;
}
So what should I do? Is this easier than I think it is?
To summarize your question: You have a table where each element is the minimum nonnegative integer that does not appear to its left or above. You need to find the element at position (x,y).
The result is surprisingly simple: If x and y are 0-based, then the element at (x,y) is x XOR y. This matches the table you have posted. I have verified it experimentally for a 200x200 table.
The proof:
It's easy to see that the same number won't appear twice on the same row or column, because if x1^y = x2^y then necessarily x1=x2.
To see that x^y is minimal: Let a be a number smaller than x^y. Let i be the index (from the right) of the leftmost bit where a differs from x^y. The ith bit of a must be 0 and the ith bit of x^y must be 1.
Therefore, either x or y must have 0 in the ith bit. Suppose WLOG it was x that had 0. Represent x and y as:
x = A0B
y = C1D
Where A,B,C,D are sequences of bits, and B and D are i bits long. Since the leftmost bits of a are the same as those in x^y:
a^x = C0E
Where E is a sequence of i bits. So we can see that a^x < y. The value that appered in the (a^x)th row on the same column was: (a^x)^x = a. So the value a must have already appeared in the same row (or column, if it was y that had 0 in the ith bit). This is true for any value smaller than x^y, so x^y is indeed the minimum possible value.