找到数独3个3x3“块”的数独板(Haskell)

时间:2015-07-11 19:06:35

标签: haskell sudoku

我正在学习Haskell,我决定将一个小型数独求解器作为一个项目。我一直在使用this assignment作为指导,我最近在子问题D2上遇到了障碍,即创建一个可以从Sudoku板生成数独块(9个3x3网格)的函数(a 9x9网格)。

我开始编写以下代码,但我很快意识到这是一个糟糕的主意。这是一个笨重的代码,不是惯用的Haskell(在我看来),完全违反了DRY原则。

type Block = [Maybe Int]
data Sudoku = Sudoku [[Maybe Int]]

blocks :: Sudoku -> [Block]
blocks (Sudoku rs) = block1 : block2 : block3 : block4 : block5 : block6 : block7 : block8 : block9 : []
  where block1 = [(rs!!0)!!0] ++ [(rs!!0)!!1] ++ [(rs!!0)!!2] ++ [(rs!!1)!!0] ++ [(rs!!1)!!1] ++ [(rs!!1)!!2]++ [(rs!!2)!!0] ++ [(rs!!2)!!1] ++ [(rs!!2)!!2]  
        block2 = ...
        block3 = ...
        ...

我想知道如何编写一个更简洁和惯用的功能来完成任务?你将如何实现它?任何想法都表示赞赏!

我还咨询了this以前和可能相关的SO问题,但我不知道如何将pythonic解决方案转换为Haskell以及我是否应该。我也看到this问题,但我的Sudoku电路板结构不同。

我的所有当前代码都可以找到here。另外,让我知道我是否可以澄清任何事情。

3 个答案:

答案 0 :(得分:2)

首先,编写一个groupBy3函数,该函数按三个元素对列表进行分组:

groupBy3 :: [a] -> [[a]]

然后使用以下操作链:

  • map groupBy3
  • transpose
  • concat
  • groupBy3
  • map concat

写在我的手机上,所以它没有经过测试,但应该很接近。

更新:我确认这有效:

groupBy3 (a:b:c:ds) = [a,b,c] : groupBy3 ds
groupBy3 []         = []
groupBy3 as         = [ as ]  -- won't happen

boxes =  map concat . groupBy3 . concat . transpose . map groupBy3

grid = [ [ [i,j] | j <- ['1'..'9'] ] | i <- ['a'..'i'] ]

test1 = boxes grid

答案 1 :(得分:0)

这个问题不是一个确切的答案,但你最好不要使用数组而不是列表。由于您需要更改元素,因此您可能希望使用mutable arrays

然后你可以实现块作为&#34; views&#34;对于基本数组,只需对索引操作应用不同的偏移量,就不需要复制它们。

答案 2 :(得分:0)

另一种方法,虽然可能不如公认的答案那么优雅:

map concat [(map  (take 3 . drop i) . (take 3 . drop j)) grid | i <- [0, 3, 6], j <- [0, 3, 6]]

其中grid是9x9数独网格。