在执行divide([1,2], 3, X).
时我想要达到的目标是:
我应该得到第一个列表的所有排列,分为N个列表。
X = [[],[],[1,2]] ;
X = [[],[],[2,1]] ;
X = [[],[2],[1]] ;
X = [[],[1],[2]] ;
X = [[],[1,2],[]] ;
X = [[],[2,1],[]] ;
X = [[],[],[2,1]] ;
X = [[],[],[1,2]] ;
X = [[],[1],[2]] ;
X = [[],[2],[1]] ;
X = [[],[2,1],[]] ;
X = [[],[1,2],[]] ;
X = [[2],[],[1]] ;
X = [[2],[1],[]] ;
X = [[1],[],[2]] ;
X = [[1],[2],[]] ;
X = [[1,2],[],[]] ;
X = [[2,1],[],[]] ;
但由于某种原因,如果我的列表超过2个项目,则下面的代码进入循环并显示太多信息。
% Divides a list over N sets
divide(_,N,[]) :- N < 1.
divide(Items,1,[Items]).
divide(Items,N,[Selected|Other]) :- N > 1,
sublistPerm(Items,Selected,Rest),
N1 is N-1,
divide(Rest,N1,Other).
sublistPerm可以正常工作(如果需要,可以测试它)。
% Gets all power sets of a list and permutes them
sublistPerm(Items, Sel, Rest) :- sublist(Items, Temp1, Temp2),
permutation(Temp1, Sel),
permutation(Temp2, Rest).
% Gets all power sets of a list
sublist([], [], []).
sublist([X|XS], YS, [X|ZS]) :- sublist(XS, YS, ZS).
sublist([X|XS], [X|YS], ZS) :- sublist(XS, YS, ZS).
如果您要努力运行以下代码,您将看到我获得的冗余信息。我绝对不知道为什么它不会像它应该的那样终止。 divide([1,2,3], 3, X).
正如您在我的示例中所看到的,没有重复项。通常这些都不会发生,如果它们发生,应该删除重复。
感谢任何指点我正确方向的人。
答案 0 :(得分:2)
您的代码有几个问题,循环不是它们。我们可以很快地将这个问题区分开来:
?- divide([1,2], 3, X), false.
终止。此查询没有终止问题。
有一些冗余的解决方案。但这又不是一个问题。但是,最有问题的是你的关系是不完整的。最小的例子是:
?- divide([1,2], 1, [[2,1]]).
应该成功但失败。所以让我们先解决这个问题。事实
divide(Items,1,[Items]).
必须概括为涵盖所有排列。
divide(Items,1,[ItemsP]) :-
permutation(Items, ItemsP).
对于冗余答案/解决方案,不需要第二个目标permutation/2
,您可以将其替换为(=)/2
或相应地重写您的程序。