0

我有

(setq l2 '(1 (2 b (c 1 b))(a (1 2) d))) 

(defun drumuri (l3) 
  (cond ((atom l3) (cons l3 nil))
     (t (append
           (cons (car l3) nil)
           (drumuri (cadr l3))
           (cons (car l3) nil)
           (drumuri (caddr l3))))))

(drumuri l2)

它给了我:

 Break 2 
[4]>     DRUMURI
 Break 2 
[4]>     (1 2 B 2 C 1 C B 1 A 1 2 1 NIL A D)

但是我需要:

((1 2 B)(1 2 C 1)(1 2 C B)(1 A 1 2)(1 A D)) 

好消息,我找到了一些答案:

(setq l2 '(1 (2 b (c 1 b))(a (1 2) d)))
( defun drumuri (l3) 
( cond ( (atom l3) ( cons l3 nil))
       (t (append  ( cons ( car l3 ) nil)
          (drumuri ( cadr l3) )))))
          (drumuri l2)

答案是:

[1]> 
(1 (2 B (C 1 B)) (A (1 2) D))
[2]> 
DRUMURI
[3]> 
(1 2 B)

接下来是第二个答案:

(defun drumuri (l4) 
    (cond ((atom l4)(cons l4 nil))
    ( t   ( append  (cons ( car l4)nil)
        (drumuri ( caddr l4))))))
            (drumuri l2)

答案是:

[1]> 
(1 (2 B (C 1 B)) (A (1 2) D))
[2]> 
DRUMURI
[3]> 
(1 A D)

所以剩下的就是找到:

(1 2 C 1) (1 2 CB) (1 A 1 2)

4

1 回答 1

1

一个棘手的问题。不是特别复杂,但有一些挑剔的边缘。由于这显然是家庭作业,我会尽力帮助你,但同时避免只是用勺子喂你(并且可能在这些目标中的一个或两个目标上失败)。所以我用 Python 编写了它。希望这与 Lisp 相距甚远,以至于您仍然需要为自己做一个很好的思考。

>>> import operator
>>> def drumuri(a):
...     if isinstance(a, list):
...         return reduce(operator.add,
...                       [[a[:1] + d for d in drumuri(x)] for x in a[1:]])
...     else:
...         return [[a]]
... 
>>> drumuri( [1, [2, 'b', ['c', 1, 'b']], ['a', [1, 2], 'd']] )
[[1, 2, 'b'], [1, 2, 'c', 1], [1, 2, 'c', 'b'], [1, 'a', 1, 2], [1, 'a', 'd']]
>>> 

这是您的 Lisp 版本中缺少的关键见解。因为drumuri 是递归的,所以每个级别都必须向其调用者返回相同类型的结构:路径列表,其中每条路径都是一个列表。简而言之,drumuri 必须始终返回一个列表列表。您的叶子案例返回一个包含单个原子的列表。

您在使用 时也犯了一些错误append,但是叶子问题可能会使其他所有东西都变形。

编辑:让我们看看是否可以帮助您自己发现解决方案。按着这些次序:

  1. 编写一个名为的函数,该函数prepend-to-paths接受一个头部和一个路径列表,并返回一个路径列表,其中头部添加到每个原始路径的前面。它应该按如下方式工作:

    > (prepend-to-paths 1 '((2 B) (2 C 1) (2 C B) (A 1 2) (A D))) ;'
    ((1 2 B) (1 2 C 1) (1 2 C B) (1 A 1 2) (1 A D))
    
  2. 编写一个名为的函数,该函数convert-to-paths接受未处理的尾元素列表并将它们转换为路径。然而,与其自己完成所有工作,它应该只关心将输入映射到路径列表(依赖尚未drumuri写入的映射每个元素),然后将返回的路径列表连接到单个路径列表中. 输出(一旦drumuri存在)应该是这样的:

    > (convert-to-paths '((2 b (c 1 b)) (a (1 2) d))) ;'
    ((2 B) (2 C 1) (2 C B) (A 1 2) (A D))
    
  3. 编写drumuri函数。它应该cond按照你原来的方式使用,但是用一个将原子作为路径列表返回的表达式替换叶子大小写:

    > (drumuri 'b) ;'
    ((b))
    

    然后将 替换为(append ...)使用您在前面步骤中编写的函数的代码,将输入列表的头部和尾部转换为路径列表。

  4. 一旦这三个函数很好地协同工作,您可以尝试弄清楚如何将前两个折叠到drumuri. 请注意,最终结果可能在结构上与我给出的 Python 解决方案不同。

如果您遇到困难,只需用您取得的任何进展以及您设法拼凑的任何代码来更新您的问题。

于 2010-05-15T09:12:43.997 回答