Related
I'm building a heatmap-like rectangular array interface and I want the 'hot' location to be at the top left of the array, and the 'cold' location to be at the bottom right. Therefore, I need an array to be filled diagonally like this:
0 1 2 3
|----|----|----|----|
0 | 0 | 2 | 5 | 8 |
|----|----|----|----|
1 | 1 | 4 | 7 | 10 |
|----|----|----|----|
2 | 3 | 6 | 9 | 11 |
|----|----|----|----|
So actually, I need a function f(x,y) such that
f(0,0) = 0
f(2,1) = 7
f(1,2) = 6
f(3,2) = 11
(or, of course, a similar function f(n) where f(7) = 10, f(9) = 6, etc.).
Finally, yes, I know this question is similar to the ones asked here, here and here, but the solutions described there only traverse and don't fill a matrix.
Interesting problem if you are limited to go through the array row by row.
I divided the rectangle in three regions. The top left triangle, the bottom right triangle and the rhomboid in the middle.
For the top left triangle the values in the first column (x=0) can be calculated using the common arithmetic series 1 + 2 + 3 + .. + n = n*(n+1)/2. Fields in the that triangle with the same x+y value are in the same diagonal and there value is that sum from the first colum + x.
The same approach works for the bottom right triangle. But instead of x and y, w-x and h-y is used, where w is the width and h the height of rectangle. That value have to be subtracted from the highest value w*h-1 in the array.
There are two cases for the rhomboid in the middle. If the width of rectangle is greater than (or equal to) the height, then the bottom left field of the rectangle is the field with the lowest value in the rhomboid and can be calculated that sum from before for h-1. From there on you can imagine that the rhomboid is a rectangle with a x-value of x+y and a y-value of y from the original rectangle. So calculations of the remaining values in that new rectangle are easy.
In the other case when the height is greater than the width, then the field at x=w-1 and y=0 can be calculated using that arithmetic sum and the rhomboid can be imagined as a rectangle with x-value x and y-value y-(w-x-1).
The code can be optimised by precalculating values for example. I think there also is one formula for all that cases. Maybe i think about it later.
inline static int diagonalvalue(int x, int y, int w, int h) {
if (h > x+y+1 && w > x+y+1) {
// top/left triangle
return ((x+y)*(x+y+1)/2) + x;
} else if (y+x >= h && y+x >= w) {
// bottom/right triangle
return w*h - (((w-x-1)+(h-y-1))*((w-x-1)+(h-y-1)+1)/2) - (w-x-1) - 1;
}
// rhomboid in the middle
if (w >= h) {
return (h*(h+1)/2) + ((x+y+1)-h)*h - y - 1;
}
return (w*(w+1)/2) + ((x+y)-w)*w + x;
}
for (y=0; y<h; y++) {
for (x=0; x<w; x++) {
array[x][y] = diagonalvalue(x,y,w,h);
}
}
Of course if there is not such a limitation, something like that should be way faster:
n = w*h;
x = 0;
y = 0;
for (i=0; i<n; i++) {
array[x][y] = i;
if (y <= 0 || x+1 >= w) {
y = x+y+1;
if (y >= h) {
x = (y-h)+1;
y -= x;
} else {
x = 0;
}
} else {
x++;
y--;
}
}
What about this (having an NxN matrix):
count = 1;
for( int k = 0; k < 2*N-1; ++k ) {
int max_i = std::min(k,N-1);
int min_i = std::max(0,k-N+1);
for( int i = max_i, j = min_i; i >= min_i; --i, ++j ) {
M.at(i).at(j) = count++;
}
}
Follow the steps in the 3rd example -- this gives the indexes (in order to print out the slices) -- and just set the value with an incrementing counter:
int x[3][3];
int n = 3;
int pos = 1;
for (int slice = 0; slice < 2 * n - 1; ++slice) {
int z = slice < n ? 0 : slice - n + 1;
for (int j = z; j <= slice - z; ++j)
x[j][slice - j] = pos++;
}
At a M*N matrix, the values, when traversing like in your stated example, seem to increase by n, except for border cases, so
f(0,0)=0
f(1,0)=f(0,0)+2
f(2,0)=f(1,0)+3
...and so on up to f(N,0). Then
f(0,1)=1
f(0,2)=3
and then
f(m,n)=f(m-1,n)+N, where m,n are index variables
and
f(M,N)=f(M-1,N)+2, where M,N are the last indexes of the matrix
This is not conclusive, but it should give you something to work with. Note, that you only need the value of the preceding element in each row and a few starting values to begin.
If you want a simple function, you could use a recursive definition.
H = height
def get_point(x,y)
if x == 0
if y == 0
return 0
else
return get_point(y-1,0)+1
end
else
return get_point(x-1,y) + H
end
end
This takes advantage of the fact that any value is H+the value of the item to its left. If the item is already at the leftmost column, then you find the cell that is to its far upper right diagonal, and move left from there, and add 1.
This is a good chance to use dynamic programming, and "cache" or memoize the functions you've already accomplished.
If you want something "strictly" done by f(n), you could use the relationship:
n = ( n % W , n / H ) [integer division, with no remainder/decimal]
And work your function from there.
Alternatively, if you want a purely array-populating-by-rows method, with no recursion, you could follow these rules:
If you are on the first cell of the row, "remember" the item in the cell (R-1) (where R is your current row) of the first row, and add 1 to it.
Otherwise, simply add H to the cell you last computed (ie, the cell to your left).
Psuedo-Code: (Assuming array is indexed by arr[row,column])
arr[0,0] = 0
for R from 0 to H
if R > 0
arr[R,0] = arr[0,R-1] + 1
end
for C from 1 to W
arr[R,C] = arr[R,C-1]
end
end
I'm working on creating a Sudoku Solver with SML/NJ. I've got all of the functions in place to actually manipulate the input data (check for legality of rows, forcing the empty spaces, etc) but I'm having trouble with the backtracking part.
I came across this question but I'm confused on how to implement it in SML.
Note that a board is input as a list of lists that represent the numbers in each row, 0 for an unknown spot
[[0,0,0, 2,6,0, 7,0,1],
[6,8,0, 0,7,0, 0,9,0],
[1,9,0, 0,0,4, 5,0,0],
[8,2,0, 1,0,0, 0,4,0],
[0,0,4, 6,0,2, 9,0,0],
[0,5,0, 0,0,3, 0,2,8],
[0,0,9, 3,0,0, 0,7,4],
[0,4,0, 0,5,0, 0,3,6],
[7,0,3, 0,1,8, 0,0,0]]
Here is my (edited) solve function.
exception Sudoku;
fun solve board =
let fun solve' board k =
(* k is the row we are working on, so if it's 9, we SHOULD be done *)
if k = 9 then board else
let
(* get row k from the board *)
val row = (List.nth (board, k));
fun trySpot number col =
(* if number >= 10, raise an exception to backtrack *)
if number > (length row) then raise Sudoku
(* if col = 9, raise an exception to backtrack *)
else if col = 9 then raise Sudoku
(* if row[col] is not a zero, move to next col *)
else if not (List.nth(row, col) = 0) then trySpot number (col + 1)
(* row doesn't contain this num already *)
else if length (List.filter (fn x => x = number) row) = 0 then
let
(* build the new row and board and check if legal (this works fine) *)
val newRow = delete(col + 1, (insertAtPos row number col));
val newBoard = delete(k + 1, (insertAtPos board newRow k));
val isLegal = checkLegal newBoard;
in
(* if legal, keep solving with new board as base *)
if isLegal then
solve' (force newBoard) 0
handle Sudoku => solve' (force board) (k + 1)
(* not legal, try with next num *)
else trySpot (number + 1) col
end
(* row already has this number, skipping *)
else trySpot (number + 1) col
in
(* if board is complete and legal we're done *)
if completedBoard board andalso checkLegal board then board
(* if row has a zero then try a spot *)
else if (zeroInList row) then trySpot 1 0
(* otherwise move to next row *)
else solve' (force board) (k + 1)
end
in
(* initial solve *)
solve' (force board) 0
end;
Calling solve on the sample data above returns the following lists
[[4,3,5,2,6,9,7,8,1],
[6,8,2,5,7,1,4,9,3],
[1,9,7,8,3,4,5,6,2],
[8,2,6,1,9,5,3,4,7],
[3,1,4,6,8,2,9,0,0],
[0,5,0,0,0,3,0,2,8],
[0,0,9,3,0,0,0,7,4],
[2,4,0,0,5,0,0,3,6],
[7,0,3,0,1,8,0,0,0]]
Now this is partially correct. The first four rows look to be fully correct based on an online sudoku solver I used to check, but it gets messed up on the 5th row. I presume it's because it's not able to backtrack all the way.
The only place it "backs up" is on this line
handle Sudoku => solve' (force board) (k + 1)
This tells it to just try solving the old board (without the new number) but this is preventing it from backtracking more than one step (I think). How could this be accomplished?
If anyone is curious to see the full code, you can find it here.
Thanks in advance!
I seem to have gotten my solve function to work with all of the cases I've tried. The trick was to keep track of a list of illegal numbers for the spot we were working on. The solver will now skip over these numbers, and backtrack if it can't find a path forward.
exception Sudoku;
(* solves a soduku board input that gives a list of lists representing the rows of a board (0 for unknown spaces) *)
fun solve board =
let fun solve' board row illegalNums =
(* if we are on row 9 and board is complete/legal, we are done *)
if row = 9 andalso completedBoard board andalso checkLegal board then board else
(* if we are on row 9 but the board is not complete/legal, throw an exception to backtrack *)
if row = 9 then raise Sudoku else
let
(* get the current row we are working on *)
val cRow = (List.nth (board, row));
(* trys a row[col] on the board with a certain number *)
fun trySpot num cRow col =
(* if number >= 10, raise an exception to backtrack *)
if num > 9 then raise Sudoku
(* if row[col] is not a 0, try next col *)
else if not (List.nth (cRow, col) = 0) then trySpot num cRow (col + 1)
(* if we know that the number we are on isn't allowed, skip to next number *)
else if length (List.filter (fn x=> x = num) illegalNums) > 0 then trySpot (num + 1) cRow col
(* if row already has this number, skip to next number *)
else if length (List.filter (fn x=> x = num) cRow) > 0 then trySpot (num + 1) cRow col
(* if col already has this number, skip to next number *)
else if length (List.filter (fn x=> x = num) (List.nth((rowsToCols board), col))) > 0 then trySpot (num + 1) cRow col
else
let
(* make our new row and board *)
val newRow = delete(col + 1, (insertAtPos cRow num col));
val newBoard = delete(row + 1, (insertAtPos board newRow row));
in
(* if new board is legal, continue solving *)
if checkLegal newBoard then
solve' (force newBoard) 0 []
(* handle any exceptions by adding the number to our list of illegal numbers, thereby backtracking *)
handle Sudoku => solve' (force board) row (illegalNums#[num])
(* if new board is not legal, try next number *)
else trySpot (num + 1) cRow col
end
in
(* if board is completed and legal, return board *)
if completedBoard board andalso checkLegal board then board
(* if current row has at least one 0, try a number in that row (beginning at col 1) *)
else if (zeroInList cRow) then trySpot 1 cRow 0
(* else, skip to next row and solve *)
else solve' (force board) (row + 1) []
end
in
(* initial solve *)
solve' (force board) 0 []
end;
The harder boards can take quite a while to fully solve, but every one I've tested eventually gets there. I'm sure there are a ton of optimizations I can do in my code, so I'm open to suggestions.
This question already has an answer here:
Wrapping in Conway's Game of Life C++
(1 answer)
Closed 7 years ago.
I am trying to write a program that implements Conway's game of life on a 20x60 cell board. The grid will wrap around so the left side will be connected to (neighbouring) the right side and the top will be connected to the bottom.
Thus any cell with position (0, col), will have a neighbour at (maxRow, col). Any cell with position (row, 0) will have a neighbour at (row, maxCol).
The following function is supposed to count the number of neighbouring cells. It works for coordinates not on the edges, but not for ones that are. For instance, if there are points at (0, 10), (0, 11), and (0, 12) and (0, 10) is passed into the function, it will return a high number as neighbor count instead of 1.
{
int i, j;
int count = 0;
for (i = row - 1; i <= row + 1; i++)
for (j = col - 1; j <= col + 1; j++)
count += grid[i][j]; }
if (row==maxrow-1 || row==0)
count = count+ grid [(row-(maxrow-1))*-1][col-1]+grid[(row-(maxrow-1))*-1][col]+grid[(row-(maxrow-1))*-1][col+1];
if (col==0 || col==maxcol-1)
count=count +grid[row-1][(col-(maxcol-1))*-1]+grid[row][(col-(maxcol-1))*-1]+grid[row+1][(col-(maxcol-1))*-1];
count -= grid[row][col];
return count;
}
You can apply this formula to indices:
(x + max) % max
It will make -1 = 7 (wrap around) and 8 will be 0.
Okay so I am making the game of life in C and I can't figure out how to count the neighbors from the matrix..
Here is my current code
http://pastebin.com/8fTdbpfs
Sorry I think it just looks better on pastebin.
For cell at location (i,j), i.e. i row, j column, coordinates of all its eight neighbors are
(i-1,j-1) | (i-1,j) | (i-1,j+1)
----------+---------+----------
(i, j-1) | (i ,j) | (i ,j+1)
----------+---------+----------
(i+1,j-1) | (i+1,j) | (i+1,j+1)
In a two-dimensional array array[row][col], you could access them by array[i][j]. Of course, you need to make sure every coordinates are valid before you try to access cell at that coordinate, you can using the following condition to make this check:
// for coordinate (i, j) in array[row][col]
if ((0 <= i) && (i < row) && (0 <= j) && (j < col)) {
/* access array[i][j] */
}
I have an 8x8 matrix, like this:
char matrix[8][8];
Also, I have an array of 64 elements, like this:
char array[64];
Then I have drawn the matrix as a table, and filled the cells with numbers, each number being incremented from left to right, top to bottom.
If I have, say, indexes 3 (column) and 4 (row) into the matrix, I know that it corresponds to the element at position 35 in the array, as it can be seen in the table that I've drawn. I believe there is some sort of formula to translate the 2 indexes of the matrix into a single index of the array, but I can't figure out what it is.
Any ideas?
The way most languages store multi-dimensional arrays is by doing a conversion like the following:
If matrix has size, n (rows) by m (columns), and we're using "row-major ordering" (where we count along the rows first) then:
matrix[ i ][ j ] = array[ i*m + j ].
Here i goes from 0 to (n-1) and j from 0 to (m-1).
So it's just like a number system of base 'm'. Note that the size of the last dimension (here the number of rows) doesn't matter.
For a conceptual understanding, think of a (3x5) matrix with 'i' as the row number, and 'j' as the column number. If you start numbering from i,j = (0,0) --> 0. For 'row-major' ordering (like this), the layout looks like:
|-------- 5 ---------|
Row ______________________ _ _
0 |0 1 2 3 4 | |
1 |5 6 7 8 9 | 3
2 |10 11 12 13 14| _|_
|______________________|
Column 0 1 2 3 4
As you move along the row (i.e. increase the column number), you just start counting up, so the Array indices are 0,1,2.... When you get to the second row, you already have 5 entries, so you start with indices 1*5 + 0,1,2.... On the third row, you have 2*5 entries already, thus the indices are 2*5 + 0,1,2....
For higher dimension, this idea generalizes, i.e. for a 3D matrix L by N by M:
matrix[ i ][ j ][ k ] = array[ i*(N*M) + j*M + k ]
and so on.
For a really good explanation, see: http://www.cplusplus.com/doc/tutorial/arrays/; or for some more technical aspects: http://en.wikipedia.org/wiki/Row-major_order
For row-major ordering, I believe the statement matrix[ i ][ j ] = array[ i*n + j ] is wrong.
The offset should be offset = (row * NUMCOLS) + column.
Your statement results to be row * NUMROWS + column, which is wrong.
The links you provided give a correct explanation.
Something like this?
//columns = amount of columns, x = column, y = row
var calculateIndex = function(columns, x, y){
return y * columns + x;
};
The example below converts an index back to x and y coordinates.
//i = index, x = amount of columns, y = amount of rows
var calculateCoordinates = function(index, columns, rows){
//for each row
for(var i=0; i<rows; i++){
//check if the index parameter is in the row
if(index < (columns * i) + columns && index >= columns * i){
//return x, y
return [index - columns * i, i];
}
}
return null;
};