Loop diagonally through 2D array in one loop - c++

How would one traverse an entire 2D array in one loop
e.g.
I want to push_back the diagonal elements into a buffer to process: 2 to 2, 3 to 3, 4 to 4
I have tried doing it in two separate loops but I can't process them together afterwards.
Example 2D array:
0 1 2 3 4 5 6
1 * * * * * *
2 * * * * * *
3 * * * * * *
4 * * * * * *
5 * * * * * *
6 * * * * * *
So, the buffer for (0,1) to (1,0) would be: one star from the grid
buffer for (0,2) to (2,0): two stars
buffer for (0,3) to (3,0): three stars
and so on...
note the buffer is a string.

If you want to get all the diagonal elements, the for loop would look something like this:
for(unsigned int i=0;i<yourArrayWidth;i++)
yourSum += yourArray[i][i];
if you want the numbers from top-left to bottom-right (so "\"), or:
for(unsigned int i=0;i<yourArrayWidth;i++)
yourSum += yourArray[yourArrayWidth-i][i];
if you want the numbers from top-right to bottom-left (so "/").
Where:
yourSum is some buffer you initialize before the traversing.
yourArrayWidth is the width of the array.
yourArray is the 2D array in your example, starting at [0][0].

For an array of M rows and N columns, you would have num=N+M-1 diagonals, which can each be obtained through:
int num = N+M-1;
int len = 1;
std::vector<std::string> res;
for (int i=0; i<num; ++i)
{
int startRow = std::min(i, M-1);
int startCol = i-startRow;
int len = std::min(startRow, N-1-startCol) + 1;
std::string str(len, '\0');
for (int j=0; j<len; ++j)
{
str[j] = arr[startRow-j][startCol+j];
}
res.push_back(str);
}
with i=0 being the "/" diagonal at the top-left, and i=N+M-1 being the diagonal at the bottom-right.

Related

How to convert triangular matrix indexes in to row, column coordinates?

I have these indexes:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,etc...
Which are indexes of nodes in a matrix (including diagonal elements):
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
etc...
and I need to get i,j coordinates from these indexes:
1,1
2,1 2,2
3,1 3,2 3,3
4,1 4,2 4,3 4,4
5,1 5,2 5,3 5,4 5,5
6,1 6,2 6,3 6,4 6,5 6,6
etc...
When I need to calculate coordinates I have only one index and cannot access others.
Not optimized at all :
int j = idx;
int i = 1;
while(j > i) {
j -= i++;
}
Optimized :
int i = std::ceil(std::sqrt(2 * idx + 0.25) - 0.5);
int j = idx - (i-1) * i / 2;
And here is the demonstration:
You're looking for i such that :
sumRange(1, i-1) < idx && idx <= sumRange(1, i)
when sumRange(min, max) sum integers between min and max, both inxluded.
But since you know that :
sumRange(1, i) = i * (i + 1) / 2
Then you have :
idx <= i * (i+1) / 2
=> 2 * idx <= i * (i+1)
=> 2 * idx <= i² + i + 1/4 - 1/4
=> 2 * idx + 1/4 <= (i + 1/2)²
=> sqrt(2 * idx + 1/4) - 1/2 <= i
In my case (a CUDA kernel implemented in standard C), I use zero-based indexing (and I want to exclude the diagonal) so I needed to make a few adjustments:
// idx is still one-based
unsigned long int idx = blockIdx.x * blockDim.x + threadIdx.x + 1; // CUDA kernel launch parameters
// but the coordinates are now zero-based
unsigned long int x = ceil(sqrt((2.0 * idx) + 0.25) - 0.5);
unsigned long int y = idx - (x - 1) * x / 2 - 1;
Which results in:
[0]: (1, 0)
[1]: (2, 0)
[2]: (2, 1)
[3]: (3, 0)
[4]: (3, 1)
[5]: (3, 2)
I also re-derived the formula of Flórez-Rueda y Moreno 2001 and arrived at:
unsigned long int x = floor(sqrt(2.0 * pos + 0.25) + 0.5);
CUDA Note: I tried everything I could think of to avoid using double-precision math, but the single-precision sqrt function in CUDA is simply not precise enough to convert positions greater than 121 million or so to x, y coordinates (when using 1,024 threads per block and indexing only along 1 block dimension). Some articles have employed a "correction" to bump the result in a particular direction, but this inevitably falls apart at a certain point.

How do I convert this recursion into iterative DP?

I am trying to solve this problem :TRT.
Here is what I have done so far:
I designed a recursion for given problem and used memoization to get the solution accepted.
int recur(int l,int r,int level)
{
if(l==r)
return level*a[l];
if(dp[l][r])
return dp[l][r];
return dp[l][r]=max(level*a[l]+recur(l+1,r,level+1),level*a[r]+recur(l,r-1,level+1));
}
I am trying to solve this problem by bottom up dynamic programming but I can't think of the approach, this happens with most of the dynamic programming problems I am solving , I am able to design the recursion but fail at building the iterative dp. Can someone please help me with the approach to iterative dp solution once I have figured out the recursion ?
Edit: My bottom up DP solution based on Tempux's explanation:
int solve()
{
REP(i,n)
{
dp[i][i]=n*a[i];
}
REPP(i,1,n)
{
for(int j=0;j+i<n;j++)
{
dp[j][j+i]=max((n-i)*a[j]+dp[j+1][j+i],(n-i)*a[j+i]+dp[j][j+i-1]);
}
}
return dp[0][n-1];
}
Generally you just have to fill the values that are independent first (base cases). Then fill the values that are dependent on the values you have filled before.
In this case when l==r you have an independent value. So you just fill these first: [0][0] [1][1] [2][2] ... [n-1][n-1].
Now you can see that value of [l][r] is dependent on [l+1][r] and [l][r-1]. So now you can fill the values of [0][1] [1][2] [2][3] ... [n][n-1].
[0][1] is dependent on [0][0] and [1][1] which you have filled before
[1][2] is dependent on [1][1] and [2][2] which you have filled before
....
So now you recognize a pattern. You can fill the whole table if you proceed diagonally.
0 * * * * 0 1 * * * 0 1 2 * * 0 1 2 3 *
* 0 * * * * 0 1 * * * 0 1 2 * * 0 1 2 3
* * 0 * * * * 0 1 * * * 0 1 2 * * 0 1 2
* * * 0 * * * * 0 1 * * * 0 1 * * * 0 1
* * * * 0 * * * * 0 * * * * 0 * * * * 0
Here is one possible implementation:
for ( int d=0; d<=n-1; ++d ){
for ( int l=0; l<=n-1; ++l ){
int r = l+d;
if ( r >= n )
break;
int level = n-(r-l);
if ( l==r ){
dp[l][r] = level*v[l];
} else {
dp[l][r] = max( level*v[l] + dp[l+1][r],
level*v[r] + dp[l][r-1] );
}
}
}

How do I draw a diagonal line of one character using nested while loops in Python code?

I need to write a program that will output a diagonal line using nested while loops.
It should look like this:
*
*
*
*
*
I know how to draw a square:
row = 1
while row <= size:
col = 1
while col <= size:
print chr,
col = col + 1
print ''
row = row + 1
print ''
which outputs:
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
but I cant seem to wrap my head around the diagonal line.
If someone could help it would be greatly appreciated.
The code has to use while loops though.
You're actually pretty close:
size = 4
row = 1
while row <= size:
col = 1
while col < row:
print ' ',
col = col + 1
print '*'
row = row + 1 # simplify to `row += 1`
The trick here is that in the inner loop, you print spaces (not the character) until you've printed 1 less space than the row number that you're on. Then you break out of the loop, print your character and newline and then continue.
In method, just pass it how long you want the line to be:
def diagonalLine( size ):
row = 1
while row <= size:
col = 1
while col <= size:
print ' ',
col += 1
print '*'

OpenGl glTexImage2D data

I am trying to read floatingpoint numbers from a CSV file, that contains a precomputed texture, store it in a 1 dimensional array, and then put that read data into a 2 dimensional texture.
I need to make sure the following code does that, because i have problems accessing the data and I cannot figure out where the error is:
// Allocate memory
float * image = new float [width * height * 3 ];
for( int i = 0; i < height; i++)
{
for( int j = 0; j < width-1; j++)
{
fscanf( fDataFile, "%f,", &fData );
image[ 4 * i * j + 0 ] = fData;
image[ 4 * i * j + 1 ] = fData;
image[ 4 * i * j + 2 ] = fData;
}
fscanf( fDataFile, "%f", &fData );
image[ 4 * i * width-1 + 0 ] = fData;
image[ 4 * i * width-1 + 1 ] = fData;
image[ 4 * i * width-1 + 2 ] = fData;
}
There shouldn't be a problem here, but what troubles me is the following:
// create the texture
glGenTextures(1, &texHandle);
glBindTexture(GL_TEXTURE_2D, texHandle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, &image[0]);
Is it okay to just give glTexImage2D the pointer to my onedimensional array?
the size of the array is width*height*3 and the texture's format should be width*height with 3 channels... so the size should be okay i guess?!
Still my program won't work as expected and this is one potential source for an error.
I solved my messed up texture reading. I don't know what got into me but the initilization of my array was pure nonesense. Here is the corrected code, I found out when trying to write a test texture:
// Allocate memory
float * image = new float [width * height * 3 ];
for( int i = 0; i < height; i++)
{
for( int j = 0; j < width-1; j++)
{
fscanf( fDataFile, "%f,", &fData );
image[ 3 * (i * width + j) + 0 ] = fData;
image[ 3 * (i * width + j) + 1 ] = fData;
image[ 3 * (i * width + j) + 2 ] = fData;
//image[ 4 * i * j + 2 ] = 1.0f;
}
fscanf( fDataFile, "%f", &fData );
image[ 3 * (i * width + width-1) + 0 ] = fData;
image[ 3 * (i * width + width-1) + 1 ] = fData;
image[ 3 * (i * width + width-1) + 2 ] = fData;
//image[ 4 * i * width-1 + 2 ] = 1;
}
Furthermore it would work now independent of the internal format. GL_RGB, GL_RGBA, GL_RGB32F and GL_RGBA32F all work fine without changing the way I read my texture.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, &image[0]);
You should be using a floating-point internal format. For example, GL_RGB32F. That should be the third parameter.

