在Haskell中打印Pascal的三角形

时间:2016-04-27 16:46:11

标签: haskell pascals-triangle

我刚刚开始学习Haskell,并且一直在网上做一些问题。大多数时候,我可以找出解决方案,但我无法以预期的输出格式打印出来。

例如,我尝试过做Pascal的三角形程序。我发现了如何生成Pascal三角形作为Ints列表的列表,但我无法弄清楚如何打印它。

这是我的代码。

import Data.List
pascal n = map liner [0..n]
    where liner x = map (comb x) [0..x]

comb n 0 = 1
comb 0 r = 0
comb n r = comb (n-1) (r-1) * n `div` r 

main = do
    order <- getLine
    let output = pascal . (read :: String -> Int) $ order
    print output 

目前,输出类似于

[[1],[1,1],[1,2,1],[1,3,3,1]...

我想以

的形式打印它
1
1 1
1 2 1
1 3 3 1
...

我该怎么做?我尝试过使用mapM_或插入“”这样的东西,没有运气。我还没有进入monad所以我不明白mapM是如何工作的。

2 个答案:

答案 0 :(得分:3)

有几种不同的方法可以做到这一点,但最直接的(IMO)如下。

putStrLn $ intercalate "\n" $ map (intercalate " " . map show) output

首先将列表中的所有数字转换为字符串(使用show)。然后它将最里面的列表转换为字符串,其中每个元素由空格分隔(使用intercalate " ")。然后它将最外层列表转换为字符串,其中每个元素由换行符(使用intercalate "\n")分隔。最后,它将生成的字符串推送到stdout。用这个替换main的最后一行,它应该做你想要的。

编辑: 正如Yakym在他的回答中提到的,intercalate " "intercalate "\n"可以替换为unwordsunlines,使上面的代码更加简洁(它也消除了对导入Data.List)。

putStr $ unlines $ map (unwords . map show) output

我将putStrLn更改为putStr,因为unlines会自动在输出结尾添加换行符。

答案 1 :(得分:2)

还有unlinesunwords等功能可以在字符串列表上进行自然插入。

pascal :: [[Int]]
pascal = iterate (\row -> zipWith (+) ([0] ++ row) (row ++ [0])) [1]

printPascal :: [[Int]] -> IO ()
printPascal = mapM_ (putStrLn . unwords . map show)

--*Main> printPascal $ take 10 pascal 
--1
--1 1
--1 2 1
--1 3 3 1
--1 4 6 4 1
--1 5 10 10 5 1
--1 6 15 20 15 6 1
--1 7 21 35 35 21 7 1
--1 8 28 56 70 56 28 8 1
--1 9 36 84 126 126 84 36 9 1