这些是与我的问题相关的代码部分:
type Pos = (Int, Int)
type Block = [Maybe Int]
type Sudoku = [[Maybe Int]]
blank :: Sudoku -> Pos
blank sud = let k = ((whichRow sud) -1) in
let n = ((whereIsNothing (head (drop (k-1) (rows sud)))) -1) in
(k, n)
whichRow :: Sudoku -> Int
whichRow sud = whichRow' sud 0
where
whichRow' (Sudoku []) i = i
whichRow' (Sudoku (r:rs)) i = if isNothingPresent r
then 1
else whichRow' (Sudoku rs) (i+1)
whereIsNothing :: Block -> Int
whereIsNothing (x:xs) = if x == Nothing then 1 else 1 + whereIsNothing xs
isNothingPresent :: Block -> Bool
isNothingPresent b = not (Nothing `notElem` b)
我想要做的是,在空白的情况下,在Sudoku中返回一个空的位置(意思是它的元素是Nothing)。因为习惯于从0开始计数,这就是空白函数中的-1。 (Int, Int)
类型表示(行号,元素编号)。哪一行有空单元格,该行中哪些元素包含空单元格。
如果我在第一个“行”中使用“空白”单元格进行此操作,则会得到预期结果。但是,如果空单元格位于第一行的其他位置,则会得到非详尽的错误。很确定whereIsNothing函数是其原因,没有基础。我只是无法弄清楚如何解决它。有什么想法吗?
编辑:当我为Sudoku写一个有效的解决方案,并将第二行的值更改为Nothing时,我收到错误消息:
*Main> blank example2
(0,*** Exception: Sudoku.hs:166:1-73: Non-exhaustive patterns in function whereIsNothing
因此,函数应将第一个数字返回为1,它将其返回为零。
答案 0 :(得分:1)
首先,如果您正在尝试解决数独,您可能更喜欢某种代数简化:您可以使用[[Maybe Int]]
代替1- {1}的数字,而不是[[[Maybe Bool]]]
可能性(即Just 8
变为“[只是假,只是假,只是假,只是假,只是假,只是假,只是假,只是真,只是假]”。那么你就像以前一样拥有行和列,还有文件,这是基于新增的Sudoku“深度”。你的普通数独规则变为:每行必须有一个True,每列中只有一个True,每个文件中只有一个True,而每个“块”的每个深度都只有一个True。
其次,你所做的一切都是通过库函数解决的。特别是:
import Data.Maybe (isNothing, listToMaybe)
allpositions :: [Pos]
allpositions = [(x, y) | x <- [1..9], y <- [1..9]]
getValue :: Sudoku -> Pos -> Maybe Int
getValue s (x, y) = s !! x !! y
blank :: Sudoku -> Maybe Pos
blank s = listToMaybe $ filter (isNothing . getValue s) allpositions
这里listToMaybe
是一个标准库函数,类似于head
,但是当列表为[]
时它不会中断(所以你可以捕到没有空格的情况,你完成了解决数独游戏的问题!)你可能更愿意只保留一个空白位置列表。