Print a specific number on a weird table - c++

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.

Related

Traverse 2D Matrix diagonally omitting first row and first column

I am trying to traverse a 2D matrix diagonally and the function below prints all elements in a diagonal.I want to skip the first row and first column elements and start the diagonal traversal from matrix[1][1] because the values in the 0th row and 0th column are not required.So it is like slicing the matrix from the top and starting from [1][1] but not making any changes to the bottom of the matrix.
void diagonalOrder(int matrix[][COL])
{
for(int line = 1;
line <= (ROW + COL - 1);
line++)
{
int start_col = max(0, line - ROW);
int count = min(line, (COL - start_col), ROW);
/* Print elements of this line */
for(int j = 0; j < count; j++)
cout << setw(5) <<
matrix[minu(ROW, line) - j - 1][start_col + j];
cout << "\n";
}
I will update my question with an example to make it clear.Consider the following matrix.
0 1 2 3 4
matrix[5][5] = 1 8 5 3 1
2 4 5 7 1
3 6 4 3 2
4 3 4 5 6
The above function will print the values of this diagonally.
Output:
0
1 1
2 8 2
3 4 5 3
4 6 5 3 4
3 4 7 1
4 3 1
5 2
6
I want to skip the elements of the first row and the first column and starting at matrix[1][1] want to traverse the matrix diagonally.
Desired Output:
8
4 5
6 5 3
3 4 7 1
4 3 1
5 2
6
From your example it looks like you want to print antidiagonals not diagonals, ie third line is 3 4 5 3 not 3 5 4 3.
To get started keep things simple: Indices (i,j) along an antidiagonal are those i and j where i+j == some_constant. Hence this is a simple (not efficient) way to print elements along one antidiagonal:
void print_antidiagonal(int matrix[5][5],int x){
for (int i=4;i >= 0; --i) {
for (int j=0;j < 5; ++j) {
if (i+j == x) std::cout << matrix[i][j] << " ";
}
}
std::cout << "\n";
}
Further there are nrows + (ncols-1) antidiagonals, hence you can print them all via:
for (int i=0;i < 5+4; ++i) {
print_antidiagonal(matrix,i);
}
The function above isnt very efficient, but it is simple. It is obvious how to skip the first row and first column:
for (int i=4;i >= 1; --i) { // loop till 1 instead of 0
for (int j=1;j < 5; ++j) { // loop from 1 instead of 0
This is sufficient to produce desired output (https://godbolt.org/z/7KWjb7qh7). However, not only is the above rather inefficient, but also the code is not very clear about its intent. print_antidiagonal prints elements along a single anti-diagonal, hence iterating all matrix elements is a bad surprise.
I suggest to print the indices rather than the matrix elements to get a better picture of the pattern (https://godbolt.org/z/TnrbbY4jM):
1,1
2,1 1,2
3,1 2,2 1,3
4,1 3,2 2,3 1,4
4,2 3,3 2,4
4,3 3,4
4,4
Again, in each line i+j is a constant. And that constant increments by 1 in each line. In each line i decrements while j increments, until either i == 1 or j==4. The first element is such that i is maximum and j = constant - i.
Hence:
void print_antidiagonal(int matrix[5][5],int x){
int i = std::min(x-1,4);
int j = x - i;
while (i >= 1 && j <= 4) {
std::cout << matrix[i][j] << " ";
--i;
++j;
}
std::cout << "\n";
}
Live Example.
PS: I used hardcoded indices, because I considered it simpler to follow the logic. For a more realistic solution the matrix size and offset should be parametrized of course.
I don't really get what your code is trying to do but just going by the description you need to iterate over the array items with equal row and column indices until there either are no more rows or no more columns i.e.
void print_tail_of_diagonal(int matrix[ROWS][COLS])
{
int n = std::min(ROWS, COLS);
for (int i = 1; i < n; ++i) {
std::cout << matrix[i][i] << " ";
}
std::cout << "\n";
}

Biggest valued, 'H' shaped area in matrix?

I got the task where I must find the H shaped region which has the biggest sum of numbers in it. Under 'H' shaped region, tha task meant this, consisting of 7 elements and never changing:
x x
xxx
x x
The matrix's size must be 33 or bigger than that, and I don't have to work with rotated 'H' shape. However, it can move upwards and downwards if the matrix is that big (for example a 46 matrix).
I thought of first counting a "maximum" value, starting from the [0][0] element. However, I can't figure out how to move this region-counting along. Could you help me out, please?
Here's my code so far:
#include<iostream>
int main(){
int n = 3;
int m = 4;
int mtx[n][m] = {
1,1,1,3,
1,1,1,3,
1,1,1,3
};
//counting the maximum H value
int max = 0;
for(int i = 0; i < n; i++){
max += mtx[i][0];
}
for(int i = 0; i < n; i++){
max += mtx[i][2];
}
max += mtx[1][1];
int counter = 0;
int j = 0;
int k = 0;
//finding if there is bigger
while(counter >max){
//questioned area, not sure what to do here
if(counter < max){
max = counter;
}
}
return 0;
}
As mentioned in a comment, knowing the single maximum element in the matrix does not help to find the maximum H shape. A concrete counter example:
0 1 0 5
9 1 1 5
0 1 0 5
Maximum element is 9 but maximum sum H shape is
1 0 5
1 1 5
1 0 5
You would need to add more information to know whether the maximum element is part of the maximum H: Only if max_element + 6*min_element > 7*second_smallest_element you can be sure that max_element is part of the biggest sum H. This condition could be refined, but it cannot be made such that the biggest element is always part of the biggest sum H, because thats not true in general (see counter example above).
As suggested in another comment, you should write a function that given coordinates of the upper left corner calculates the sum of elements in the H shape:
#include <iostream>
#include <array>
int H_sum(const std::array<std::array<int,4>,3>& matrix, int x0,int y0){
// A E
// BDF
// C G
int sum = matrix[x0][y0]; // A
sum += matrix[x0+1][y0]; // B
sum += matrix[x0+2][y0]; // C
sum += matrix[x0+1][y0+1]; // D
sum += matrix[x0][y0+2]; // E
sum += matrix[x0+1][y0+2]; // F
sum += matrix[x0+2][y0+2]; // G
return sum;
}
int main() {
std::array<std::array<int,4>,3> mtx{
1,1,1,3,
1,1,1,3,
1,1,1,3
};
for (const auto& row : mtx){
for (const auto& e : row){
std::cout << e;
}
std::cout << "\n";
}
std::cout << H_sum(mtx,0,0);
}
This is of course only something to get you started. Next you have to carefully consider what are the maximum indices you can pass to H_sum without going out-of-bounds. Then write a nested loop to scan all positions of the H and remember the maximum value encountered.
Last but not least, what I described so far is a brute force approach. You calculate sum for all possible H shapes, remember the maximum, and are done. Maybe there is a clever trick to avoid adding all elements multiple times (for example in a larger matrix, the right leg of one H is the left leg of a different H). Though before applying such tricks and trying to be clever I strongly suggest to write something that is perhaps slow but correct, easy to read and verify.

Stuck with spiral triangle

I am looking for an algorithm that numbers and outputs a triangle with sides n (or half of a square) where n is an input of the program. But the numbering starts at the top of the triangle, goes down the diagonal, back along the bottom row and up the left edge. If there is an interior remaining it goes diagonally down from the highest number and continues.
Here is an example:
1
9 2
8 10 3
7 6 5 4
Here is my code and it results in:
1
10 2
9 8 3
7 6 5 4
Is there any algorithm for this of program if there any please explain to me.
The above program works well with row size less than 3 but doesn't for size above 3.
#include<iostream.h>
#include<conio.h>
void main()
{
int n,i,j,v=0;
static int k;
clrscr();
cout<<"Enter the number of rows : ";
cin>>n;
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++)
{
v++;
}
}
for(i=0;i<n;i++)
{
for(j=0;j<i;j++)
{
cout<<v;
cout<<"\t";
v--;
}
while(k==i)
{
k++;
cout<<k;
cout<<"\t";
}
cout<<"\n";
}
getch();
}
Here's a solution that doesn't use any array storage. The spiral can be thought of as a set of right angled triangles inside each other. The function iterates over all the rows and columns and for each position, it calculates what triangle the element is on by finding the closest distance to the edge of the outer triangle, then computes its adjusted position (x, y) relative to the top-left corner of that inner triangle, the number of rows of the inner triangle (r), and the start number of the inner triangle (start+1). Then it outputs a number based on whether it lies on the diagonal, horizontal or vertical side.
#include <iostream>
#include <iomanip>
using namespace std;
int main(void) {
int rows;
cout << "Enter the number of rows : ";
cin >> rows;
int i, j;
for(i = 0; i < rows; i++)
{
for(j = 0; j <= i; j++)
{
// find the closest side:
int distance = j; // distance to vertical side
if(i-j < distance)
distance = i-j; // distance to diagonal side
if((rows-1)-i < distance)
distance = (rows-1)-i; // distance to horizontal side
int r = rows - distance * 3;
// compute position on inner triangle:
int x = j - distance;
int y = i - distance * 2;
// compute start number for inner triangle:
int start = (((rows+1)*rows)/2) - (((r+1)*r)/2);
// output number based on side:
if(x==y) // diagonal side
cout << setw(2) << (start+y+1) << " ";
else if(y==(r-1)) // horizontal side
cout << setw(2) << (start+(r*2)-(x+1)) << " ";
else // vertical side
cout << setw(2) << (start+(r*3)-(y+2)) << " ";
}
cout << endl;
}
return 0;
}
Demo
Take the example where rows equals 7. In that case the distance value for each element will be:
(0)
0 0
0 (1) 0
0 1 1 0
0 1 (2) 1 0
0 1 1 1 1 0
0 0 0 0 0 0 0
All elements with the same distance value form a triangle. The number of rows of the outer triangle is 7, the next smaller one has 4, then 1. So r = rows - (distance * 3).
The top-left corner of the outer triangle is at row 0, column 0. The first inner triangle is row 2, column 1, the next one is at row 4, column 2. So the position of a given row/column position on the inner triangle that it lies on is found by subtracting distance * 2 from the row and distance from the column, so y = i - (distance *2) and x = j - distance.
The inner triangle column is stored in x. The inner triangle row is stored in y. In the example above, the values in brackets are the top-left corners of each triangle, where x = 0 and y = 0. For example for the top-left corner of the triangle with distance = 1, i = 2 and j = 1, so x = 1 - 1 = 0, and y = 2 - (1 * 2) = 0.
The start value is found by calculating the number of elements in the entire large triangle ((row+1)*row)/2 and then subtracting the number of elements remaining, which is the number of elements in the inner triangle.
For a triangle with n rows, the total number of elements is ((n+1)*n)/2, as shown below for rows = 5:
1 X 0 0 0 0 0
2 X X 0 0 0 0
3 X X X 0 0 0
4 X X X X 0 0
5 X X X X X 0
1 2 3 4 5 6
To count the number of X's, we can see that it's half the number of elements in a rectangle of (5+1)*5, so half of 30, which is 15.
If there are 2 triangles one inside the other, like this:
X
X X
X O X
X O O X
X X X X X
and we want to count the number of X's, then we can calculate the size of the entire triangle using the above formula to get 15, and then calculate the size of the inner triangle which has 2 rows as ((2+1)*2)/2 = 3, and subtracting the smaller from the larger gives 15 - 3 = 12. So if there are 12 X's, then the first O must be number 13. That's how we can calculate the number to output for the top-left corner of the inner triangle.
Once you've calculated all that it's just a matter of working out which side of the inner triangle the element is on and printing it out.
Here is a general idea as to how to solve this with recursion. There is probably a way to solve this in a space-efficient way, but I leave that for someone else. So let's say we store this as an array of arrays accessed by x[i][j] and let's say the size of sides of the triangle are n. You can google for how to dynamically create an array of arrays.
Now what we want is an equation for the outside of the triangle. Numbers along the diagonal are (i(i+1))/2 for 1 <= i <= n. Numbers along the left edge are 1+(i(i-1))/2 for 1 <= i <= n. And numbers along the bottom are 1+(n(n-1))/2 .. (n(n+1))/2.
So now to the recursion. Let j be the size of the remaining triangle yet to be numbered, k the highest number you've encountered before and (l,m) the index of the top of the triangle. Use the equations above and the preceding information to calculate the number and store that into the remaining triangle array. If there is yet another interior, recurse with the highest number and index of the top. And so on.
Example for side size 4. First number the outside. Highest prior number is 0. Index of the first position is (0,0)
1
9 2
8 x 3
7 6 5 4
We are not done because we still have an interior of size one. So when you recurse you, the position of the top of the triangle is (2,2), the highest number so far is 9 and the size of the triangle remaining is 1.
Now try with side size 5. After the first numbering we'd get:
1
12 2
11 x 3
10 x x 4
9 8 7 6 5
And the triangle remaining also starts at (2,2) as for side 4. But the size of the triangle remaining is now 2 and the highest number seen so far is 12.
After all the recursion is done, then print out of the table.
Easy way is to use an array.
#include <iostream>
using namespace std;
int main(){
int n;
cout <<"Enter the number of rows : ";
cin >> n;
int **tri = new int *[n];
for(int i=0; i<n; i++){
tri[i] = new int[i+1];
}
int v = 0, r = 0, c = 0;
for(int k = n-1; 0 <= k; k -=3){//k is total side size / 3, next k -2 -1
if(k==0){
tri[r][c] = ++v;
break;
}
for(int i = 0; i < k; ++i)//↘
tri[r++][c++] = ++v;
for(int i = 0; i < k; ++i)//←
tri[r][c--] = ++v;
for(int i = 0; i < k; ++i)//↑
tri[r--][c] = ++v;
r += 2; ++c;//next start position
}
//print
for(r = 0; r < n; ++r){
for(c = 0; c <= r; ++c)
cout << tri[r][c] << '\t';
cout << endl;
}
for(int i=0; i<n; i++){
delete[] tri[i];
}
delete[] tri;
}

In a matrix put 0 in the row and column of a cell which contains 0 without using extra space

Given a matrix, if a cell contains 0, then we have make entire row and column corresponding to the cell as 0. For example, if
1 2 3
M = 0 4 5
4 2 0
then the output should be
0 2 0
0 0 0
0 0 0
The method I thought is as follows
Make auxiliary arrays row[] and col[]. If a cell(i,j) contains 0 then, mark row[i] and col[j] as 0.(Initially row[] and col[] contains all 1s).
Again traverse the whole matrix, if for cell(i,j), either of row[i] or col[j] is 0, then put cell(i,j) as 0.
This takes O(m*n) time and O(m+n) space.
How to optimize it further specially in terms of space.Any suggestions for improving time complexity are also welcomed.
Aha, this is an old question.
Use one boolean variate(isZeroInFirstRow) saving if first row has zero element(s) or not and one boolean variate(isZeroInFirstCol) saving if first column has zero element(s) or not.
Then, traverse the whole matrix. If cell(i,j)==0, then set cell(0,j) and cell(i,0) to 0.
Traverse the first row of the matrix. If cell(0,j)==0, then set all elements in column(j) to 0.
Traverse the first column of the matrix. If cell(i,0)==0, then set all elements in row(i) to 0.
If isZeroInFirstRow==true, set all elements in row(0) to 0.
If isZeroInFirstCol==true, set all elements in column(0) to 0.
You can solve this in O(1) space. One solution is to iterate on the matrix, for each 0 you see, you fill the corresponding row/col with some character, 'X' for example.
When you finish, you should have something like that:
X 2 X
M= 0 X X
X X 0
Then you iterate again on the matrix and replace each 'X' with 0 to get:
0 2 0
M= 0 0 0
0 0 0
If you are concerned with storage you may think of using some sparse matrix storage formats to store the resulting matrix, and then free the original dense input.
An example of what I am proposing may be the following (implementing COO format) which should take O(M*N) time:
#include<vector>
#include<iostream>
#include<algorithm>
#include<cstddef>
using namespace std;
int main()
{
constexpr size_t M = 3;
constexpr size_t N = 3;
int matrix[M][N] = {
{1, 2, 3},
{0, 4, 5},
{4, 2, 0}
};
vector<size_t> markedRows;
vector<size_t> markedColumns;
// Search for zeroes
for (size_t ii = 0; ii < M; ++ii) {
for(size_t jj = 0; jj < N; ++jj) {
if (matrix[ii][jj] == 0) {
markedRows.push_back (ii);
markedColumns.push_back(jj);
}
}
}
// Sort columns (rows are ordered by construction)
sort(markedColumns.begin(),markedColumns.end());
// Eliminate duplicates
markedRows.erase (unique(markedRows.begin() ,markedRows.end()) ,markedRows.end() );
markedColumns.erase(unique(markedColumns.begin(),markedColumns.end()),markedColumns.end());
// Construct COO matrix format
vector<size_t> irow;
vector<size_t> icol;
vector<int> val;
for (size_t ii = 0; ii < M; ++ii) {
for(size_t jj = 0; jj < N; ++jj) {
if ( ( find(markedRows.begin() ,markedRows.end() ,ii) == markedRows.end() ) &&
( find(markedColumns.begin(),markedColumns.end(),jj) == markedColumns.end() )
) {
irow.push_back(ii);
icol.push_back(jj);
val.push_back (matrix[ii][jj]);
}
}
}
// FROM HERE YOU NO LONGER NEED MATRIX, AND YOU CAN FREE THE STORAGE
// Print non zero entries
for( size_t ii = 0; ii < irow.size(); ++ii) {
cout << "A["<<irow[ii]<<","<<icol[ii]<<"] = "<<val[ii]<<endl;
}
return 0;
}
You can use your algorithm without allocating and auxiliary row or column by searching the matirx for a row that contains no zeros and a column that contains no zero elements.
If either of these searches fails, then the resulting matrix will all zeros, so your work is done by simply setting all elements to zero.
Otherwise, use the row and colum you found as the bookkeeping row and column you mentioned, setting the corresponding element to zero as you find zeros in the remainder of the matrix. Once that pass is done you walk the bookkeeping row, setting the matix columns to zeros for any zero found in the bookkeeping row, similarly for the aux column.
Here is an algorithm can do it in O(M*N) time and O(1) space : -
Find the max element in the matrix .
Mat[i][j] = max - Mat[i][j] for all (i,j)
Notice that Mat[i][j] will only have positive values.
Use negetive values as sentinels and Mat[i][j] = max as zeros.
Retrieve original values as Mat[i][j] = max - Mat[i][j]
Simple and easy answer:
<2 nested loop> to search through all columns and rows you find any cell = 0 through all column and set it to zeros through all row and set it to zeros. let me know if it not clear to record video for it.
Int main()
{
//example matrix dimension rows(r=6) * columns (c=3)
int r = 6;
int c = 3;
int matrix[r][c];
for(int i=0; i<r; ++i){
for(int j=0 ; j < c ; ++j){
if(matrix[i][j] == 0){
for(int ii=0; ii<r; ++ii){
Matrix[ii][j] = 0 ;
}
for(int jj=0; jj<c; ++jj){
Matrix[i][jj] = 0 ;
}
}
}
}
}

Getting specific elements in a vector

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.