DrRacket结合列表

时间:2011-11-19 00:47:09

标签: racket cartesian-product

我希望有人可以指导我朝着正确的方向前进: 我正在寻找两个产生所有可能的项目组合的两个列表:
例如:
鉴于列表'(symbol1 symbol2)和'(1 2),我希望产生:
(列表(列表'symbol1 1)(列表'symbol1 2)(列表'symbol2 1)(列表符号2 2))

到目前为止我的代码是:

    (define (combiner list1 list2)
    (list
      (foldr (lambda (a b) (foldr (lambda (c d) (list a c)) empty list1)) empty list2)
      (foldr (lambda (a b) (foldr (lambda (c d) (list b d)) empty list1)) empty list2)))

这显然不起作用,也没有其他一些我尝试过的方法。我在使用两个列表上的隐式递归时遇到了麻烦 - 任何想法?

3 个答案:

答案 0 :(得分:4)

您在这里看到的是两个复杂参数的递归,section 17如何设计程序。如果你想要另一个提示,我会告诉你这三种情况中的哪一种。

答案 1 :(得分:1)

我想到了解决问题的另一种可行方法。这是一个提示:

(define (combiner list1 list2)
  (define (combine l1 l2)
    (cond ((empty? l1) empty)
          ((empty? l2) XXX)
          (else (cons YYY
                      ZZZ))))
  (combine list1 list2))

在上面的代码中,您必须找出三个问题的答案:

  • XXX当你完成对第二个列表的迭代时,如何推进递归,但是第一个列表仍然有元素,你还希望在第一个列表中前进一个元素?
  • YYY您如何将第一个列表中的元素与第二个列表中的元素组合在一起?
  • ZZZ当两个列表仍然有剩余元素时,如何推进递归,但此时你只对推进第二个列表感兴趣?

最后一个提示:请注意,在某些时候你需要“重新启动”第二个列表,为此,你可以参考原来的list2,它根本没有改变。

我希望这会对你有所帮助,我不想给你一个直接的答案(我) - 我希望你自己找出解决方案。

答案 2 :(得分:0)

似乎有一件事可以增加混淆是list的自由使用。我将开始使用Haskell表示法来解决您的问题。 ::表示“有类型”,[Foo]表示“列表Foo”。

list1 :: [Symbol]
list2 :: [Number]
type Pair = (Symbol, Number)
(combiner list1 list2) :: [Pair]

现在看来你想用foldr over list2来解决这个问题。

foldr :: (a -> b -> b) -> b -> [a] -> b

foldr需要step :: a -> b -> bstart :: b。由于我们希望最终结果为[Pair],这意味着b = [Pair]。那么start可能是空列表。由于list2填充[a]广告位,这意味着a = Number。因此,对于我们的问题,step :: Number -> [Pair] -> [Pair]

combiner :: [Symbol] -> [Number] -> [Pair]
combiner list1 list2 = foldr step start list2
  where step :: Number -> [Pair] -> [Pair]
        step a b = undefined
        start = []

到目前为止,这与您编写的foldr相同,但我还没有定义step。那么步功能是什么?从类型来看,我们知道必须使用Number[Pair]并生成[Pair]。但这些输入意味着什么?那么Number输入将是list2的一些元素。 [Pair]输入将是“到目前为止的结果”。 因此,我们需要使用Number,然后执行某些内容为其创建Pair,然后将其打到目前为止的结果上。< / strong>这是我的代码与您的代码开始不同的地方。

step a b = append (doSomething a) b
doSomething :: Number -> [Pair]
doSomething a = undefined

由于您使用Racket,可能会将doSomething定义为匿名函数,这意味着list1在范围内。 (因为它在Haskell中的函数的where子句中,所以它在范围内)。您可能会使用该列表来生成组合。

doSomething a = ... a ... list1 ...

实施doSomething留给读者一个练习,就像转换回Racket一样。请注意,我在此处定义的Haskell函数的类型签名combiner可以推广到[a] -> [b] -> [(a,b)]