输出帕斯卡的三角形

问题描述

import Data.List (intercalate)
import Control.Concurrent (threadDelay)
import System.IO

-- I love how amazingly concise Haskell code can be.  This same program in C,C++ or Java
-- would be at least twice as long.


pascal :: Int -> Int -> Int
pascal row col | col >= 0 && col <= row =
                 if row == 0 || col == 0 || row == col
                 then 1
                 else pascal (row - 1) (col - 1) + pascal (row - 1) col
pascal _ _ = 0


pascalsTriangle :: Int -> [[Int]]
pascalsTriangle rows =
  [[pascal row col | col <- [0..row]] | row <- [0..rows]]


main :: IO ()
main = do
  putStrLn "" 
  putStr "Starting at row #0,how many rows of Pascal's Triangle do you want to print out? "
  hFlush stdout
  numRows <- (\s -> read s :: Int) <$> getLine
  let triangle = pascalsTriangle numRows
      triangleOfStrings = map (intercalate ",") $ map (map show) triangle
      lengthOfLastDiv2 = div ((length . last) triangleOfStrings) 2 
  putStrLn ""
  mapM_ (\s -> let spaces = [' ' | x <- [1 .. lengthOfLastDiv2 - div (length s) 2]]
                   in (putStrLn $ spaces ++ s) >> threadDelay 200000) triangleOfStrings
  putStrLn ""

我上面的小程序找到了Pascal Triangle的值。但是,如果编译并使用它,您会发现“三角形”看起来更像是圣诞树,而不是三角形!哎呀!

我只是占用最后一行的一半的长度,然后减去前一行的一半,然后创建那么多空格以添加到每个字符串的开头。它几乎可以工作,但是我正在寻找等边三角形的效果,但对我来说,它就像是倾斜的圣诞树!有一个更好的方法吗。除了一些编程人才,我还缺少什么?谢谢您的帮助。这不是家庭作业。我只是为了娱乐和娱乐而这样做。感谢您的帮助。

最佳。 道格拉斯·莱威特。

解决方法

这是一个简单的实现:

space n = replicate n ' '

pad n s | n < length s = take n s
pad n s = space (n - length s) ++ s

triangle = iterate (\ xs -> zipWith (+) (xs ++ [0]) (0:xs)) [1]

rowPrint n hw xs  = space (n * hw) ++ concatMap (pad (2*hw) . show) xs

triRows n hw = [rowPrint (n-i) hw row | (i,row) <- zip [1..n] triangle]

main = do
  s <- getLine
  mapM_ putStrLn (triRows (read s) 2)

请注意,triangle是由递归关系生成的无限Pascal三角形。同样,hw代表“半角宽度”:分配用于打印数字的宽度的一半,而pad是严格的左键,可以截断输出而不破坏格式。