我正在尝试在序言中解决这个难题
Five people were eating apples, A finished before B, but behind C. D finished before E, but behind B. What was the finishing order?
我当前的解决方案有单例变量,我不知道如何解决这个问题。
finishbefore(A, B, Ls) :- append(_, [A,B|_], Ls).
order(Al):-
length(Al,5),
finishbefore(A,B,Al),
finishbefore(C,A,Al),
finishbefore(D,E,Al),
finishbefore(B,D,Al).
%%query
%%?- order(Al).
最佳答案
这是使用library(clpz)
或library(clpfd)
约束的纯版本。这个想法是提出一个稍微不同的问题。
How can an endpoint in time be associated to each person respecting the constraints given?
由于我们有五个人,所以五个不同的时间点就足够了,但不是绝对必要的,例如 1..5。
:- use_module(library(clpz)). % or clpfd
:- set_prolog_flag(double_quotes, chars). % for "abcde" below.
appleeating_(Ends, Zs) :-
Ends = [A,B,C,D,E],
Zs = Ends,
Ends ins 1..5,
% alldifferent(Ends),
A #< B,
C #< A,
D #< E,
B #< D.
?- appleeating_(Ends, Zs).
Ends = [2, 3, 1, 4, 5], Zs = [2, 3, 1, 4, 5].
只有一个解决方案!请注意,all different/1 并不是直接需要的,因为没有任何地方指出不允许两个人同时结束。事实上,上面证明了没有更短的解决方案。 @CapelliC 的解决方案强加了一个命令,即使两个人按照平等原则完成。但为了兼容性,现在让我们将解决方案映射回您的表示。
list_nth1(Es, N, E) :-
nth1(N, Es, E).
appleeatingorder(OrderedPeople) :-
appleeating_(Ends, Zs),
same_length(OrderedPeople, Ends),
labeling([], Zs), % not strictly needed
maplist(list_nth1(OrderedPeople), Ends,"abcde"). % effectively enforces alldifferent/1
?- appleeatingorder(OrderedPeople).
OrderedPeople = [c,a,b,d,e].
?- appleeatingorder(OrderedPeople).
OrderedPeople = "cabde".
最后一个使用双引号的解决方案直接生成 Scryer。在 SWI 中使用 library(double_quotes)
.
(在这种情况下,appleeating_/2
的额外参数 Zs
并不是严格需要的,但它对于一般 CLP 谓词来说是一个非常有用的约定。它将从搜索部分 (labeling([], Zs)
) 中提取建模部分 (appleeating_/2
),以便您可以轻松地同时尝试各种版本的搜索/标签.为了真正解决问题,Zs
中的所有变量都必须具有实际值。)
关于prolog - 如何检查序言中的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67278346/