Formula needed: Sort array to array-"zig-zag" - arrays

I have the following array:
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
I use it for some visual stuff like this:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now I want to sort the array like this to have a "zig-zag" when rendering later.
// rearrange the array according to this schema
1 3 6 10
2 5 9 13
4 8 12 15
7 11 14 16
// the original array should look like this:
a = [1,5,2,9,6,3,13,10,7,4,14,11,8,15,12,16]
// the second index to draw should be the first index in the second row,
// which is represent by 5 in the original 1D Array
Yeah, now I'm looking for a smart formula to do that
ticker = 0;
rows = 4; // can be n
cols = 4; // can be n
originalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
newArray = [];
while(ticker < originalArray.length)
{
//do the magic here
ticker++;
}

You can leave it sorted in the original order, you just have to step through it differently. EDIT: Turns out that my naive implementation didn't account for the differing step size based on the diagonal. The code below does and has been tested in C#.
var diagonals = new [] { 1, 2, 3, 4, 4, 3, 2, 1 };
for (int i = 0, m = 0; m < 4; i = i + m, ++m) {
for (int j = m, k = 0; k < 4; j = j + diagonals[m+k+1], ++k) {
Console.Write( i+j+1 );
Console.Write( " " );
}
Console.WriteLine();
}
Obviously, you could use this algorithm to fill a new array if you needed to keep that ordering around. It should also scale -- you just need to change the termination conditions to the square root of the array size and automate the generation of the diagonals.

