【问题标题】:Lisp Reverse Function using ONLY primitives [duplicate]仅使用原语的 Lisp 反向函数 [重复]
【发布时间】:2014-12-11 05:02:47
【问题描述】:

我遇到了一些 lisp 代码的问题。这个函数只是应该反转一个基本列表。 我只能使用原语,它们被定义为 " defun, cond, cons, car, cdr, null, eq, listp, atom, symbolp, +, - , "

在传递的例子中 (1 2 3 4) 我回来了 (((4 3) 2) 1)

(defun reverse2 (l)
(cond
    ((eq nil (cdr l)) (car l) )
    (t (cons(reverse2 (cdr l)) (cons (car l) nil)))))

请告诉我如何改进。这不是家庭作业,我只是为了明天的期末考试而做这个练习。

【问题讨论】:

  • -- 不是 Common Lisp 中的运算符。你的意思是-
  • 如果您可以使用append 而不是cons,那么您的方法将有效;但它不在您允许的原语列表中。

标签: lisp reverse


【解决方案1】:

要实现反向功能,您需要使用累加器。以下是你可以如何实现它(在这种情况下,tail 是累加器):

(defun revappend (list tail)
  (cond ((null list) tail)
        (t (revappend (cdr list) (cons (car list) tail)))))

然后,根据revappend 实现reverse

(defun reverse (list)
  (revappend list nil))

【讨论】:

  • 但是你(定​​义和)使用revappend,这不是一个原语。点是给定列表中的to use only primitives
  • @WillNess defun 是经过批准的原语。如果允许,通过扩展,您必须被允许定义自己的函数。
  • @Tyler 那么这个谜题毫无意义。您只需自己重新定义整个标准库。这不是重点。你看过我链接的条目吗?
  • @WillNess 我明白这个难题的重点是迫使学生重新实现标准库的部分内容作为学习练习。
【解决方案2】:

如果您想使用简单递归,则必须将第一项附加到列表的末尾。请注意,这不是列表反向操作的良好实现。为什么?

(defun reverse2 (l)
   (cond ((endp l) l)                                                                                                                
         (t (append (reverse2 (rest l))                                                                                                     
                    (list (first l))))))
REVERSE                                                                                      
CL-USER> (reverse2 '(a b c d))
(D C B A)                                                                                                                                

【讨论】:

  • 使用 cons 而不是 append 的实现呢?就我的课程而言,我们不允许追加。仅从您的代码来看,我假设 (rest l) 等效于 (cdr l) 并且 (first l) 等效于 (car l)。如果我在这种情况下错了,请纠正我。
  • @colin 你可以尝试实现 APPEND 看看效果如何。对于 Lisp 原语,请参阅 Lisp 手册。无需“假设”他们做了什么。请查阅手册。
  • 我的课程将原语定义为我上面提到的那些,因此我们没有学习附加。与 rest 和 first 相同,这就是我在最初的帖子中首先定义它的原因。
  • @colin Rainer 的观点是,如果您想使用非累积解决方案,则必须实现 append 并使用它,这是一个糟糕的解决方案,因为您的反向操作将是 O(n² ) 而不是 O(n) (revappend 解决方案就是)。
  • @Colin:您的课程使用旧函数名称进行列表处理操作。目前的做法使用稍新的做法。请查阅手册。
【解决方案3】:

您可以使用可选参数来代替辅助函数:

(defun reverse (list &optional tail)
  (cond ((null list) tail)
        (t (reverse (cdr list)
                    (cons (car list) tail)))))

【讨论】:

  • 是的,但是revappend 是一个标准的 CL 函数,所以我想我不妨使用它。
猜你喜欢
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
  • 2018-03-24
  • 2011-03-27
  • 1970-01-01
  • 2013-09-06
  • 2014-09-13
相关资源
最近更新 更多