使用Haskell的替代系列

时间:2017-09-14 19:42:13

标签: list haskell sum

我正在尝试使用Haskell读入列表并执行交替序列,因此从第一个元素添加其他元素并从第二个元素中减去所有其他元素开始。例如[1,2,3,4]将是1-2 + 3-4 = -2。我以为我已经想出了如何为特定长度的列表执行此操作(我编写它以容纳空列表并列出最多4个元素的长度),但它没有按照我的想法执行。它只返回列表中的第一个元素。这就是我所拥有的:

altSeries :: Num a => [a] -> a
altSeries [] = 0
altSeries (x:xs) = if length xs == 1 then x
                   else if length xs == 2 then x
                   else if length xs == 3 then (x - xs!!1 + xs!!2)
                   else (x - xs!!1 + xs!!2 - xs!!3)

另外,如果我想使用任何列表大小怎么办?

2 个答案:

答案 0 :(得分:4)

我认为很明显,这个解决方案无法扩展:即使你将函数写入长度为千的列表,它也会从有人输入千列表的那一刻开始打破一个要素。

列表处理通常以递归完成:我们处理列表的 head (或第一个 k 头),并执行递归列表的尾部。此外,我们有许多 basecases (可以是一个)来终止递归。

您已经提供了一个基本案例:空列表:

altSeries [] = 0

如果我们输入一个空列表,很明显我们应该返回0。现在我们可能会问,如果我们获得长度为1的列表该怎么做:在这种情况下,列表的形状为[x]。因此,在这种情况下,我们应该返回x,因为我们应该添加x,并且不能减去第二个数字。所以我们补充说:

altSeries [x] = x

现在问题是如何处理长度为2或更长的列表。在这种情况下,列表具有模式(x1:x2:t),第一个元素为x1,第二个元素为x2,剩余元素为t。根据您的说明,我们应该计算x1-x2并添加altSeries t

altSeries (x1:x2:t) = x1 - x2 + altSeries t

这是有效的,因为altSeries将递归提取x3x4,因此它将递归到:

altSeries [x1,x2,x3,x4,x5] = x1 - x2 + altSeries [x3,x4,x5]
                           = x1 - x2 + x3 - x4 + altSeries [x5]
                           = x1 - x2 + x3 - x4 + x5

所以完整的实现是:

altSeries :: Num n => [n] -> n
altSeries [] = 0
altSeries [x] = x
altSeries (x1:x2:t) = x1 - x2 + altSeries t

答案 1 :(得分:4)

你想要的是一个最终看起来像这个[1,-1]的列表,你可以总结。

您可以列出交替标志let alternatingSigns = cycle [1,-1]。使用.Last.value函数可以使其无限。 [1,2,3,4]

要转换zipWith (*) alternatingSigns input列表,您可以使用您的列表压缩无限的交替列表,如altSeries :: Num a => [a] -> a altSeries input = let alternatingSigns = cycle [1,-1] in sum $ zipWith (*) alternatingSigns input

整个功能看起来像这样:

library('scatterplot3d')
rx <- c(0,100, -80)
ry <- c(24.6,-19,14)
rz <- c(-2.1,3,-10)
axlim <- 120
spo <- scatterplot3d(rx, y=ry, z=rz, xlim = c(-axlim, axlim), ylim = c(-axlim, axlim), zlim = c(-axlim, axlim))