DrRacket 组合列表
我希望有人能引导我走向正确的方向: 我正在寻找两个产生两个列表中所有可能的项目组合:
示例:
给定列表 '(symbol1 symbol2) 和 '(1 2),我希望生成:
(list (list 'symbol1 1) (list 'symbol1 2) (list 'symbol2 1)(list symbol2 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)))
这显然不起作用,我尝试过的其他一些方法也不起作用。我在处理两个列表上的隐式递归时遇到问题 - 有什么想法吗?
I was hoping someone could guide me in the right direction:
I am looking two produce all possible combinations of items in two lists:
Example:
Given the lists '(symbol1 symbol2) and '(1 2), I am looking to produce:
(list (list 'symbol1 1) (list 'symbol1 2) (list 'symbol2 1)(list symbol2 2))
My code thus far is:
(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)))
This clearly isn't working, and neither are a few other methods I've tried. I am having trouble working with the implicit recursion on two lists - any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您在这里看到的是两个复杂参数的递归, 《如何设计程序》第 17 节。如果您需要其他提示,我会告诉您这是三种情况中的哪一种。
What you're looking at here is recursion on two complex arguments, section 17 of How To Design Programs. If you want another hint, I'll tell you which of the three cases this is.
我想到了另一种可能的方法来解决这个问题。这里有一个提示:
在上面的代码中,您必须找出三个问题的答案:
XXX
当您完成对第二个列表的迭代后,如何推进递归,但是第一个列表仍然有元素,并且您还想在第一个列表中前进一个元素吗?YYY
如何将第一个列表中的元素与第二个列表中的元素组合起来?ZZZ
当两个列表仍有剩余元素时,如何推进递归,但此时您只对推进第二个列表感兴趣?最后一个提示:请注意,在某些时候您需要“重新启动”第二个列表,为此,您可以参考原始的
list2
,它根本没有改变。我希望这对你有帮助,我不想给你一个直接的答案(还) - 我希望你自己找出解决方案。
I thought of another possible way to solve the problem. Here's a hint:
In the above piece of code, you'll have to figure out the answer to three questions:
XXX
How do you advance the recursion when you've finished iterating over the second list, but the first list still has elements, and also you want to advance one element in the first list?YYY
How would you combine an element from the first list with an element from the second list?ZZZ
How do you advance the recursion when both lists still have elements left, but at this point you're only interested in advancing over the second list?One last hint: notice that at some point you need to "restart" the second list, for that, you can refer to the original
list2
, which has not changed at all.I hope this helps you, I don't want to give you a straight answer (yet) - I want you to figure out the solution by yourself.
似乎这里会增加混乱的一件事是
list
的自由使用。我将开始使用 Haskell 类型表示法来解决您的问题。::
表示“有类型”,[Foo]
表示“Foo 列表”。现在看来您想通过 list2 上的
foldr
来解决这个问题。foldr 需要
step :: a -> b-> b
和 astart :: b
。由于我们希望最终结果是一个[Pair]
,这意味着b = [Pair]
。那么start
可能会是空列表。由于 list2 填充了[a]
槽,这意味着a = Number
。因此,对于我们的问题,step :: Number -> [对]-> [Pair]到目前为止,这与您编写的
foldr
相同,只是我尚未定义step
。那么什么是阶跃函数呢?从类型中,我们知道它必须采用一个Number
和一个[Pair]
并生成一个[Pair]
。但这些输入意味着什么?那么Number
输入将是list2
的某个元素。[Pair]
输入将是“到目前为止折叠的结果”。 因此,我们需要获取Number
,并执行一些操作来为其创建Pair
,然后将它们拍打到到目前为止的结果。 这是我的代码开始与您的代码不同的点。由于您使用 Racket 可能会将
doSomething
定义为匿名函数,这意味着list1
在范围内。 (因为它位于 Haskell 函数的 where 子句中,所以它在作用域内)。您可能会使用该列表来生成组合。实现
doSomething
留给读者作为练习,就像翻译回 Racket 一样。请注意,我在此处定义的 Haskell 函数的类型签名combiner
可以概括为[a] -> [b]-> [(a,b)]
。It seems that one thing that can add to confusion here is the liberal use of
list
. I'm going to start approaching your problem using Haskell notation for types.::
means "has type", and[Foo]
means "list of Foo".Now it looks like you want to approach this problem with a
foldr
over list2.foldr requires a
step :: a -> b -> b
and astart :: b
. Since we want the final result to be a[Pair]
, that means thatb = [Pair]
.start
will probably be the empty list, then. Since list2 fills the[a]
slot, that means thata = Number
. Therefore for our problem,step :: Number -> [Pair] -> [Pair]
So far this is the same as the
foldr
that you wrote, except I haven't defined thestep
yet. So what is the step function? From the type, we know it must take aNumber
and a[Pair]
and produce a[Pair]
. But what do these inputs mean? Well theNumber
input will be some element oflist2
. And the[Pair]
input will be the "result of the fold so far". So we'll want to take ourNumber
, and do something to create thePair
s for it, and then slap those onto the result so far. This is the point at which my code begins to differ from yours.Since you, using Racket, will probably define
doSomething
as an anonymous function, that meanslist1
is in scope. (Since it is in the where clause of the function in Haskell, it is in scope). You will probably use that list to generate the combinations.Implementing
doSomething
is left as an exercise for the reader, as is translating back into Racket. Note that the type signature for the Haskell function that I'm defining here,combiner
, can be generalized to[a] -> [b] -> [(a,b)]
.