Haskell: Get block for Sudoku solver

点点圈 提交于 2020-01-25 04:42:08

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!