功能中的非穷举错误

时间:2014-10-16 10:35:29

标签: haskell brute-force

这些是与我的问题相关的代码部分:

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,它将其返回为零。

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,但是当列表为[]时它不会中断(所以你可以捕到没有空格的情况,你完成了解决数独游戏的问题!)你可能更愿意只保留一个空白位置列表。