如何使用permute谓词输出到SWI prolog中的列表?
permutation / 2谓词一次只返回一个结果。
答案 0 :(得分:4)
描述所有排列的最直接方式是使用bagof/3
。请注意,findall/3
无法直接使用,因为findall
会生成原始列表的文字副本。
list_allperms(L, Ps) :-
bagof(P, permutation(L,P), Ps).
?- L = [A,B,C], list_allperms(L, Ps).
L = [A, B, C],
Ps = [[A, B, C], [A, C, B], [B, A, C], [B, C, A], [C, A, B], [C, B, A]].
所以这是毫无疑问的版本。但你甚至可以在没有任何辅助内置函数的情况下直接在纯Prolog中实现它。
答案 1 :(得分:0)
如果你想要一个所有排列的列表,findall / 3就是你要走的路。如果要打印,可以使用forall / 2。无论哪种情况:
case_a(In, L) :- findall(Perm, permutation(In, Perm), L).
case_b(In) :- forall(permutation(In, Perm), writeln(Perm)).
forall它是一个通用的内置程序,实现了一个故障驱动的循环,其简单性令人惊叹。我报告了SWI-Prolog库的定义,我认为这很有意思。
%% forall(+Condition, +Action)
%
% True if Action if true for all variable bindings for which Condition
% if true.
forall(Cond, Action) :-
\+ (Cond, \+ Action).
修改强>
如上所述,如果你的列表中有变量,你应该知道findall / 3 WRT bagof / 3的不同行为:
?- case_a([1,2,3],X).
X = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]].
?- case_a([A,B,C],X).
X = [[_G467, _G470, _G473], [_G455, _G458, _G461], [_G443, _G446, _G449], [_G431, _G434, _G437], [_G419, _G422, _G425], [_G407, _G410, _G413]].
请注意,第二个查询输出中的每个变量都是不同的:可能是请求结果,也可能不是,具体取决于手头的问题。确定适当的行为WRT变量量化在变量是数据的限制类问题中是强制性的,即元编程,我认为......