Prolog:让我的谓词返回所有可能的解决方案

问题描述

我在prolog online的99-problems中发现了这个问题。有一个解决方案(与我的无关),我想知道为什么我的不起作用。或者准确地说:它有效,但它只找到了 1 个解决方案,而不是所有解决方案。问题是这样表述的: a) 一组 9 人可以在 3 个不相交的 2、3 和 4 人小组中以多少种方式工作?

member(X,[X]).
member(X,[X|_]).
member(X,[_|R]):- member(X,R).

append(X,[],X).
append([],X,X).
append([H|R],[A|B],[H|W]):- append(R,W).

group234(G,G2,G3,G4):- length(G2,2),length(G3,3),length(G4,4),member(X,G),member(Y,member(Z,G2),G3),append(G2,I),append(I,G4,G).

q1:有没有办法像我一样使用长度和附加和成员并成功完成这个,还是我需要完全重写它?
q2:为什么这段代码只产生 1 个解决方案? Prolog 应该搜索许多可能的成员,不是吗?(显然,它不应该,因为该语言比我更了解。但据我所知,它应该搜索,为什么不?)

解决方法

您只需要 append/3 来定义谓词以选择和删除组中的一个人:

choose(X,L1,L2) :-
    append(A,[X|B],L1),append(A,B,L2).

例如:

?- choose(X,[a,b,c],Rest).
X = a,Rest = [b,c] ;
X = b,Rest = [a,c] ;
X = c,b] ;
false.

然后,使用此谓词,您可以将 group234/4 定义为:

group234(G,[A,B],[C,D,E],G4):-
    choose(A,G,G0),choose(B,G0,G1),A @< B,choose(C,G1,G2),choose(D,G2,G3),C @< D,choose(E,G3,G4),D @< E.

请注意,您需要条件 A @< B,以避免排列(因为两个列表 [A,B][B,A] 代表同一组)。类似地,条件 C @< DD @< E 避免了列表 [C,E] 的排列。

示例:

?- group234([a,c,d,e,f,g,h,i],G4).
G2 = [a,b],G3 = [c,e],G4 = [f,i] ;
G2 = [a,f],G4 = [e,g],h],i] 
...
,

我认为问题的表述相当模糊。 @slago 提出的(不错!+1)解决方案依赖于可排序的元素,但我认为该解决方案应该在列表的 positions 上进行表达。这是他们完成的解决方案,使用库谓词表示:

%!  %%%%

group234(G,G4):-
    select(A,select(B,select(C,select(D,select(E,D @< E.

n_group234_slago(N) :-
    numlist(1,9,L),aggregate_all(count,group234(L,_,_),N).

这是我的

take_ordered(L,[X],R) :-
    select(X,L,R).
take_ordered(L,[X|Xs],R) :-
    append(H,[X|T],take_ordered(T,Xs,J),append(H,J,R).

group234_cc(L,[A1,A2],[B1,B2,B3],[C1,C2,C3,C4]) :-
    take_ordered(L,U),take_ordered(U,C4]).

n_group234_cc(N) :-
    numlist(1,group234_cc(L,_A,_B,_C),N).

n_group234_slago(N)n_group234_cc(N) 都返回请求的正确数字 N

编辑

我对 take_ordered/3 不满意。然后,我试着用 DCG 来表达:

take_ordered([],[]) --> [].
take_ordered([X|Xs],Ys) --> [X],take_ordered(Xs,Ys).
take_ordered(Xs,[Y|Ys]) --> [Y],Ys).

take_ordered(L,O,R) :-
    phrase(take_ordered(O,R),L).

效率提升显着,推理次数减半。

编辑

“P-99:九十九个序言问题”站点提出的解决方案 group3/4 的效率远低于您在此处找到的 @slago 和我的建议。

?- numlist(1,time(aggregate_all(count,group3(L,A,C),N)).
% 122,373 inferences,...

?- time(n_group234_cc(N)).
% 7,549 inferences,...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...