如何在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