Master_Pabu
Master_Pabu

Reputation: 23

Printing Pascal's triangle in Haskell

I just started learning Haskell, and have been doing a few problems online. Most of the times, I can figure out the solution but I am unable to print it out in the output format that is expected.

For example, I tried doing a Pascal's triangle program. I found out how to generate Pascal's Triangle as a list of lists of Ints, but I cant figure out how to print it.

Here is my code.

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 

Currently, the output is like

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

I want to print it in the form

1
1 1
1 2 1
1 3 3 1
...

How do I do this? I have tried using things like mapM_ or intercalate " ", with no luck. I'm not into monads yet so I don't understand how mapM works.

Upvotes: 2

Views: 1184

Answers (2)

Kwarrtz
Kwarrtz

Reputation: 2753

There are several different ways to do this, but the most straight forward (IMO) is the following.

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

This first converts all of the numbers in the list into strings (using show). Then it converts the innermost lists into strings, where each element is separated by spaces (using intercalate " "). Then it converts the outermost list into a string where each element is separated by a newline (using intercalate "\n"). And finally, it pushes the resulting string onto stdout. Replace the last line of your main with this and it should do what you want.

EDIT: As Yakym mentioned in his answer, intercalate " " and intercalate "\n" can be replaced with unwords and unlines, making the code above a little more concise (it also removes the need for the import of Data.List).

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

I changed putStrLn to putStr because unlines automatically adds a newline to the end of the output.

Upvotes: 4

hilberts_drinking_problem
hilberts_drinking_problem

Reputation: 11602

There are also functions like unlines and unwords that do natural intercalation on string lists.

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

Upvotes: 2

Related Questions