2016-04-27 15 views
2

Ich habe gerade angefangen zu lernen Haskell, und habe ein paar Probleme online getan. Die meiste Zeit kann ich die Lösung herausfinden, aber ich kann es nicht in dem erwarteten Ausgabeformat ausdrucken.Drucken Pascals Dreieck in Haskell

Zum Beispiel habe ich versucht, ein Pascal-Dreieck-Programm zu tun. Ich habe herausgefunden, wie man Pascal's Triangle als eine Liste von Ints-Listen generiert, aber ich kann nicht herausfinden, wie man es druckt.

Hier ist mein 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 

Derzeit ist die Ausgabe wie

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

ich es in der Form dieses

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

Wie kann ich tun, um zu drucken? Ich habe versucht, Dinge wie mapM_ oder intercalate "" zu verwenden, ohne Glück. Ich bin noch nicht in Monaden, also verstehe ich nicht, wie mapM funktioniert.

+0

Keine Notwendigkeit, Monaden dafür wirklich zu verstehen. 'f = hebt ab. map (intercalate "". map show) 'erzeugt den gewünschten' String' Wert aus einem '[[Int]]' Wert; Übergeben Sie einfach das Ergebnis an 'putStr'. – Jubobs

+3

und 'intercalate" "' ist nur 'unwords' - du bekommst es mit' putStr. unlines. Karte (unwords. Karte anzeigen) ' – Carsten

+0

Aah schön. Ich vermischte Zeilen und Linien und ordnete alles falsch an. Ich habe 'show' nicht richtig benutzt. Vielen Dank! –

Antwort

3

Es gibt verschiedene Möglichkeiten, dies zu tun, aber das einfachste (IMO) ist das Folgende.

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

Dieser erste wandelt alle der Zahlen in der Liste in Strings (mit show). Dann konvertiert es die innersten Listen in Zeichenfolgen, wobei jedes Element durch Leerzeichen getrennt ist (intercalate " "). Dann konvertiert es die äußerste Liste in eine Zeichenkette, in der jedes Element durch eine Newline (unter Verwendung intercalate "\n") getrennt wird. Und schließlich schiebt er die resultierende Zeichenfolge auf stdout. Ersetzen Sie die letzte Zeile Ihres main damit und es sollte tun, was Sie wollen.

EDIT: Wie Yakym in seiner Antwort erwähnt, intercalate " " und intercalate "\n" mit unwords und unlines, so dass der Code über etwas prägnanter (es auch für die Einfuhr von Data.List beseitigt die Notwendigkeit) ersetzt werden.

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

Ich änderte putStrLn-putStr weil unlines automatisch eine neue Zeile an das Ende der Ausgabe hinzufügt.

2

Es gibt auch Funktionen wie unlines und unwords, die natürliche Interkalation auf String-Listen durchführen.

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 
+2

'[0] ++ Zeile' könnte zu' 0: Zeile' vereinfacht werden –

+0

Sie haben Recht; Ich lieh mir die Zeile aus dem Haskell-Wiki https://wiki.haskell.org/Blow_your_mind - ich nehme an, die obige Version ist wegen der Symmetrie. –