如何计算连续对的差异乘积?

时间:2015-11-09 18:41:16

标签: haskell

我必须在具有此函数定义f :: [Int] -> Int的列表中计算每个连续对的差异之间的乘积,例如:

f [3, 1, 4, 2, 5] = (3 - 1) * (1 - 4) * (4 - 2) * (2 - 5) 
                  = 36

我必须递归地执行此操作,我知道如何处理数组中元素的产品,但是如何从列表中选择元组并将它们的差异乘以下一个元组的差异,任何提示都将受到赞赏。到目前为止,我有这个:

f :: [Int] -> Int
f [] = 1
f (x:xs) = x * f xs

但这只给了我元素的产物。

4 个答案:

答案 0 :(得分:5)

使用对

创建中间结构
a = [3, 1, 4, 2, 5]
zip a (tail a)

或更好地使用

zipWith (-) a (tail a)

将为您提供差异并继续使用该产品。

如果需要实现自己的递归解决方案,则需要逐个使用输入元素。基本情况应该很容易,您必须考虑null情况和单个元素的情况(可能是相同的!)

附加提示,为此基本案例编写函数

f (x:y:xs) = (x-y) * f ???

和这个终端案例(如果行为相同,可能会合并)。

f [] = ???
f [x] = ???

答案 1 :(得分:2)

怎么样:

import Data.List

f l = product [a-b | (a:b:_) <- tails l ]

该函数的工作方式如下:tails生成 - 顾名思义 - 给定列表l的所有尾部,因此对于[3, 1, 4, 2, 5][[3,1,4,2,5],[1,4,2,5],[4,2,5],[2,5],[5],[]] (a:b:_) }。现在我们使用a进行模式匹配,这意味着只会考虑包含至少两个项目的列表,此外前两个元素将与ba-b统一。现在我们使用[3,1,4,2,5]生成一个新列表。因此[2,-3,2,-3]的列表为f。现在你只需拿走产品。

修改

Num a => [a] -> a的签名是[Int] -> Int,比import Data.List f :: [Int] -> Int f l = product [a-b | (a:b:_) <- tails l ] 更通用。因此,您可以简单地通过以下方式向下转发:

FOO='Hi" a/b/c:'
BAR='hello'

if [ "$FOO" == "$BAR" ] ; then
  echo "yes"
fi

答案 2 :(得分:2)

注意:这篇文章是用literate Haskell写的。您可以将其保存为ListProduct.lhs并在GHCi中尝试。

为了修复你的功能,我们必须考虑一些情况。首先,如果列表为空,会发生什么?我们返回1

> f :: [Int] -> Int
> f [] = 1

现在,我们必须考虑具有更多元素的列表。例如,列表可以包含至少一个元素:

f (x:xs) = ...

然而,这并不是真的有用。我们需要两个个连续元素,以便相互减去它们。但是,我们可以通过模式再次匹配剩余列表来实现:

f (x : (y : xs))

f (x : y : xs)相同,因为(:)是右关联的。我们最终得到:

> f (x : y : xs) = (x - y) * f rest

其余的是什么?它不能是xs。如果我们使用xs,我们就无法在以下情况下获得正确的结果:

f [1,2,3,4] = (1 - 2) * f [3,4]
            = (1 - 2) * (3 - 4) * f []
            --      ^^^^^^ 
            --      (2 - 3) is missing!

因此rest需要同时拥有y xs

>      where rest = y : xs

我们可以确认这是按预期工作的:

f [1,2,3,4] = (1 - 2) * f [2,3,4]
            = (1 - 2) * (2 - 3) * f [3,4]
            = (1 - 2) * (2 - 3) * (3 - 4) * f [4]

因此,正确处理我们至少有两个元素的情况。

我们只有一个元素的列表怎么样?好吧,有一个元素,你不能减去另一个元素。正如您在上面所看到的那样,我们总会在f [x]处为某些x提供f [x] = 1。因此,明智的选择是f [a] = 1

_

但是,由于我们实际上并不关注该元素,因此我们可以将> f _ = 1 用作通配符

f []

请注意,这与f的结果相同。所以我们可以将f :: [Int] -> Int f (x : y : xs) = (x - y) * f (y : xs) f _ = 1 写成

True

但这取决于你。

锻炼

  • 编写一个函数,为具有两个元素的列表返回length。请勿使用True,仅使用模式匹配。
  • 编写一个函数,对于包含至少四个元素的列表返回False,否则返回f [1,2,3,4,5] = (1 * 2 * 3) + (2 * 3 * 4) + (3 * 4 * 5) 。仅使用模式匹配,不使用其他功能。

  • 编写一个返回三连续产品总和的函数,例如

    #m1 li {
    list-style: none;
    display: inline-block;
    padding-right: 18px;
    padding-left: 18px;
    font-size: 18px;
    }
    
    #m2 li {
    list-style: none;
    display: inline-block;
    padding-right: 18px;
    padding-left: 18px;
    font-size: 18px;
    }
    
    #m1 {
    display: inline-block;
    float: left;
    }
    
    #m2 {
    display: inline-block;
    float: left;
    }

答案 3 :(得分:0)

虽然这种问题通常更容易拉链,但折叠工作也是如此:

f (x:xs) = fst $ foldl (\(p,n) m -> (p*(n-m),m)) (1,x) xs