解决Prolog中的谜题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决Prolog中的谜题相关的知识,希望对你有一定的参考价值。

我是prolog的新手,我正在努力解决这个难题。我在youtube上做了一些关于prolog基础知识的教程,但我需要一些帮助解决下面的难题。

两周前,四名爱好者在他们附近的天空中看到了物体。四人中的每一人都在另一天报告了他或她的目击事件。联邦调查局来了,能够给每个人一个不同的解释,说明他或她“真正”看到了什么。你能确定每个人看到这个物体的日子(星期二到星期五),以及它所发现的物体吗?

  1. 本周早些时候,K先生在某个时刻看到了这个气球,而不是那个看过气球的人,而是在本周晚些时候发现的那个人,而不是那个发现风筝的人(不是G女士)。
  2. 星期五的观察是由Barn女士或看过一架飞机(或两者)的人发现的。
  3. 尼克斯周二没有看到他。
  4. 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]]

以上是关于解决Prolog中的谜题的主要内容,如果未能解决你的问题,请参考以下文章

在 Prolog 中使用约束和排列解决难题

Prolog 谜题面包师、肉工和木匠

Prolog:获取包含给定整数的子列表

Swi-prolog 双向子句/事实

Prolog 中的爱因斯坦谜题

使用 clpfd Prolog 库解决斑马谜题(又名爱因斯坦谜题)