问题
I am trying to build a Sudoku solver for a project I am working on. I have a 9x9 grid with each position numbered 0..80, left to right, top to bottom
e.g.:
0 1 2 3 4 5 6 7 8
9 10 ...
I am trying to return a list of Int's that represent the 3x3 grid that a position falls in. For example for position 1, which is in grid (0,0) it would return [0,1,2,9,10,11,18,19,20] and for position 8, which is in grid (0,2) it would return [6,7,8,15,16,17,24,25,26].
I have written a function which returns the required 3x3 grid, on a 9x9 Sudoku:
getBlock :: Int -> Int -> [[Int]]
getBlock x y = [[((x * sudokuSizeSq + 0) * sudokuSize) + (y * sudokuSizeSq + 0),((x * sudokuSizeSq + 0) * sudokuSize) + (y * sudokuSizeSq + 1)..((x * sudokuSizeSq + 0) * sudokuSize) + (y * sudokuSizeSq + (sudokuSizeSq-1))],[((x * sudokuSizeSq + 1) * sudokuSize) + (y * sudokuSizeSq + 0),((x * sudokuSizeSq + 1) * sudokuSize) + (y * sudokuSizeSq + 1)..((x * sudokuSizeSq + 1) * sudokuSize) + (y * sudokuSizeSq + (sudokuSizeSq-1))],[((x * sudokuSizeSq + 2) * sudokuSize) + (y * sudokuSizeSq + 0),((x * sudokuSizeSq + 2) * sudokuSize) + (y * sudokuSizeSq + 1)..((x * sudokuSizeSq + 2) * sudokuSize) + (y * sudokuSizeSq + (sudokuSizeSq-1))]]
Where: sudokuSizeSq is the square of the width (3) sudokuSize is the width (9)
x and y represent the possible grids.
This works, however I would like to increase it so it will work for larger grids. I changed my code to the follow but it seems then wont load the function.
getBlock :: Int -> Int -> [[Int]]
getBlock x y = [[((x * sudokuSizeSq + 0) * sudokuSize) + (y * sudokuSizeSq + 0),((x * sudokuSizeSq + 0) * sudokuSize) + (y * sudokuSizeSq + 1)..((x * sudokuSizeSq + 0) * sudokuSize) + (y * sudokuSizeSq + (sudokuSizeSq-1))],[((x * sudokuSizeSq + 1) * sudokuSize) + (y * sudokuSizeSq + 0),((x * sudokuSizeSq + 1) * sudokuSize) + (y * sudokuSizeSq + 1)..((x * sudokuSizeSq + 1) * sudokuSize) + (y * sudokuSizeSq + (sudokuSizeSq-1))]..[((x * sudokuSizeSq + (sudokuSizeSq-1)) * sudokuSize) + (y * sudokuSizeSq + 0),((x * sudokuSizeSq + (sudokuSizeSq-1)) * sudokuSize) + (y * sudokuSizeSq + 1)..((x * sudokuSizeSq + (sudokuSizeSq-1)) * sudokuSize) + (y * sudokuSizeSq + (sudokuSizeSq-1))]]
The way I'm doing it seems very cumbersome, is there a better way to do this or a way to fix the problem I'm having. Thanks.
回答1:
[ a + b
| a <- take sudokuSizeSq $ map (sudokuSize *) [x * sudokuSizeSq .. ]
, b <- take sudokuSizeSq [y * sudokuSizeSq ..] ]
回答2:
You can walk over the x/y offsets in each block to generate all the positions in it. List comprehensions make this rather easy:
getBlock :: Int -> Int -> [[Int]]
getBlock x y = [[(y*sudokuSizeSq+dy)*sudokuSize + x*sudokuSizeSq+dx | dx <- offsets]
| dy <- offsets]
where offsets = [0..sudokuSizeSq-1]
来源:https://stackoverflow.com/questions/4851802/haskell-get-block-for-sudoku-solver