Sum of submatrices of bigger matrix

I have a big matrix as input, and I have the size of a smaller matrix. I have to compute the sum of all possible smaller matrices which can be formed out of the bigger matrix.
Example.
Input matrix size: 4 × 4
Matrix:
1 2 3 4
5 6 7 8
9 9 0 0
0 0 9 9
Input smaller matrix size: 3 × 3 (not necessarily a square)
Smaller matrices possible:
1 2 3
5 6 7
9 9 0
5 6 7
9 9 0
0 0 9
2 3 4
6 7 8
9 0 0
6 7 8
9 0 0
0 9 9
Their sum, final output
14 18 22
29 22 15
18 18 18
I did this:
int** matrix_sum(int **M, int n, int r, int c)
{
int **res = new int*[r];
for(int i=0 ; i<r ; i++) {
res[i] = new int[c];
memset(res[i], 0, sizeof(int)*c);
}
for(int i=0 ; i<=n-r ; i++)
for(int j=0 ; j<=n-c ; j++)
for(int k=i ; k<i+r ; k++)
for(int l=j ; l<j+c ; l++)
res[k-i][l-j] += M[k][l];
return res;
}
I guess this is too slow, can anyone please suggest a faster way?
Your current algorithm is O((m - p) * (n - q) * p * q). The worst case is when p = m / 2 and q = n / 2.
The algorithm I'm going to describe will be O(m * n + p * q), which will be O(m * n) regardless of p and q.
The algorithm consists of 2 steps.
Let the input matrix A's size be m x n and the size of the window matrix being p x q.
First, you will create a precomputed matrix B of the same size as the input matrix. Each element of the precomputed matrix B contains the sum of all the elements in the sub-matrix, whose top-left element is at coordinate (1, 1) of the original matrix, and the bottom-right element is at the same coordinate as the element that we are computing.
B[i, j] = Sum[k = 1..i, l = 1..j]( A[k, l] ) for all 1 <= i <= m, 1 <= j <= n
This can be done in O(m * n), by using this relation to compute each element in O(1):
B[i, j] = B[i - 1, j] + Sum[k = 1..j-1]( A[i, k] ) + A[j] for all 2 <= i <= m, 1 <= j <= n
B[i - 1, j], which is everything of the sub-matrix we are computing except the current row, has been computed previously. You keep a prefix sum of the current row, so that you can use it to quickly compute the sum of the current row.
This is another way to compute B[i, j] in O(1), using the property of the 2D prefix sum:
B[i, j] = B[i - 1, j] + B[i, j - 1] - B[i - 1, j - 1] + A[j] for all 1 <= i <= m, 1 <= j <= n and invalid entry = 0
Then, the second step is to compute the result matrix S whose size is p x q. If you make some observation, S[i, j] is the sum of all elements in the matrix size (m - p + 1) * (n - q + 1), whose top-left coordinate is (i, j) and bottom-right is (i + m - p + 1, j + n - q + 1).
Using the precomputed matrix B, you can compute the sum of any sub-matrix in O(1). Apply this to compute the result matrix S:
SubMatrixSum(top-left = (x1, y1), bottom-right = (x2, y2))
= B[x2, y2] - B[x1 - 1, y2] - B[x2, y1 - 1] + B[x1 - 1, y1 - 1]
Therefore, the complexity of the second step will be O(p * q).
The final complexity is as mentioned above, O(m * n), since p <= m and q <= n.