【问题标题】:Lisp function which adds parentheses in a certain way以某种方式添加括号的 Lisp 函数
【发布时间】:2014-03-14 09:33:58
【问题描述】:

我正在尝试编写一个添加如下括号的函数:(parens '(a b c d e)) 返回 (a (b (c (d (e)))))。我只是看不太清楚这种模式。到目前为止,我只返回一个带有括号的列表。我似乎无法弄清楚如何让它看起来像那样。

(DEFUN PARENS (L)
   (COND ((NULL L) NIL)
   (T (CONS (LIST (CAR L)) (PARENS (CDR L))))))

【问题讨论】:

    标签: function recursion lisp


    【解决方案1】:

    列表中没有括号。您从包含五个元素的列表(a b c d e) 开始,然后返回包含两个元素的列表(a (b (c (d (e)))))。第一个元素是a,第二个元素是另一个列表(b (c (d (e))))

    使用reduce 很容易接近

    CL-USER> (reduce 'list '(a b c d e) :from-end t)
    (A (B (C (D E))))
    

    您可以将reduce 视为将函数list“注入”到(a b c d e) 中以产生

    (list a (list b (list c (list d e))))
    

    这几乎就是你想要的。你实际上想要:

    (list a (list b (list c (list d (list e)))))
    

    你将如何制作它?您可以递归列表,对于每个子列表(x . ys),您想要返回(list x (recurse ys)),但ys() 时除外。你不想递归到(),因为你不想要一个包含两个元素的列表,你实际上什么都不想要。因此,诀窍是比您通常使用列表更早地停止递归。因此:

    (defun parens (l)
      (cond
        ((endp l) '())
        ((endp (rest l)) l)
        ((list (first l) (parens (rest l))))))      ; *
    
    CL-USER> (parens '(a b c d e))
    (A (B (C (D (E)))))
    CL-USER> (parens '(a b))
    (A (B))
    CL-USER> (parens '(a))
    (A)
    CL-USER> (parens '())
    NIL
    

    *在最后一个子句中省略 t 测试是有意的。如果cond 子句中没有正文形式,则返回测试值。因此(list …) 既是测试形式又是值形式。

    我们实际上可以稍微清理一下。 ((endp l) '()) 的情况可能是 ((endp l) l),因为 l 是空列表。但这意味着在第一种和第二种情况下,我们都可以返回l。我们可以在 Common Lisp 中调用 (rest '()) 并返回 (),所以当 l 类似于 (e) 时,(rest l) 将是 () 并且l 是 @987654353 时@。这意味着我们可以使用:

    (defun parens (l)
      (cond
        ((endp (rest l)) l)
        ((list (first l) (parens (rest l))))))
    

    如果我们只有一个测试,我们不妨使用if

    (defun parens (l)
      (if (endp (rest l))
          l
          (list (first l) (parens (rest l)))))
    

    【讨论】:

      【解决方案2】:

      您实际上可以使用reduce 和一些特殊考虑来完成它:

      (defun unflatten (list)
        (reduce #'list list
                :from-end t
                :end (1- (length list))
                :initial-value (last list)))
      

      请注意,last 返回最后一个 n(默认为 1)元素的列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-25
        • 2019-01-19
        • 2021-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多