首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell: n皇后ASCII图形

Haskell: n皇后ASCII图形
EN

Stack Overflow用户
提问于 2016-07-17 21:14:09
回答 3查看 247关注 0票数 0

我一直在研究哈斯克尔的皇后问题,而且我大部分时间都能解决这个问题。

代码语言:javascript
复制
queens :: Int -> [[Int]]
queens 0 = [[]]
queens n = [ x : y | y <- queens (n-1), x <- [1..8], safe x y 1]
     where
         safe x [] n = True
         safe x (y:ys) n = and [ x /= y , x /= y + n , x /= y - n , safe x ys (n+1)]
drawQueens :: [Int] -> String
drawQueens [] = ""
drawQueens x = "1 2 3 4 5 6 7 8" ++ ['\n'] ++ concatMap showRow x  ++       ['\n']
    where
        size = length x
        spaces = replicate size '_' ++  ""
        showRow n = take (n - 1) spaces ++ "D" ++ take (size - n) spaces   ++ ['\n']

理想情况下,我的第二个函数drawQueens应该将皇后问题的一个解决方案转换为ASCII图形(参见下面的图像)。我的问题/问题是:

  1. 如何获得输出[ Int ]以“给”drawQueens函数一个Int的皇后函数?

2.为什么编译器不解释'\n'?如何修改代码以实现所需的输出?

这最初是一个家庭作业问题,在本学期,但我现在做它只是为了自己。

N=8的期望输出

这就是我的drawQueens输出当前的样子

谢谢你的帮助。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-07-17 21:54:39

编译器“解释”'\n'很好。只是,换行符并不是真正的“安全字符”,如:不能在Haskell代码中直接使用包含换行符的字符串文字。print的输出-- GHCi默认使用它来打印内容--总是试图生成有效的Haskell代码,因此它再次将这些换行符转义。如果您只是指示它像对终端那样禁止字符串,这是可以抑制的:

代码语言:javascript
复制
*Main> drawQueens [4,2,7,3,6,8,5,1]
"1 2 3 4 5 6 7 8\n___D____\n_D______\n______D_\n__D_____\n_____D__\n_______D\n____D___\nD_______\n\n"
*Main> putStrLn $ drawQueens [4,2,7,3,6,8,5,1]
1 2 3 4 5 6 7 8
___D____
_D______
______D_
__D_____
_____D__
_______D
____D___
D_______

还有另一个问题:你在数字上没有和实际上的棋盘相同的间距。嗯,这也很容易解决。

代码语言:javascript
复制
drawQueens :: [Int] -> String
drawQueens [] = ""
drawQueens x = "1 2 3 4 5 6 7 8" ++ "\n" ++ concatMap showRow x
    where
        size = length x
        spaces n = concat $ replicate n "□ "
        showRow n = spaces (n - 1) ++ "♛ " ++ spaces (size - n) ++ "\n"

这就给出了:

代码语言:javascript
复制
*Main> putStrLn $ drawQueens [4,2,7,3,6,8,5,1]
1 2 3 4 5 6 7 8
□ □ □ ♛ □ □ □ □ 
□ ♛ □ □ □ □ □ □ 
□ □ □ □ □ □ ♛ □ 
□ □ ♛ □ □ □ □ □ 
□ □ □ □ □ ♛ □ □ 
□ □ □ □ □ □ □ ♛ 
□ □ □ □ ♛ □ □ □ 
♛ □ □ □ □ □ □ □ 

花哨的版本:

代码语言:javascript
复制
chessboardRow, chessboardRow' :: [Maybe Char] -> String
chessboardRow' [] = "▌"
chessboardRow' (Just c:cs) = '▌':c:chessboardRow cs
chessboardRow' (Nothing:cs) = "▌ "++chessboardRow cs
chessboardRow [] = " "
chessboardRow (Just c:cs) = '▐':c:chessboardRow' cs
chessboardRow (Nothing:cs) = "▐█"++chessboardRow' cs

drawQueens :: [Int] -> String
drawQueens [] = ""
drawQueens x = "  a b c d e f g h" ++ "\n"
                 ++ concat (reverse $ 
                             zipWith3 showRow
                                      ['1'..]
                                      (cycle [chessboardRow, chessboardRow'])
                                      x)
                 ++ "\n"
    where
        size = length x
        showRow i rsh n = i : rsh (replicate (n - 1) Nothing
                                      ++ [Just '♛']
                                      ++ replicate (size - n) Nothing)
                              ++ "\n"

给出

代码语言:javascript
复制
  a b c d e f g h
8▌♛▐█▌ ▐█▌ ▐█▌ ▐█▌
7▐█▌ ▐█▌ ▐♛▌ ▐█▌  
6▌ ▐█▌ ▐█▌ ▐█▌ ▐♛▌
5▐█▌ ▐█▌ ▐█▌♛▐█▌  
4▌ ▐█▌♛▐█▌ ▐█▌ ▐█▌
3▐█▌ ▐█▌ ▐█▌ ▐♛▌  
2▌ ▐♛▌ ▐█▌ ▐█▌ ▐█▌
1▐█▌ ▐█▌♛▐█▌ ▐█▌  
票数 3
EN

Stack Overflow用户

发布于 2016-07-17 21:29:25

给ghci drawQueens (head (queens 8))将输出一个字符串,您可以将该字符串复制到代码中以获得该字符串,包括引号、文字\n等。

给予ghci putStr (drawQueens (head (queens 8)))将代替“解释”字符串,将\n转换为换行符,省略引号等。putStrLn而不是putStr在末尾添加了一个换行符。

如果皇后区返回的列表为空,这两者都会崩溃。更安全的变体包括listToMaybe、大小写匹配和/或来自另一个答案的forM/traverse内容。

票数 1
EN

Stack Overflow用户

发布于 2016-07-17 21:19:43

看起来这应该是可行的:

代码语言:javascript
复制
import Control.Monad

forM_ (map drawQueens (queens 8)) putStrLn

forM_drawQueens ...中的每个结果“提供”给putStrLn

更新

putStrLn实际上将一个字符串打印到控制台,从而“解释”新行。

例如:

代码语言:javascript
复制
ghci> "line 1\nline 2\n"
"line 1\nline 2\n"
ghci> putStrLn "line 1\nline 2\n"
line 1
line 2
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38425982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档