1

我需要在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 函数中的情况,但我不知道如何解决它。此外,字符不考虑在它们之前打印的字符。任何有关如何解决此问题的帮助将不胜感激。

4

2 回答 2

3

前段时间我写了一个小脚本,它采用制表符分隔的表格(CSV 样式)并将其漂亮地打印到控制台。我已经提取了相关部分并在此处上传了源代码。例如,给定您的输入

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

putStrLn $ showMat m会变成

  1  -500 -4
100 15043  6
  5     3 10

如果您想要左对齐,那么在最底部还有一个功能(已注释掉)。

于 2012-10-27T18:43:04.650 回答
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//而不是显式编写递归zipWithzipWith3因为它使代码更容易理解。

于 2012-10-27T17:20:42.843 回答