Haskell:列表的最小总和

时间:2011-05-23 19:14:25

标签: haskell

所以,我是新来的,我想问一些关于某些代码的问题:

  1. 将列表中的每个元素复制n次。例如,重复[1,2,3]应该提供[1,2,2,3,3,3]

    duplicate1 xs = x*x ++ duplicate1 xs
    

    这里有什么问题?

  2. 从列表中取正数并找到最小正减法。例如,[-2,-1,0,1,3]应该1,因为(1-0)0以上的最低差异。

5 个答案:

答案 0 :(得分:4)

对于你的第一部分,有一些问题:你忘记了第一个参数中的模式,你试图平方第一个元素而不是复制它,并且没有第二个案例来结束你的递归(它会崩溃) )。为了提供帮助,这是一个类型签名:

replicate :: Int -> a -> [a]

对于你的第二部分,如果你的课程已经涉及,你可以尝试列表理解来获得数字的所有差异,然后你可以应用minimum函数。如果您不了解列表推导,则可以使用concatMap执行类似操作。

不要忘记您可以查看http://www.haskell.org/hoogle/(Hoogle)或类似搜索引擎上的功能。

告诉我你是否需要更全面的答案。

答案 1 :(得分:1)

关于你的第一个问题:

  • 使用模式匹配。你可以写duplicate (x:xs)之类的东西。这将解构参数列表的第一个单元格。如果列表为空,则尝试下一个模式:

     duplicate (x:xs) = ... -- list is not empty
     duplicate []     = ... -- list is empty
    
  • 函数replicate n x创建一个包含nx的列表。例如replicate 3 'a'产生'['a','a','a']。

  • 使用递归。要理解递归是如何工作的,首先要理解递归的概念很重要;)

答案 2 :(得分:0)

1)

dupe :: [Int] -> [Int]
dupe l = concat [replicate i i | i<-l]

你的一些问题,一个问题是你正在平衡每个术语,而不是创建一个新列表。此外,您的模式匹配已关闭,您将创建无限递归。请注意您如何递归到与输入完全相同的列表。我认为你的意思是duplicate1 (x:xs) = (replicate x x) ++ duplicate1 xs的意思,只要你写一个合适的基础案例就可以了。

2)

这可以从您的问题描述中直接进行,但可能效率不高。首先过滤掉负数,然后检查所有减法,并给出非负结果。答案是这些

的最小值
p2 l = let l2 = filter (\x -> x >= 0) l 
        in minimum [i-j | i<-l2, j<-l2, i >= j]

这里的问题是它会允许一个数字与自身相关联,这会导致总是为零的答案。有任何想法吗?我想把它留给你,评论者还有一点需要用勺子喂食。

答案 3 :(得分:0)

在这里,这应该可以解决问题:

dup [] = []
dup (x:xs) = (replicate x x) ++ (dup xs)

我们递归地定义dup:对于空列表,它只是一个空列表,对于非空列表,它是一个列表,其中前x个元素等于x(初始列表的头部),其余的是通过递归应用dup函数生成的列表。通过归纳很容易证明这种解决方案的正确性(将其作为练习)。

现在,让我们分析您的初始解决方案:

duplicate1 xs = x*x ++ duplicate1 xs

第一个错误:您没有正确定义列表模式。根据你的定义,函数只有一个参数 - xs。要获得所需的效果,您应该使用正确的模式来匹配列表的头部和尾部(x:xs,请参阅我之前的示例)。阅读模式匹配。

但这不是全部。第二个错误:x * x实际上是x平方,而不是两个值的列表。这带来了第三个错误:++期望它的两个操作数都是相同类型的值列表。在您的代码中,您尝试将++应用于两个类型Int[Int]的值。

至于第二项任务,已经给出了解决方案。

HTH

答案 4 :(得分:0)

1)您可以使用list是monad的事实:

dup = (=<<) (\x -> replicate x x)

或者用符号表示:

dup xs = do x <- xs; replicate x x; return x

2)要从列表中仅获取正数,您可以使用过滤器:

filter (>= 0) [1,-1,0,-5,3]
-- [1,0,3]   

要获得所有可能的“配对”,您可以使用monad或applicative functor:

import Control.Applicative
(,) <$> [1,2,3] <*> [1,2,3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]

当然,在(,)替换(-)时,您可以直接生成对,而不是创建对。现在您需要再次过滤,丢弃所有零或负差异。然后你只需要找到列表的最小值,但我认为你可以猜出该函数的名称。