如何在Haskell中将整数列表转换为真假矩阵

时间:2015-11-29 17:58:19

标签: haskell

在本练习中,我应该编写一个函数,它接收一个整数列表作为参数,并给出一个矩阵或列表列表。制作矩阵的要点是整数表示矩阵的每个中的True个数。例如

[2,4,1]

必须翻译为:

enter image description here

在系统中将其表示为列表列表:

[ [0,1,0], [0,1,0], [1,1,0], [1,1,1] ]

由于按列操作矩阵(列表列表)并不容易,我使用了一个技巧并使用transpose将矩阵向左旋转了90度,这使得矩阵如下所示: / p>

enter image description here

然后我开发了以下算法来解决问题:

  1. 获取输入列表的第一个元素
  2. 创建一个长度为maximum xs的列表(每个列表的长度等于列表中的最大元素)
  3. 在第一个元素确定的列表中放置了这么多True
  4. 使用False
  5. 填写列表的其余部分
  6. 对所有元素执行相同操作并旋转矩阵
  7. 我试图实现两个解决方案,但每个解决方案都有一个我无法解决的问题:

    1. 这个适用于第一个元素,但我不知道如何将它应用于输入列表的所有元素

      listToMatrix x = (replicate ((maximum x) - (head x)) False) ++ (replicate (head x) True)`
      
    2. 这适用于所有元素但不能保留内部列表的长度,因此列表的长度不同。

      listToMatrix lst@(x:xs) = ((replicate ((maximum lst) - x) False) ++ (replicate x True)) : listToMatrix xs`
      
    3. 问题1 :如何使用最少的更改使这些功能正常工作?

      问题2 :更优雅,更紧凑的解决方案?

      P.S。我在矩阵中使用了1和0来使它们更具可读性,但它们实际上是真和假

2 个答案:

答案 0 :(得分:3)

我会使用以下方法,与您的方法兼容。

正如您所建议的那样,我们最后使用transpose,因为转置矩阵看起来更容易生成。

f :: [Int] -> [[Bool]]
f xs = transpose (...)

然后,xs的每个元素都必须生成一个新行。我们可以使用列表推导(在下面完成),也可以使用map

f :: [Int] -> [[Bool]]
f xs = transpose [ row x | x <- xs ]
  where row :: Int -> [Bool]
        row x = ...

根据您的建议,我们还需要maximum来生成每一行,因此我们只计算一次:

f :: [Int] -> [[Bool]]
f xs = transpose [ row x | x <- xs ]
  where m = maximum xs
        row :: Int -> [Bool]
        row x = ...   -- we know x and m, we need m-x Falses and x Trues

现在,您只需要调整代码。

答案 1 :(得分:3)

我就是这样做的:

toMatrix' :: [[Bool]] -> [Int] -> [[Bool]]
toMatrix' acc xs
    | or  bools = toMatrix' (bools : acc) (map pred xs)
    | otherwise = acc
    where bools = map (> 0) xs

toMatrix :: [Int] -> [[Bool]]
toMatrix = toMatrix' []

简单明了。无需转置。

这是我的程序的可视化。我将01分别用于FalseTrue

toMatrix [2,4,1] = toMatrix' []                                [ 2, 4, 1]
                 = toMatrix' [[1,1,1]]                         [ 1, 3, 0]
                 = toMatrix' [[1,1,0],[1,1,1]]                 [ 0, 2,-1]
                 = toMatrix' [[0,1,0],[1,1,0],[1,1,1]]         [-1, 1,-2]
                 = toMatrix' [[0,1,0],[0,1,0],[1,1,0],[1,1,1]] [-2, 0,-3]
                 = [[0,1,0],
                    [0,1,0],
                    [1,1,0],
                    [1,1,1]]

当我们致电toMatrix' acc xs时,我们首先计算bools = map (> 0) xs。如果bools的所有元素都是False,那么我们就完成了。我们简单地返回acc。否则,我们会将bools添加到acc的开头,并从xs的每个元素中减去一个。冲洗并重复。

无需跟踪xs的最大元素,也无需转置矩阵。简单。