Lisp 如何返回特定列表

Lisp 如何返回特定列表,lisp,common-lisp,Lisp,Common Lisp,我正在尝试用LISP编写代码,我遇到了很多麻烦 这就是我目前的情况: (defun list_incr (x) (if (eq (first x) nil) x (if (< (first x) (first(rest x))) (append (list (first x) (first(rest x))) (list_incr (rest(rest x)))) (list_incr (cons (f

我正在尝试用LISP编写代码,我遇到了很多麻烦

这就是我目前的情况:

(defun list_incr (x)
    (if (eq (first x) nil)
        x
        (if (< (first x) (first(rest x)))
            (append (list (first x) (first(rest x))) (list_incr (rest(rest x))))
            (list_incr (cons (first x) (rest(rest x)))))))
(定义列表\u增量(x)
(如果(等式(第一个x)为零)
x
(如果(<(第一个x)(第一个(剩余x)))
(附加(列表(第一个x)(第一个(其余x)))(列表(其余x)))
(列表增加(反对(第一个x)(其余(其余x)(()()))))
如果给定一个列表(1 3 2 4),它需要返回(1 3 4)。目前,我的代码对两个连续递增的数字都很好,但当它递减时就不再有效了

我需要代码返回一个从给定列表中递增的列表

一些例子:

如果给出一个列表(1 2 4 6 5),它应该返回(1 2 4 6)

如果给定(3 1 4 5 2 6),则应返回(3 4 5 6)


谢谢大家!

这里有一个可能的递归定义来解决这个问题:

(defun exercise-1d (x)
  (cond ((null x) nil)
        ((null (rest x)) x)
        ((> (second x) (first x)) (cons (first x) (exercise-1d (rest x))))
        (t (exercise-1d (cons (first x) (rest (rest x)))))))
递归有两种终端情况:当列表为空或包含单个元素时。在这两种情况下,都会返回当前列表

在前两个测试之后,我们确定列表至少有两个元素,因此我们可以开始检查前两个元素之间的关系

如果第二个元素大于第一个元素,则包括第一个元素,并将递归应用于列表的其余部分


另一方面,如果第二个元素不大于第一个元素,则跳过该元素,并将递归应用于由第一个元素和第二个元素之后的所有元素构成的列表。

以下是解决此问题的可能递归定义:

(defun exercise-1d (x)
  (cond ((null x) nil)
        ((null (rest x)) x)
        ((> (second x) (first x)) (cons (first x) (exercise-1d (rest x))))
        (t (exercise-1d (cons (first x) (rest (rest x)))))))
递归有两种终端情况:当列表为空或包含单个元素时。在这两种情况下,都会返回当前列表

在前两个测试之后,我们确定列表至少有两个元素,因此我们可以开始检查前两个元素之间的关系

如果第二个元素大于第一个元素,则包括第一个元素,并将递归应用于列表的其余部分


另一方面,如果第二个元素不大于第一个元素,则跳过该元素,并将递归应用于由第一个元素和第二个元素之后的所有元素构成的列表。

这里是一个可选的尾部递归版本。这样做的优点是,在优化尾部调用的实现中,它可以处理任意大的列表,但通常的缺点是它会向后返回内容,因此需要调用
reverse

它使用一个局部函数,因为您需要两个额外的参数,并且还使用
解构bind
来避免大量重复调用
first
rest
。它还通过
(null(rest list))
略微卑鄙地检查一个包含零或一个元素的列表:这在CL中是有效的,因为
(cdr'())
(aka
(rest'())
)是
):我认为它在Scheme中不起作用,Scheme对这些事情更挑剔

(defun increasing-elements (list)
  (labels ((increasing-loop (tail current accumulator)
             (if (null tail)
                 (reverse accumulator)
               (destructuring-bind (first . rest) tail
                 (if (> first current)
                     (increasing-loop rest first (cons first accumulator))
                   (increasing-loop rest current accumulator))))))
    (if (null (rest list))
        list
      (destructuring-bind (head . tail) list
        (increasing-loop tail head (list head))))))

这里是另一个可选的尾部递归版本。这样做的优点是,在优化尾部调用的实现中,它可以处理任意大的列表,但通常的缺点是它会向后返回内容,因此需要调用
reverse

它使用一个局部函数,因为您需要两个额外的参数,并且还使用
解构bind
来避免大量重复调用
first
rest
。它还通过
(null(rest list))
略微卑鄙地检查一个包含零或一个元素的列表:这在CL中是有效的,因为
(cdr'())
(aka
(rest'())
)是
):我认为它在Scheme中不起作用,Scheme对这些事情更挑剔

(defun increasing-elements (list)
  (labels ((increasing-loop (tail current accumulator)
             (if (null tail)
                 (reverse accumulator)
               (destructuring-bind (first . rest) tail
                 (if (> first current)
                     (increasing-loop rest first (cons first accumulator))
                   (increasing-loop rest current accumulator))))))
    (if (null (rest list))
        list
      (destructuring-bind (head . tail) list
        (increasing-loop tail head (list head))))))

这里还有另外两种方法,一种是使用高阶
REDUCE
函数,另一种是使用
LOOP
,并带有注释。 它们都比您的问题中要求的更一般,因为它们接受
TEST
KEY
参数:
TEST
是比较谓词,表示结果列表的排序顺序;测试功能 对于由
谓词从原始元素中提取的值调用,并默认为标识函数

减少 减少(也称为折叠)是一种基于列表中的值以增量方式构建值的方法。 下面,中间状态是一个cons单元,其结果列表目前已在其CAR中构建,且列表中的元素在其CDR中获取的最新(最大)值。 在提供给
REDUCE
的匿名lambda中,只要当前值大于最新值,它就会被放大,否则它会保持原样。 使用初始状态值调用
REDUCE
,以避免列表中包含零个或一个元素的情况:一般来说,当状态的类型与列表元素的类型不同时,提供
:初始值
是有意义的。 相反,如果它们属于同一类型,则更自然地避免使用它(例如
(reduce#'+'(0 1 2))


这里还有另外两种方法,一种是使用高阶
REDUCE
函数,另一种是使用
LOOP
,并带有注释。 它们都比您的问题中要求的更一般,因为它们接受
TEST
KEY
参数:
TEST
是比较谓词,表示结果列表的排序顺序;测试功能 对于由
谓词从原始元素中提取的值调用,并默认为标识函数

减少 减少(也称为折叠)是一种基于列表中的值以增量方式构建值的方法。 下面,中间状态是一个cons单元,其结果列表目前已在其CAR中构建,且列表中的元素在其CDR中获取的最新(最大)值。 匿名