Can be this lisp function be implemented recursively?

坚强是说给别人听的谎言 提交于 2019-12-08 11:44:39

问题


The goal of this function is to generate the cartesian product of 2 list. For example

  • (combo (list 1 2 3) (list 4 5)) => (1 4) (1 5) (2 4) (2 5) (3 4) (3 5)

    (defun combo (l1 l2)
    (let    (
                (res (list))
            )
        (dolist (elem1 l1 res)
            (dolist (elem2 l2 res)
                (setq res (append res (list(list elem1 elem2))))
            )
        )
    )
    

    )

How could be implemented recursively?


回答1:


A simple recursive implementation would be to use two helper functions; one to traverse through L1 (%COMBO in the code below), calling another function to pair an element with each element from L2 (%PRODUCT):

(defun combo (l1 l2)
  (labels ((%product (el list &optional (acc (list)))
             (if (endp list)
                 acc
                 (%product el (rest list) (cons (list el (first list)) acc))))
           (%combo (l1 l2 &optional (acc (list)))
             (if (endp l1)
                 (nreverse acc)
                 (%combo (rest l1) l2 (nconc (%product (first l1) l2) acc)))))
    (%combo l1 l2)))

The iterative approach is both simpler and more efficient though. Instead of using APPEND in a loop, you should just reverse the list at the end.

(defun combo (l1 l2)
  (let ((res (list)))
    (dolist (e1 l1 (nreverse res))
      (dolist (e2 l2)
        (push (list e1 e2) res)))))

You could also just use the MAP-PRODUCT function from Alexandria:

CL-USER> (ql:quickload :alexandria)
;=> (:ALEXANDRIA)
CL-USER> (use-package :alexandria)
;=> T
CL-USER> (map-product #'list (list 1 2 3) (list 4 5))
;=> ((1 4) (1 5) (2 4) (2 5) (3 4) (3 5))



回答2:


It seems ideal for Prolog, though data has to be put differently:

items1(1).
items1(2).
items1(3).

items2(4).
items2(5).

?- findall((A,B), (items1(A), items2(B)), L).
L = [ (1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)].


来源:https://stackoverflow.com/questions/37976330/can-be-this-lisp-function-be-implemented-recursively

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