在 Prolog 中解决一个难题
Solving a puzzle in Prolog
我是序言新手,我正在尝试解决这个难题。我在 youtube 上做了几个关于 prolog 基础知识的教程,但我需要一些帮助来解决下面的难题。
两周前,四位爱好者在他们附近的天空中目击了物体。这四个人中的每一个都在不同的一天报告了他或她的目击事件。 FBI 来了,并且能够就他或她所看到的 "really" 向每个人提供不同的解释。你能确定每个人在哪一天(周二到周五)看到了这个物体,以及它原来是什么物体吗?
- 先生K 的目击时间比看到气球的人早,但在本周晚些时候,比发现风筝的人(不是 G 女士)。
- 星期五的目击是由巴恩女士或看到飞机的人(或两者)造成的。
- 先生Nik 周二没有出现。
- 先生K不是对象原来是电线杆的那个
我已经正确设置了我的规则,但我似乎无法理解逻辑。我正在寻找指导而不是直接的答案。在最右边,我列出了我试图回答的每个问题的编号
enthu(mr_k).
enthu(ms_barn).
enthu(ms_g).
enthu(mr_nik).
object(ballon).
object(kite).
object(plane).
object(tele_pole).
day(tuesday).
day(wednesday).
day(thursday).
day(friday).
sight(X,ballon).
sighting(mr_k):- 1
day(X),
sight(X,Y),
didntc_kite(ms_g).
friday_sight:- enthu(ms_barn); 2
saw(X,plane);
both(ms_barn,X).
nosight_tuesday(mr_nik,X). 3
no_telepole(mr_k,Y). 4
我知道您没有寻求解决方案,但我发现很难描述没有有效解决方案的情况下该怎么做。对此我深表歉意。
我会这样做:
/*
1. Mr. K made his sighting at some point earlier in the week than the one who saw the balloon, but at some point later in the week, than the one who spotted the Kite ( who isn't Ms. G ).
2. Friday's sighting was made by either Ms. Barn or the one who saw a plane ( or both ).
3. Mr. Nik did not make his sighting on Tuesday.
4. Mr. K isn't the one whose object turned out to be a telephone pole.
*/
?-
% Set up a list of lists to be the final solution
Days = [[tuesday,_,_],[wednesday,_,_],[thursday,_,_],[friday,_,_]],
/* 1 */ before([_,mr_k,_],[_,_,balloon],Days),
/* 1 */ before([_,_,kite],[_,mr_k,_],Days),
/* 2 */ (member([friday,ms_barn,_],Days);
member([friday,_,plane],Days);
member([friday,ms_barn,plane],Days)),
% Fill in the rest of the people
members([[_,mr_k,_],[_,ms_barn,_],[_,ms_g,_],[_,mr_nik,_]],Days),
% Fill in the rest of the objects
members([[_,_,balloon],[_,_,kite],[_,_,plane],[_,_,tele_pole]],Days),
% Negations should be done after the solution is populated
/* 1 */ member([_,NOT_ms_g,kite],Days), NOT_ms_g \= ms_g,
/* 3 */ member([tuesday,NOT_mr_nik,_],Days), NOT_mr_nik \= mr_nik,
/* 4 */ member([_,NOT_mr_k,tele_pole],Days), NOT_mr_k \= mr_k,
write(Days),
nl,
fail.
% Checks that `X` comes before `Y`
% in the list `Ds`
before(X,Y,Ds) :-
remainder(X,Ds,Rs),
member(Y,Rs).
% Finds a member of a list and
% unifies the third parameter such
% that it is the remaining elements in
% the list after the found member
remainder(X,[X|Ds],Ds).
remainder(X,[_|Ds],Rs) :- remainder(X,Ds,Rs).
% An extended version of `member` that
% checks if the members of the first list
% are all members of the second
members([],_).
members([X|Xs],Ds) :-
member(X,Ds),
members(Xs,Ds).
这给了我:
[[tuesday, ms_g, tele_pole],
[wednesday, mr_nik, kite],
[thursday, mr_k, plane],
[friday, ms_barn, balloon]]
我是序言新手,我正在尝试解决这个难题。我在 youtube 上做了几个关于 prolog 基础知识的教程,但我需要一些帮助来解决下面的难题。
两周前,四位爱好者在他们附近的天空中目击了物体。这四个人中的每一个都在不同的一天报告了他或她的目击事件。 FBI 来了,并且能够就他或她所看到的 "really" 向每个人提供不同的解释。你能确定每个人在哪一天(周二到周五)看到了这个物体,以及它原来是什么物体吗?
- 先生K 的目击时间比看到气球的人早,但在本周晚些时候,比发现风筝的人(不是 G 女士)。
- 星期五的目击是由巴恩女士或看到飞机的人(或两者)造成的。
- 先生Nik 周二没有出现。
- 先生K不是对象原来是电线杆的那个
我已经正确设置了我的规则,但我似乎无法理解逻辑。我正在寻找指导而不是直接的答案。在最右边,我列出了我试图回答的每个问题的编号
enthu(mr_k).
enthu(ms_barn).
enthu(ms_g).
enthu(mr_nik).
object(ballon).
object(kite).
object(plane).
object(tele_pole).
day(tuesday).
day(wednesday).
day(thursday).
day(friday).
sight(X,ballon).
sighting(mr_k):- 1
day(X),
sight(X,Y),
didntc_kite(ms_g).
friday_sight:- enthu(ms_barn); 2
saw(X,plane);
both(ms_barn,X).
nosight_tuesday(mr_nik,X). 3
no_telepole(mr_k,Y). 4
我知道您没有寻求解决方案,但我发现很难描述没有有效解决方案的情况下该怎么做。对此我深表歉意。
我会这样做:
/* 1. Mr. K made his sighting at some point earlier in the week than the one who saw the balloon, but at some point later in the week, than the one who spotted the Kite ( who isn't Ms. G ). 2. Friday's sighting was made by either Ms. Barn or the one who saw a plane ( or both ). 3. Mr. Nik did not make his sighting on Tuesday. 4. Mr. K isn't the one whose object turned out to be a telephone pole. */ ?- % Set up a list of lists to be the final solution Days = [[tuesday,_,_],[wednesday,_,_],[thursday,_,_],[friday,_,_]], /* 1 */ before([_,mr_k,_],[_,_,balloon],Days), /* 1 */ before([_,_,kite],[_,mr_k,_],Days), /* 2 */ (member([friday,ms_barn,_],Days); member([friday,_,plane],Days); member([friday,ms_barn,plane],Days)), % Fill in the rest of the people members([[_,mr_k,_],[_,ms_barn,_],[_,ms_g,_],[_,mr_nik,_]],Days), % Fill in the rest of the objects members([[_,_,balloon],[_,_,kite],[_,_,plane],[_,_,tele_pole]],Days), % Negations should be done after the solution is populated /* 1 */ member([_,NOT_ms_g,kite],Days), NOT_ms_g \= ms_g, /* 3 */ member([tuesday,NOT_mr_nik,_],Days), NOT_mr_nik \= mr_nik, /* 4 */ member([_,NOT_mr_k,tele_pole],Days), NOT_mr_k \= mr_k, write(Days), nl, fail. % Checks that `X` comes before `Y` % in the list `Ds` before(X,Y,Ds) :- remainder(X,Ds,Rs), member(Y,Rs). % Finds a member of a list and % unifies the third parameter such % that it is the remaining elements in % the list after the found member remainder(X,[X|Ds],Ds). remainder(X,[_|Ds],Rs) :- remainder(X,Ds,Rs). % An extended version of `member` that % checks if the members of the first list % are all members of the second members([],_). members([X|Xs],Ds) :- member(X,Ds), members(Xs,Ds).
这给了我:
[[tuesday, ms_g, tele_pole], [wednesday, mr_nik, kite], [thursday, mr_k, plane], [friday, ms_barn, balloon]]