我需要编写一个Haskell程序,它将以递归方式生成菱形输出。 以下是给定输入的一些示例输出
输入:1
输出:
*
* *
*
输入:2
输出:
*
* *
*
* *
* * * *
* *
*
* *
*
输入:3
输出:
*
* *
*
* *
* * * *
* *
*
* *
*
* *
* * * *
* *
* * * *
* * * * * * * *
* * * *
* *
* * * *
* *
*
* *
*
* *
* * * *
* *
*
* *
*
我写了以下功能:
next 0 = [1,0,1]
next n = map (+3^n) (next (n-1)) ++ next (n-1) ++ map (+3^n) (next (n-1))
lpad n = map (++"*") (zipWith ($) (map (take)(next (n-1))) ((repeat(repeat ' '))))
pretty n = putStrLn $ intercalate "\n" $ lpad n
给出以下输出:
漂亮1
*
*
*
漂亮2
*
*
*
*
*
*
*
*
*
任何人都可以帮助我剩下的一半吗?提前谢谢。
答案 0 :(得分:5)
我喜欢这个任务,所以我写了一个替代解决方案。
我们可以建立它,有点像你用漂亮的打印机。查看pretty包以获取这些想法并正确使用它们,但为此我们坚持使用普通的[String]
。
首先让我们制作一个空白网格
blank :: Int -> [String]
blank n = replicate (3^n) $ replicate (3^n) ' '
然后让我们定义一颗钻石。
diamond :: Int -> [String]
diamond 0 = ["*"]
diamond n = let
o = diamond (n-1)
x = blank (n-1) in
joinMatrix [[x,o,x]
,[o,x,o]
,[x,o,x]]
但是我们怎样才能将[String]
这个矩阵加在一起呢?
首先使用String
将所有应transpose
连接在一起,而不是彼此连接,然后concat
全部:
joinLine :: [[String]] -> [String]
joinLine = map concat.transpose
要对整个矩阵执行此操作,我们需要连接每行上的行,然后将所有行连接在一起成为一个行列表:
joinMatrix :: [[[String]]] -> [String]
joinMatrix = concat.map joinLine
打印帮助函数:
put = mapM_ putStrLn
d n = put $ diamond n
你可以说数值解决方案效率更高,而且d 4
是最适合我屏幕的并且速度不慢。你也可以说这个解决方案更清楚。
*Main> d 0
*
*Main> d 1
*
* *
*
*Main> d 2
*
* *
*
* *
* * * *
* *
*
* *
*
(它也适用于更高的n,但它们会使页面上的帖子不必要地长。)
答案 1 :(得分:4)
对于n==0
,next n
描述了直到镜像的整个画面。对于更大的n
,情况不再如此。因此,在第一步中,我们更改next
函数以输出对称图片:
mmap = map . map
next :: Int -> [[Int]]
next 0 = [[1],[0,2],[1]]
next n = sn ++ map (\a -> a ++ map (+2*3^n) a) nn ++ sn
where
nn = next (n - 1)
sn = mmap (+3^n) nn
现在,next n
描述了所有明星的位置。要打印它们,我们首先计算相对距离。
diffs :: [Int] -> [Int]
diffs (x:xs) = x: diffs' x (xs)
where
diffs' x (y:ys) = y - x - 1 : diffs' y ys
diffs' _ [] = []
diffs [] = []
lpad :: Int -> [[Char]]
lpad = map (concatMap $ \n -> replicate n ' ' ++ "*") . map diffs . next'
应用于一行,diffs
返回我们需要在每个星号之前放置的空格数列表,lpad
从中生成图片。像以前一样打印:
pretty :: Int -> IO ()
pretty n = putStrLn $ unlines $ lpad n
答案 2 :(得分:1)
这源于AndrewC的解决方案。空间块是递归生成的,我更喜欢使用运算符来使代码更清晰:
diamond
= putStr
. unlines
. fst
. (iterate f (["*"], [" "]) !!)
where
f (d, e)
= ( e + d + e
++ d + e + d
++ e + d + e
, e + e + e
++ e + e + e
++ e + e + e
)
(+) = zipWith (++)
概括。 如果我们想要这个:
+
- -
+
- -
+ + + +
- -
+
- -
+
- -
+ + + +
- -
+ + + +
- - - - - - - -
+ + + +
- -
+ + + +
- -
+
- -
+
- -
+ + + +
- -
+
- -
+
然后解决方案是star 3
其中
star
= putStr
. unlines
. (\(d, p, e) -> d)
. (iterate f (["-"], ["+"], [" "]) !!)
where
f (d, p, e)
= ( e + p + e
++ d + e + d
++ e + p + e
, e + d + e
++ p + e + p
++ e + d + e
, e + e + e
++ e + e + e
++ e + e + e
)
(+) = zipWith (++)