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

如何在Haskell中将整数列表转换为真与假矩阵,haskell,Haskell,在本练习中,我将编写一个函数,该函数接收整数列表作为参数,并给出矩阵或列表。制作矩阵的要点是,整数表示矩阵每列中Trues的数量。比如说 [2,4,1] 必须翻译为: 在系统中以列表列表的形式表示: [ [0,1,0], [0,1,0], [1,1,0], [1,1,1] ] 由于按列操作矩阵(列表列表)不容易,我使用了一个技巧,使用转置将矩阵向左旋转90度,使矩阵如下所示: 然后我开发了以下算法来解决这个问题: 取输入列表的第一个元素 创建长度最大xs的列表(每个列表的长度等于列表中的

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

[2,4,1]
必须翻译为:

在系统中以列表列表的形式表示:

[ [0,1,0], [0,1,0], [1,1,0], [1,1,1] ]
由于按列操作矩阵(列表列表)不容易,我使用了一个技巧,使用
转置将矩阵向左旋转90度,使矩阵如下所示:

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

  • 取输入列表的第一个元素
  • 创建长度
    最大xs
    的列表(每个列表的长度等于列表中的最大元素)
  • 根据第一个元素确定的数量,在列表中放入
    True
  • False
  • 对所有元素执行相同操作并旋转矩阵
  • 我曾尝试实施两种解决方案,但每种解决方案都有一个我无法解决的问题:

  • 这一个对第一个元素很好,但我不知道如何将它应用于输入列表的所有元素

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

    listToMatrix lst@(x:xs) = ((replicate ((maximum lst) - x) False) ++ (replicate x True)) : listToMatrix xs`
    
  • 问题1:如何使这些功能在进行最小更改的情况下工作

    问题2:是否有更优雅、更紧凑的解决方案


    另外,我在矩阵中使用了1和0,以使它们更具可读性,但它们实际上是真的和假的

    我将使用以下方法,这与您的方法兼容

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

    f :: [Int] -> [[Bool]]
    f xs = transpose (...)
    
    然后,
    xs
    的每个元素都必须生成一个新行。我们可以使用列表理解(如下所示),也可以使用
    map

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

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

    我将这样做:

    toMatrix'::[[Bool]]->[Int]->[[Bool]]
    toMatrix'acc xs
    |或bools=toMatrix'(bools:acc)(映射pred-xs)
    |否则=acc
    其中bools=map(>0)xs
    toMatrix::[Int]->[[Bool]]
    toMatrix=toMatrix'[]
    
    简单明了。不需要换位

    这是我的程序的可视化。我将分别使用
    0
    1
    表示
    False
    True

    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
    的最大元素,也无需转置矩阵。很简单。

    这是一种项目。为什么?嗯,至少它显示了努力,不像大多数家庭作业问题。它不是简单地问“给我代码”,而是提供了一个解决方案的尝试。换位是简化这类生成矩阵问题的一种好方法,但在这种情况下,我认为对于原始的非换位形式存在一个简单的解决方案。也许这会有所帮助:有一种方法可以使用嵌套在另一个列表理解(也称为嵌套在另一个映射中的映射)中的列表理解生成所需的矩阵。另一个提示:预先计算最大值并将其存储起来,这样就不会一次又一次地支付该成本。这是一个很好的答案,总结一下你为什么用这种方式构建它会使它变得更好。这将从OP文章中的示例中生成颠倒的矩阵。如果不是对源数组中的各个元素进行倒计时,而是传递一个从最大值开始并最终达到0的额外倒计时,并用该倒计时是否小于或等于源元素来填充每个元素,则得到正确的顺序。@SebastianRedl否。它生成的矩阵面朝上。我知道这一点,因为我编写了函数并对其进行了测试。你应该自己测试一下。很好的补充+1完整性!它工作得很好。感谢您的详细解释:)
    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