在N列表中划分列表时Prolog循环

时间:2014-12-19 00:58:11

标签: loops prolog

在执行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).

正如您在我的示例中所看到的,没有重复项。通常这些都不会发生,如果它们发生,应该删除重复。

感谢任何指点我正确方向的人。

1 个答案:

答案 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或相应地重写您的程序。