Array 2D to 1D conversion and confusion - c

I am confused to convert a 2D array into 1D array.
I want to write a neighboring 8 elements for "a11" (which is at (1,1)) in the form of width ,rows and cols format without using for loop.
|<--Width--->|
cols
____________
| a00 a01 a02
rows | a10 a11 a12
| a20 a21 a22
I tried in this way :
a00 = pSrc[(cols-1)+ (rows - 1)*width];
a02 = pSrc[(cols-1)+ (rows + 1)*width];
a10 = pSrc[cols+ (rows -1)*width];
a12 = pSrc[cols+ (rows +1)*width];
a20 = pSrc[(cols+1)+ (rows - 1)*width];
a22 = pSrc[(cols+1)+ (rows + 1)*width];
a01 = pSrc[(cols-1)+ (rows )*width];
a21 = pSrc[(cols+1)+ (rows )*width];
But I think I did some mistake .Can any one help me in that .

It isn't clear how pSrc is defined since you don't show its definition. However, your code is consistent with it being declared as a 1D array:
int pSrc[9]; // Or a larger dimension
Your code can sensibly be written so it is more uniformly laid out:
a00 = pSrc[(cols-1) + (rows-1)*width];
a01 = pSrc[(cols-1) + (rows+0)*width];
a02 = pSrc[(cols-1) + (rows+1)*width];
a10 = pSrc[(cols+0) + (rows-1)*width];
a12 = pSrc[(cols+0) + (rows+1)*width];
a20 = pSrc[(cols+1) + (rows-1)*width];
a21 = pSrc[(cols+1) + (rows+0)*width];
a22 = pSrc[(cols+1) + (rows+1)*width];
The +0 will be ignored by even the most simple-minded compiler, almost certainly without even turning the optimizer on, but it makes the code much easier to read. I also resequenced the entries so the row above are listed first, then the row in the middle, and then the bottom row. Again, it makes it easier to see the patterns.
It is then clear that you are using 'rows' and 'cols' backwards. You actually need:
a00 = pSrc[(cols-1) + (rows-1)*width];
a01 = pSrc[(cols+0) + (rows-1)*width];
a02 = pSrc[(cols+1) + (rows-1)*width];
a10 = pSrc[(cols-1) + (rows+0)*width];
a12 = pSrc[(cols+1) + (rows+0)*width];
a20 = pSrc[(cols-1) + (rows+1)*width];
a21 = pSrc[(cols+0) + (rows+1)*width];
a22 = pSrc[(cols+1) + (rows+1)*width];

Related

Karatsuba Algorithm: splitting strings

I am trying to implement the Karatsuba algorithm in C.
I work with char strings (which are digits in a certain base), and although I think I have understood most of the Karatsuba algorithm, I do not get where I should split the strings to multiply.
For example, where should I cut 123 * 123, and where should I cut 123 * 12?
I can't get to a solution that works with both these calculations.
I tried to cut it in half and flooring the result when the number if odd, but it did not work, and ceiling does not work too.
Any clue?
Let a, b, c, and d be the parts of the strings.
Let's try with 123 * 12
First try (a = 1, b = 23, c = 1, d = 2) (fail)
z0 = a * c = 1
z1 = b * d = 46
z2 = (a + b) * (c + d) - z0 - z1 = 24 * 3 - 1 - 46 = 72 - 1 - 46 = 25
z0_padded = 100
z2_padded = 250
z0_padded + z1 + z2_padded = 100 + 46 + 250 = 396 != 123 * 12
Second try (a = 12, b = 3, c = 12, d = 0) (fail)
z0 = 144
z1 = 0
z2 = 15 * 12 - z1 - z0 = 180 - 144 = 36
z0_padded = 14400
z2_padded = 360
z0_padded + z1 + z2_padded = 14760 != 1476
Third try (a = 12, b = 3, c = 0, d = 12) (success)
z0 = 0
z1 = 36
z2 = 15 * 12 - z0 - z1 = 144
z0_padded = 0
z2_padded = 1440
z0_padded + z1 + z2_padded = 1476 == 1476
Let's try with 123 * 123
First try (a = 1, b = 23, c = 1, d = 23) (fail)
z0 = 1
z1 = 23 * 23 = 529
z2 = 24 * 24 - z0 - z1 = 46
z0_padded = 100
z2_padded = 460
z0_padded + z1 + z2_padded = 561 != 15129
Second try (a = 12, b = 3, c = 12, d = 3) (success)
z0 = 12 * 12 = 144
z1 = 3 * 3 = 9
z2 = 15 * 15 - z0 - z1 = 72
z0_padded = 14400
z2_padded = 720
z0_padded + z1 + z2_padded = 15129 == 15129
Third try (a = 12, b = 3, c = 1, d = 23) (fail)
z0 = 12
z1 = 3 * 23 = 69
z2 = 15 * 24 - z0 - z1 = 279
z0_padded = 1200
z2_padded = 2799
z0_padded + z1 = z2_padded = 4068 != 15129
Here, I do not get where I messed this up. Note that my padding method adds n zeroes at the end of a number where n = m * 2 and m equals the size of the longest string divided by two.
EDIT
Now that I have understood that b and d must be of the same length, it works almost everytime, but there are still exceptions: for example 1234*12
a = 123
b = 4
c = 1
d = 2
z0 = 123
z1 = 8
z2 = 127 * 3 - 123 - 8 = 250
z0_padded = 1230000
z2_padded = 25000
z0_padded + z1 + z2_padded = 1255008 != 14808
Here, assuming I split the strings correctly, the problem is the padding, but I do not get how I should pad. I read on Wikipedia that I should pad depending on the size of the biggest string (see a few lines up), there should be another solution.
The Karatsuba algorithm is a nice way to perform multiplications.
If you want it to work, b and d must be of the same length.
Here are two possibilities to compute 123x12 :
a= 1;b=23;c=0;d=12;
a=12;b= 3;c=1;d= 2;
Let's explain how it works for the second case :
123=12×10+3
12= 1×10+2
123×12=(12×10+3)×(1×10+2)
123×12=12×1×100+ (12×2+3×1)×10+3×2
123×12=12×1×100+((12+3)×(1+2)-12×1-3×2)×10+3×2
Let's explain how it works for the first case :
123=1×100+23
12=0×100+12
123×12=(1×100+23)×(0×100+12)
123×12=1×0×10000+ (1×12+23×0)×100+23×12
123×12=1×0×10000+((1+23)×(0+12)-1×0-23×12)×100+23×12
It also works with 10^k, 2^k or n instead of 10 or 100.

