Reputation: 23
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
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
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