(Scheme) Recursive function to compute all possible combinations of some lists?

邮差的信 提交于 2019-12-19 04:14:30

问题


What is an example of a recursive function to compute all possible combinations of lists? For example, (combine (list 1 2 3) (list 1 2)) should return '((1 1) (1 2) (2 1) (2 2) (3 1) (3 2)).


回答1:


Here's my solution. Requires SRFIs 1 and 26 to be available.

(define (cartesian-product first . rest)
  (define (iter l result)
    (define (prepend-all x)
      (map (cut cons <> x) l))
    (concatenate (map prepend-all result)))
  (map reverse (fold iter (map list first) rest)))



回答2:


Here's my take; I first define a helper concat/map, which takes a list and a function. Like regular map, it applies that function to each element in the list. Unlike map, though, it uses append to combine the results rather than cons. This is useful because we want to get back a single level of lists as an answer:

(define concat/map
  (lambda (ls f)
    (cond
      [(null? ls) '()]
      [else (append (f (car ls)) (concat/map (cdr ls) f))])))

Then, writing combine for two lists is straightforward. You take each element of the first list, then make every list combining it and an element x from the second list. Since this gives back a list of answers for each element in the first list, use concat/map to put it together as we want:

(define combine
  (lambda (xs ys)
    (concat/map xs (lambda (x)
                     (map (lambda (y) (list x y)) ys)))))

The version of combine that operates on one or more lists, let's call it combine*, is a bit trickier. Instead of making all the lists combining x with the elements from the second list, we just recursively ask for the product of all the remaining ys, and then cons x onto each of those results. The recursion stops when there's only two lists to combine, and uses the original combine in that case.

(define combine*
  (lambda (xs . ys*)
    (cond
      [(null? ys*) (map list xs)]
      [(null? (cdr ys*)) (combine xs (car ys*))]
      [else (concat/map xs (lambda (x)
                             (map (lambda (y) (cons x y))
                                  (apply combine* ys*))))])))

As a bonus, this pattern of using concat/map to do some work and combine the resulting answers is actually the list monad. It's simplified here, but the structure is in place.



来源:https://stackoverflow.com/questions/5546552/scheme-recursive-function-to-compute-all-possible-combinations-of-some-lists

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!