stack representation of multidimensional array

Can some explain me the row & column wise representation of a 2 dimensional array in stack? My teacher told that if we have following matrix:
a00 a01 a02
a10 a11 a12
a20 a21 a22
Column wise representation: Row Wise representation:
a00 a00
a10 a01
a20 a02
a01 a10
a11 a11
a21 a12
a02 a20
a12 a21
a22 a22
Whereas i only know about the representation of multidimensional array in memory:
a00 then a01 then a02 then a10 and so on(there increasing order of addresses)
I raised this question in class what is the difference b/w stack representation & memory representation of multidimensional arrays. She said we are doing 2-D array here not pointer. What kind of answer is that. Please explain me this.
She also told some formulae to calculate the address of any element of 2-D array of row representation and column representation in stack. I didn't understand it.
Location(A[j,k]) = Base_address(A) + W(M(k-1)+(j-1))
You said,
Whereas i only know about the representation of multidimentional array in memory: a00 then a01 then a02 then a10 and so on(there increasing order of addresses)
In C/C++, multidimensional arrays are stored using the row representation.
IIRC, in FORTRAN, multidimensional arrays are stored using the column representation.
In C, you can define a 2D array as:
int a[10][3];
When you pass the array to a function, it decays to a pointer of type int (*)[3].
Disclaimer: My FORTRAN is rusty, so pardon any use of incorrect syntax
In FORTRAN, you can define a 2D array as:
INTEGER A(10, 3)
When you pass the array to a function, it the argument type in the function looks like
INTEGER A(10, *)
The differences in the syntax makes it more natural for multidimensional arrays in C to be represented by rows while in FORTRAN it seems natural for them to be represented by columns.
You also said:
Location(A[j,k]) = Base_address(A) + W(M(k-1)+(j-1))
It seems you are using 1-based index. Not sure what W and M stand for.
Let's say you have ROW number of rows and COL number of columns.
If you have row representation:
Location(A[j,k]) = Base_address(A) + (j-1)*COL + (k-1)
If you have column representation:
Location(A[j,k]) = Base_address(A) + (k-1)*ROW + (j-1)
Here's a better representation of your 2D array in the RAM:
Column wise representation:
Chip1 Chip2 Chip3
a00 a01 a02
a10 a11 a12
a20 a21 a22
Row Wise representation:
Chip1 Chip2 Chip3
a00 a10 a20
a01 a11 a21
a02 a12 a22

Reduce the Average difference

