1

所以在过去的几个小时里,我一直在研究打印数独板的问题,我几乎完成了,但我被困在最后一步。所以我所拥有的是一个表示为“列表列表”的数独板(即 board = [[1, 3, 5, 7, 0, 2, 0, 0, 0], [3, 4, 5, .. .], ...]

我已经能够使用以下功能打印出带有格式的行:

line i s_board = intercalate " | " . map unwords . chunksOf 3 $ map show a
             where 
               a = s_board!!i 

因此,通过拨打“line 0 board”之类的电话,我会得到“1 3 5 | 7 0 2 | 0 0 0”,这部分是我需要的。接下来我尝试使用“do block”来输出我需要的板,它看起来像这样:

print = do line 0 board 
        line 1 board 
        ...

这甚至不会编译,当我做这样的事情时:

print = do 
        line 0 board 
        line 1 board

适当的列表被打印了多次,这相当令人困惑。我想努力增加额外的格式,例如在每三行之后打印一个字符串,例如“----------”以完成电路板,但我什至无法让其他东西工作对了。对于这些问题提供的任何帮助,我将不胜感激。

4

2 回答 2

7

生成一个函数来获取您的电路板,制作一个大字符串并最终打印它会更容易和更优雅,而不是担心通过一个do块打印每一行。

因此,如果我们简化您的线条显示功能以占用电路板的一条线:

showLine :: [Int] -> String
showLine = intercalate " | "
         . map unwords
         . chunksOf 3
         . map show

然后,我们需要获取每一行的字符串表示并将它们放在一起。这看起来很像showLine代码:

showBoard :: [[Int]] -> String
showBoard = intercalate "---------------------\n"
          . map unlines
          . chunksOf 3
          . map showLine

使用示例板

-- Obviously not a valid sudoku board...
example :: [[Int]]
example = replicate 9 [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

*Main> putStrLn $ showBoard example
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
---------------------
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
---------------------
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
于 2012-11-26T03:46:27.243 回答
3

您最初的尝试没有编译,因为它违反了 Haskell 的布局规则。

第二个没有做你所期望的,因为line n board它是一个列表,所以do-notation 表示不确定性,而不是 IO 操作的顺序。如果您尝试输入类似的类型

print :: IO ()

在你的函数之上(顺便说一句,print在标准前奏中定义,你应该得到一个关于隐藏它的警告),类型检查器会通知你你的错误。如果您真的想像这样打印出电路板(尽管正如另一个答案所暗示的那样,构建一个字符串然后将整个内容打印出来要好得多),您可以尝试

printBoard :: IO ()
printBoard = do print $ line 0 board
                print $ line 1 board

或打印整个电路板,

printBoard = mapM_ (print . showLine) board

whereshowLine和你的一样print,但是去掉了索引。

于 2012-11-26T03:52:22.647 回答