【发布时间】:2015-11-13 17:24:05
【问题描述】:
对于 L = (A B C D) 的元素列表,要生成满足元素字典顺序 (A
【问题讨论】:
-
您的意思是每个子集中的元素是有序的,还是您要按顺序获取子集,或者两者兼而有之?您的示例同时显示了两者,但我不确定这是否是您的问题所要求的。
标签: lisp common-lisp clisp
对于 L = (A B C D) 的元素列表,要生成满足元素字典顺序 (A
【问题讨论】:
标签: lisp common-lisp clisp
lexicographical(非词法)顺序可以通过以下函数获得,该函数检查列表a是否在列表b之前按字典顺序:
(defun lex<= (a b)
(or (null a)
(and b
(string<= (car a) (car b))
(lex<= (cdr a) (cdr b)))))
因此,您可以生成所有组合,就像在 coredump 的答案中一样,然后使用 (sort result #'lex<=) 对它们进行排序。
【讨论】:
(sort (powerset '(a b c d)) #'lex<=) 或者,如果你想从结果中消除nil,(sort (remove nil (powerset '(a b c d))) #'lex<=),powerset 在 coredump 的答案中定义。
nil 值放在排序范围的开头。排序后删除它们显然是更好的选择。
看起来您只需编写简单的函数来获取列表的幂集,然后只需删除一个空集,并以您想要的任何方式对其进行排序。
(defun powerset (lst)
(if lst (mapcan (lambda (el) (list (cons (car lst) el) el))
(powerset (cdr lst)))
'(())))
CL-USER> (powerset '(A B C D))
((A B C D) (B C D) (A C D) (C D) (A B D) (B D) (A D) (D) (A B C) (B C) (A C)
(C) (A B) (B) (A) NIL)
要准确获得您的描述输出,您可以删除 NIL 并将其反转:
CL-USER> (reverse (remove nil (powerset '(A B C D))))
((A) (B) (A B) (C) (A C) (B C) (A B C) (D) (A D) (B D) (A B D) (C D) (A C D)
(B C D) (A B C D))
这是你想要的吗?
更新。抱歉,没有提到您希望它以另一种方式排序。你应该使用它:
CL-USER> (sort
(reverse
(remove nil
(powerset '(A B C D))))
#'< :key #'length)
((A) (B) (C) (D) (A B) (A C) (B C) (A D) (B D) (C D) (A B C) (A B D) (A C D)
(B C D) (A B C D))
这是另一个更重要的解决方案,使用loop 宏,按照您的描述进行:
(defun combinations (lst)
(loop :for i :below (expt 2 (length lst))
:when (loop :for j :below i :for el :in lst if (logbitp j i) :collect el)
:collect it :into result
:finally (return (sort result #'< :key #'length))))
CL-USER> (combinations '(A B C D E))
((A) (B) (C) (D) (E) (A B) (A C) (B C) (A D) (B D) (C D) (A E) (B E) (C E)
(D E) (A B C) (A B D) (A C D) (B C D) (A B E) (A C E) (B C E) (A D E) (B D E)
(C D E) (A B C D) (A B C E) (A B D E) (A C D E) (B C D E) (A B C D E))
【讨论】: