DrRacket 组合列表

发布于 2024-12-16 14:26:25 字数 512 浏览 3 评论 0原文

我希望有人能引导我走向正确的方向: 我正在寻找两个产生两个列表中所有可能的项目组合:
示例:
给定列表 '(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

好多鱼好多余 2024-12-23 14:26:25

您在这里看到的是两个复杂参数的递归, 《如何设计程序》第 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.

荆棘i 2024-12-23 14:26:25

我想到了另一种可能的方法来解决这个问题。这里有一个提示:

(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,它根本没有改变。

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

I thought of another possible way to solve the problem. Here's a hint:

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

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.

明明#如月 2024-12-23 14:26:25

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

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

现在看来您想通过 list2 上的 foldr 来解决这个问题。

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

foldr 需要 step :: a -> b-> b 和 a start :: b。由于我们希望最终结果是一个[Pair],这意味着b = [Pair]。那么 start 可能会是空列表。由于 list2 填充了 [a] 槽,这意味着 a = Number。因此,对于我们的问题,step :: Number -> [对]-> [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,然后将它们拍打到到目前为止的结果。 这是我的代码开始与您的代码不同的点。

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)]

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".

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

Now it looks like you want to approach this problem with a foldr over list2.

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

foldr requires a step :: a -> b -> b and a start :: b. Since we want the final result to be a [Pair], that means that b = [Pair]. start will probably be the empty list, then. Since list2 fills the [a] slot, that means that a = Number. Therefore for our problem, 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 = []

So far this is the same as the foldr that you wrote, except I haven't defined the step yet. So what is the step function? From the type, we know it must take a Number and a [Pair] and produce a [Pair]. But what do these inputs mean? Well the Number input will be some element of list2. And the [Pair] input will be the "result of the fold so far". So we'll want to take our Number, and do something to create the Pairs for it, and then slap those onto the result so far. This is the point at which my code begins to differ from yours.

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

Since you, using Racket, will probably define doSomething as an anonymous function, that means list1 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.

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

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)].

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文