Two arrays A,B are given of same length (not sorted).
Make pairs of their entries (one from A and one from B), such that average difference in the entries (|a1-b1|,|a2-b2|,....) is minimum.
I have thought of sorting them and then making pairs of same index entries.
Will this work ?
If yes, how ? else some other solution with proof.
I'm assuming that this problem can be formally stated as follows: given two n-element vectors A and B, find permutations A' of A and B' of B so as to minimize the L1 norm of A' - B'.
If so, then your proposed algorithm is correct. Suppose that we have a solution with an inversion, that is, a1 matched with b2 and a2 matched with b1 such that a1 < a2 and b1 < b2. The contribution of these pairs to the L1 norm is
|a1 - b2| + |a2 - b1| >= |a1 - b1| + |a2 - b2|,
where the inequality follows from an inelegant case argument that we defer for the moment. Accordingly, by rematching a1 with b1 and a2 with b2, we decrease the number of inversions without increasing the cost. It follows by induction that the matching with no inversions is optimal.
Case argument: symmetrically (by interchanging A and B), there are three possible interleavings.
(1) a1 <= a2 <= b1 <= b2
(2) a1 <= b1 <= a2 <= b2
(3) a1 <= b1 <= b2 <= a2
In case (1),
|a1 - b2| + |a2 - b1| = b2 - a1 + b1 - a2
= b1 - a1 + b2 - a2
= |a1 - b1| + |a2 - b2|.
In case (2),
|a1 - b2| + |a2 - b1| = b2 - a1 + a2 - b1
>= b2 - a1 + a2 - b1 - 2 (a2 - b1)
= b1 - a1 + b2 - a2
= |a1 - b1| + |a2 - b2|.
In case (3),
|a1 - b2| + |a2 - b1| = b2 - a1 + a2 - b1
>= b2 - a1 + a2 - b1 - 2 (b2 - b1)
= b1 - a1 + a2 - b2
= |a1 - b1| + |a2 - b2|.
Edit: misread the question, the below describes why the sum of differences is maximized when you sort the two lists in opposite order
Here is another way to see that the algorithm you described gives you the optimal solution. Note that when you write out |x - y| it equals either x - y or y - x. Thus,
|a_1 - b_1| + |a_2 - b_2| + ... + |a_n - b_n|
can be thought of as summing the numbers a_1, ..., a_n, b_1, ... , b_n, except that exactly n of them have their sign flipped. Clearly, this is maximized when you choose to negate the n smallest numbers out of a_1, ..., a_n, b_1, ..., b_n. And indeed, that is exactly what your algorithm does.

why only column size works but only row size does not works in 2-d array initialisation?

this works
int a[][2]={
{2,4},
{6,8}
};
but this shows error
int a[2][]={
{2,4},
{6,8}
};
why giving only column size shows no error but giving only row size gives error?
In C, you can omit only the length of first dimension. For 1D array, you can do as
int oneD_array[2] = {1,2};
or
int oneD_array[] = {1,2};
In case of 2D array, both of
int twoD_array[2][2] = { {2,4}, {6,8} };
and
int twoD_array[][2] = { {2,4}, {6,8} };
is valid.
But the above declaration is valid only if the initializer is present. Otherwise it would through error.
The compiler uses length of the initializer to determine how long is the array. But the length of the column can't be determined this way. Without knowing the length of the array, compiler is not able to calculate the address of its corresponding elements. By knowing the length of rows and column, compiler calculate the address of its elements using array equation:
address(array) = address(first element) + (row number * columns + column number)*sizeof)type)
Detailed look on array equation:
A 2D array in C is treated as a 1D array whose elements are 1D arrays (the rows).
For example, a 4x3 array of T (where T is some data type) may be declared by: T mat[4][3], and described by the following scheme:
+-----+-----+-----+
mat == mat[0] ---> | a00 | a01 | a02 |
+-----+-----+-----+
+-----+-----+-----+
mat[1] ---> | a10 | a11 | a12 |
+-----+-----+-----+
+-----+-----+-----+
mat[2] ---> | a20 | a21 | a22 |
+-----+-----+-----+
+-----+-----+-----+
mat[3] ---> | a30 | a31 | a32 |
+-----+-----+-----+
The array elements are stored in memory row after row, so the array equation for element mat[m][n] of type T is:
address(mat[i][j]) = address(mat[0][0]) + (i * n + j) * size(T)
address(mat[i][j]) = address(mat[0][0]) +
i * n * size(T) +
j * size(T)
address(mat[i][j]) = address(mat[0][0]) +
i * size(row of T) +
j * size(T)
The compiler has to convert the array into a linear structure (i.e. memory addresses). It does this by multiplying the row number by the width of the column then add the column number you are interested in. You can note that this calculation requires the width (number of columns) needs to be known. The compiler is able to count the number of rows.
So memory address = row number * number of columns + column number you are interested in. Cannot get away from the fact that number of columns is a compile time requirement

How to make my matrix array become like this?

I have a matrix like this:
A = 1 2 3
4 5 6
7 8 9
My question is how I want to make my matrix to be like this:
A11 = 1
A12 = 2
A13 = 3
A21 = 4
A22 = 5
A23 = 6
A31 = 7
A32 = 8
A33 = 9
Because i have to multiply A21 with A22 which is 4x5=20.
Your question is not clear to me.
To create the matrix, use ',' (or nothing) to delimit columns, ';' to delimit rows.
A = [1 2 3 ; 4 5 6 ; 7 8 9];
To access the matrix, you can use a 1-dimensional index as well as a 2-dimensional index.
E.g. A21 is A(2, 1) as well as A(0*3+2).
If you actually need variables such as 'A11', 'A12' etc. you could do as follows:
A = [1 2 3; 4 5 6; 7 8 9];
for i = 1:size(A,1)
for j = 1:size(A,2)
eval(sprintf('A%d%d = %f;',i,j,A(i,j)));
end
end
A21 * A22
# will result in 20
Maybe not the best way, but it will create the variables for you.

Resources