我正在学习Haskell,我决定开始一个小的数独解算器作为一个项目。我一直使用this assignment作为指导,我最近在子问题D2
上碰壁,这是创建一个函数,将生成数独块(9 3x 3网格)从数独板(9 x9网格)。
我开始写下面的代码,但我很快意识到这是一个可怕的想法。这是笨重的代码,不是惯用的Haskell(在我看来),完全违反了干原则。
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之前的和可能相关的问题,但我不知道如何转换Python解决方案到Haskell,我甚至不应该。我也看到了this的问题,但我有不同的结构我的数独板。
我目前所有的代码都可以在here中找到。另外,如果我能澄清任何事情,请让我知道。
4条答案
按热度按时间h6my8fg21#
首先,编写一个
groupBy3
函数,该函数按三个元素对列表进行分组:然后使用以下操作链:
map groupBy3
个transpose
concat
groupBy3
map concat
写在我的手机上,所以它是未经测试的,但它应该是接近。
更新:我验证了这一点:
inkz8wg92#
虽然这不是这个问题的确切答案,但是使用数组比使用列表要好得多。因为需要更改元素,所以可能需要使用mutable arrays。
然后,您可以将块实现为基数组的“视图”,只需对索引操作应用不同的偏移量,而无需复制它们。
6rqinv9w3#
另一种方法,虽然可能不如公认的答案那么优雅:
其中
grid
是9x9数独网格。ig9co6j14#
下面是另一种方法:boxsize = 3用于(9 x 9)网格,对于(4 X 4)网格,可以使用boxsize = 2