Look at the structure of your matrix:
1 3
| / /
| / /
|/ / ...
2 / 5
/ /
/ /
4
The 1st row starts at 1
The 2nd row starts at 2 = 1 + 1 (# elements in 1st zig)
The 3rd row starts at 4 = 1
+ 1 (# elements in 1st zig)
+ 2 (# elements in 2nd zig)
...
The 3rd row ends at 6 = start of 3rd row + row num
= 4 + 3 = 7
You can derive a closed form formula for the ith row and go ahead.

Related

How to create a Sudoku grid with the following pattern in C without arrays?

I have to create a Sudoku grid with the following pattern in C:
1 2 3 4
3 4 1 2
2 3 4 1
4 1 2 3
The first number in the top left corner (here: 1) must be an editable variable for a start value. There is another variable to create the grid with by the square size, in this example the square size is 2 and the 1 2 3 4 are in one square. 3 4 1 2 are in another square and so on...
If the start value is e.g. 3, the grid looks like this:
3 4 1 2
1 2 3 4
4 1 2 3
2 3 4 1
I noticed that there is a pattern: If the row number is odd, the new start value of the next row is the second last one. If the row number is even, the new start value of the next row is the last one. I tried to do it in C, but the even rows are cloning themselves. Note that arrays and pointers are not allowed here, only loops and other control-structures.
I tried the following approach, but the even rows are cloning themselves:
#include <stdio.h>
const int intSquareSize = 2;
const int intFieldLength = intSquareSize * intSquareSize;
int intStartValue = 3;
int main() {
int a = 0;
int b = 0;
int m = 0;
for (int intRowCounter = 1; intRowCounter <= intFieldLength; intRowCounter++) {
m = intFieldLength - 1;
for (int intColumnCounter = 1; intColumnCounter <= intFieldLength; intColumnCounter++) {
a = intStartValue + (intColumnCounter - 1);
b = a;
if (a > intFieldLength) {
a = intFieldLength - m;
m--;
}
if (intRowCounter % 2 == 0 && intColumnCounter == intFieldLength) {
intStartValue = a;
} else if (intRowCounter % 2 == 1 && intColumnCounter == (intFieldLength - 1)) {
intStartValue = b;
}
printf("%d\t", a);
}
printf("\n");
}
return 0;
}
What did I wrong and how can I fix it?
If the row number is odd, the new start value of the next row is the second last one. If the row number is even, the new start value of the next row is the last one.
I don't think it is helpful to think in terms of odd and even. The involved numbers are just symbols, and one could even replace them with distinct colors (for example). Odd/even is not a significant thing here, and it would certainly not play the same role in other board sizes.
The pattern I see is this:
In the first intSquareSize rows, the values shift horizontally (compared to the previous row) by intSquareSize. For example with intSquareSize=3 the first three rows could be:
3 4 5 6 7 8 9 1 2
6 7 8 9 1 2 3 4 5
9 1 2 3 4 5 6 7 8
Notice the shift of 3 positions to the left at each next row.
Then the pattern for the next chunks of intSquareSize rows would be the same, but with one shift. So the complete 9x9 sudoku would look like this:
3 4 5 6 7 8 9 1 2
6 7 8 9 1 2 3 4 5
9 1 2 3 4 5 6 7 8
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
1 2 3 4 5 6 7 8 9
5 6 7 8 9 1 2 3 4
8 9 1 2 3 4 5 6 7
2 3 4 5 6 7 8 9 1
This is just one possible pattern you could follow. There could be others. But the following code will apply the above logic. Note I used your variables, but I prefer to use 0-based logic, so loop variables start at 0, and the value of a is also 0-based. Only at the time of printing 1 is added to that value, so it becomes 1-based:
int a = intStartValue - 1; // Move from 1-based to 0-based
for (int intBlockCounter = 0; intBlockCounter < intSquareSize; intBlockCounter++) {
for (int intRowCounter = 0; intRowCounter < intSquareSize; intRowCounter++) {
for (int intColumnCounter = 0; intColumnCounter < intFieldLength; intColumnCounter++) {
printf("%d\t", (a + 1)); // back to 1-based
a = (a + 1) % intFieldLength;
}
printf("\n");
a = (a + intSquareSize) % intFieldLength; // Shift within a block
}
a = (a + 1) % intFieldLength; // Shift between blocks
}

MATLAB store indices maximum in logical matrix

Lets say I have a 4 dimensional matrix, from which I would like to retrieve the maximum values over the 2nd and 3rd dimension.
A = rand(4, 4, 4, 4);
[max_2, in_2] = max(A, [], 2);
[max_3, in_3] = max(max_2, [], 3);
How could I use ind_2 and ind_3 to obtain a logical 4 dimensional matrix, where a 1 entry means this entry is maximum in the 2nd and 3rd dimension?
I would use this approach:
A = rand(4, 4, 4, 4); % example data
B = permute(A, [1 4 2 3]); % permute dims 2 and 3 to the end
B = reshape(B, size(A,1), size(A,4), []); % collapse last two dims
C = bsxfun(#eq, B, max(B, [], 3)); % maximize over collapsed last dim
C = reshape(C, size(A,1), size(A,4), size(A,2), size(A,3)); % expand dims back
C = permute(C, [1 3 4 2]); % permute dims back. This is the final result
Here's an approach working with linear indices and uses argmax indices from max function, so it would only consider the first argmax in case of ties for the max value -
% Get size parameters
[m,n,p,q] = size(A);
% Reshape to merge second and third dims
[~, in_23] = max(reshape(A,m,[],q), [], 2);
% Get linear indices equivalent that could be mapped onto output array
idx1 = reshape(in_23,m,q);
idx2 = bsxfun(#plus,(1:m)', m*n*p*(0:q-1)) + (idx1-1)*m;
% Initialize output array an assign 1s at linear indices from idx2
out = false(m,n,p,q);
out(idx2) = 1;
Explanation with a sample
1) Input array :
>> A
A(:,:,1,1) =
9 8
9 1
A(:,:,2,1) =
2 9
8 1
A(:,:,1,2) =
1 7
8 1
A(:,:,2,2) =
8 5
9 7
2) Reshape array for a better visualization :
>> reshape(A,m,[],q)
ans(:,:,1) =
9 8 2 9
9 1 8 1
ans(:,:,2) =
1 7 8 5
8 1 9 7
3) The question is to take max value from each of the rows. For that, we had idx2 as the linear indices :
>> idx2
idx2 =
1 13
2 14
Looking back at the reshape version, thus we chose (bracketed ones) -
>> reshape(A,m,[],q)
ans(:,:,1) =
[9] 8 2 9
[9] 1 8 1
ans(:,:,2) =
1 7 [8] 5
8 1 [9] 7
So, looking closely, we see that for the first row, we had two 9s, but we are choosing the first one only.
4) Finally, we are assigning these into the output array initialized as logical zeros :
>> out
out(:,:,1,1) =
1 0
1 0
out(:,:,2,1) =
0 0
0 0
out(:,:,1,2) =
0 0
0 0
out(:,:,2,2) =
1 0
1 0

Find unique elements of multiple arrays

Let say I have 3 MATs
X = [ 1 3 9 10 ];
Y = [ 1 9 11 20];
Z = [ 1 3 9 11 ];
Now I would like to find the values that appear only once, and to what array they belong to
I generalized EBH's answer to cover flexible number of arrays, arrays with different sizes and multidimensional arrays. This method also can only deal with integer-valued arrays:
function [uniq, id] = uniQ(varargin)
combo = [];
idx = [];
for ii = 1:nargin
combo = [combo; varargin{ii}(:)]; % merge the arrays
idx = [idx; ii*ones(numel(varargin{ii}), 1)];
end
counts = histcounts(combo, min(combo):max(combo)+1);
ids = find(counts == 1); % finding index of unique elements in combo
uniq = min(combo) - 1 + ids(:); % constructing array of unique elements in 'counts'
id = zeros(size(uniq));
for ii = 1:numel(uniq)
ids = find(combo == uniq(ii), 1); % finding index of unique elements in 'combo'
id(ii) = idx(ids); % assigning the corresponding index
end
And this is how it works:
[uniq, id] = uniQ([9, 4], 15, randi(12,3,3), magic(3))
uniq =
1
7
11
12
15
id =
4
4
3
3
2
If you are only dealing with integers and your vectors are equally sized (all with the same number of elements), you can use histcounts for a quick search for unique elements:
X = [1 -3 9 10];
Y = [1 9 11 20];
Z = [1 3 9 11];
XYZ = [X(:) Y(:) Z(:)]; % one matrix with all vectors as columns
counts = histcounts(XYZ,min(XYZ(:)):max(XYZ(:))+1);
R = min(XYZ(:)):max(XYZ(:)); % range of the data
unkelem = R(counts==1);
and then locate them using a loop with find:
pos = zeros(size(unkelem));
counter = 1;
for k = unkelem
[~,pos(counter)] = find(XYZ==k);
counter = counter+1;
end
result = [unkelem;pos]
and you get:
result =
-3 3 10 20
1 3 1 2
so -3 3 10 20 are unique, and they appear at the 1 3 1 2 vectors, respectively.

What is wrong with my 2-D array bordering algorithm?

I have a 2-D array in which I have to calculate the sum of the neighbours of each element, wrapping around margins and corners.
So, if we had the matrix:
1 2 3
4 5 6
7 8 9,
computing the sum of the neighbours of the last element at position (2, 2):
neighSum(A[2][2]) = 8 + 5 + 6 + 4 + 7 + 1 + 3 + 2
The way I want to implement this is by adding outside borders to the matrix. There's no point in explaining because it would take a lot longer than a visual example, so building upon the previous one, the matrix becomes:
7 8 9
3 1 2 3 1
6 4 5 6 4
9 7 8 9 7
1 2 3
For the corners, there is a catch however. The matrix is considered to be a toroid, which is a geometric shape that has the form of a donut. Think of it as taking the original matrix, wrapping it around a vertical cylinder, and then wrapping it around a horizontal cylinder. This operation makes all the corners be neighbours and we just have to fill in what is left after adding borders.
9 7 8 9 7
3 1 2 3 1
6 4 5 6 4
9 7 8 9 7
3 1 2 3 1
So far I have come up with this algorithm, which pretty much works fine, except for the rightmost column, or so I think. It is behaving strangely, sometimes overwriting some of the values in the right border, sometimes the ones in the left border as well
/* Copy the original matrix to the bordered one */
for (i = 1; i < N + 1; i++)
{
for (j = 1; j < M + 1; j++)
{
B[i][j] = A[i][j];
}
}
/* Add the left and right borders */
for(i = 1; i < M + 1; i++)
{
B[0][i] = B[N][i];
B[N+1][i] = B[1][i];
}
/* Add the top and down borders */
for(j = 1; j < N+1; j++)
{
B[i][0] = B[i][M];
B[i][M+1] = B[i][1];
}
/* Mirror the corners */
B[0][0] = B[N][M];
B[M+1][N+1] = B[1][1];
B[N+1][0] = B[1][M];
B[0][M+1] = B[N][1];
Your last loop iterator is 'j' but you use 'i' to index elements.

If I'm using a 1d array to represent a square board, how can I take my index and check the squares above, below and to its sides?

If I have a 4x4 gameboard which I'm representing in my program as a 1d integer array of size 16.
How can I get the indexs of the squares above, below, to the left and to the right any given index?
So, for example:
A = { 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 }
Which represents this board
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
Lets say I am currently on index #8 in the board (value = 7). How can I get the index for 4 (value = 3) , 5 (value = 6), 10 (value = 11) and realize that there is no right square because it is on the right hand edge of the board.
I know I need to use some modulus math but I'm failing to come up with the right way to get the indexes for adjacent squares.
I'm thinking something like...
if ((i % 4) + 1 < 3) right = i + 1;
if ((i % 4) - 1 > 0) left = i - 1;
if ((i % 4) + 4 < 15) bottom = i + 4;
if ((i % 4) - 4 > 0 ) top = i - 4;
Does this seem like it is the right approach?
To get row,column from your index, use the following:
row = index/num_columns;
column = index % num_columns;
to get back to the index, use
index = row * num_columns + column;
One you're in rows and columns, it's easy to get the surrounding positions.
above = (row-1, column)
left = (row, column-1)
etc...

Resources