2012-10-27 94 views
0

我需要打印在Haskell矩陣,所以它看起來是這樣的:打印矩陣哈斯克爾

main> putStr (showMat [[1,-500,-4], [100,15043,6], [5,3,10]]) 
     1 -500 -4 
    100 15043 6 
     5  3 10 

到目前爲止,我想出了這一點:

type Matrix a = [[a]] 
type IntMat = Matrix Integer 

showMat :: IntMat -> String 
showMat [] = "" 
showMat ((y:ys):xs) = (printRow (rowmaxs) (elements) (y:ys)) ++ "\n" ++ showMat xs 
    where rowmaxs = rowMaxs ((y:ys):xs) ; elements = elementLengths (y:ys) 

rowMaxs :: IntMat -> [Int] 
rowMaxs [] = [] 
rowMaxs (x:xs) = [length (show (maximum (x)))] ++ (rowMaxs xs) 

elementLengths :: [Integer] -> [Int] 
elementLengths [] = [] 
elementLengths (y:ys) = [length (show y)] ++ (elementLengths ys) 

printRow :: [Int] -> [Int] -> [Integer] -> String 
printRow [] (a:as) (y:ys) = "" 
printRow (z:zs) (a:as) [] = "" 
printRow [] [] (y:ys)  = "" 
printRow [] [] []   = "" 
printRow (z:zs) (a:as) (y:ys) = addSpaces (z-a) ++ show y ++ [' '] ++ printRow zs as ys 

addSpaces :: Int -> String 
addSpaces 0 = "" 
addSpaces n = " " ++ addSpaces (n-1) 

它返回這樣的:

Main> putStr (showMat [[1,23,1],[23,56,789],[1234,0,1]]) 
     1 23 1 
     23 56 
    1234 

我可以看到在行結束元素的損失是由於在printRow功能的情況下,但我不知道怎麼牛逼o修復它。這些角色也不會考慮在他們之前打印的角色。任何幫助我如何解決這個問題將不勝感激。

回答

1

showMat你計算每行rowmaxselements。特別地,rowmaxs具有矩陣中每個行左邊的元素,但是printRow使用它作爲矩陣的每個的含義。

編輯:這裏有一個稍微好一點的版本showMat

showMat :: IntMat -> String 
showMat rows = concat (map perRow rows) 
    where rowmaxs = rowMaxs rows 
     perRow cols = printRow rowmaxs elements cols ++ "\n" 
      where elements = elementLengths cols 

它仍然是越野車--- rowMaxs(試圖)計算每一行的數字的最大長度,但你真正想要的每列中數字的最大長度。這方面的一個後果是,你偶爾傳遞負數addSpaces,不應對非常好,所以這裏的addSpaces一個版本的行爲更優雅:

addSpaces :: Int -> String 
addSpaces n = replicate n ' ' 

所以,現在我們得到這個:

*Main> putStr (showMat [[1,23,1],[23,56,789],[1234,0,1]]) 
1 23 1 
23 56 789 
1234 0 1 

更好,但尚未正常工作。

我還沒有修復代碼中的所有錯誤,因爲我覺得你還在學習,需要爲自己找到它們的經驗。

我建議使用map/zipWith/zipWith3而不是明確寫入遞歸,因爲它使代碼更容易理解。

+0

對,我弄明白了這些事情。我如何計算一次? – Joe

+0

@ user1762909看我的編輯。 – dave4420

+0

謝謝你。你是對的,我仍在學習,但我現在應該能夠修復最後幾個錯誤。 – Joe

2

前段時間我寫了一個小腳本,它採用製表符分隔的表格(CSV樣式)並將其打印到控制檯。我已經提取了相關部分並上傳了源代碼here。例如,假設您輸入

m = [[1,23,456],[78,-90,123],[4567,8,9]] 

putStrLn $ showMat m將使它成爲

1 -500 -4 
100 15043 6 
    5  3 10 

有在最底層也是一個函數(註釋掉)如果你想左對齊。