Prolog - 谜语的解决方案

时间:2018-03-16 15:05:20

标签: prolog

我在互联网上找到了一个谜语,我想用Prolog解决它。我有一个Prolog程序,但结果与我的逻辑方法不符,所以我对我在Prolog程序中缺少的内容感兴趣。任何帮助,将不胜感激。很抱歉发布到stackoverflow,我找不到更适合此问题的stackexchange站点。

谜语的文字:

  

在丛林中生活着一群当地人,他们的表情有着非同寻常的怪癖:男人总是说实话;女人从不按顺序说两句错误句子,或依次说两句真句。最令人不舒服的是,男人和女人的穿着和整体看起来都是一样的,所以对真理的认识有时很复杂。一位人类学家试图研究当地人,但他仍然不熟悉母语。所以有一天,他遇到了一个家庭并问孩子他是男孩,人类学家不明白答案。这就是为什么他转向父母,其中一个告诉他“孩子说他是个男孩”,另一个说“孩子是女孩,孩子撒了谎”。人类学家需要知道孩子如何回应(或撒谎)继续研究当地传统,决定孩子和父母双方的性别。

我认为我的逻辑方法是正确的:

  

孩子可以是女人也可以是男人。让他成为一个男人。然后他不得不说他是一个男人,因为男人总是说实话。父母2说孩子是女孩,孩子撒谎。父母2当然不是男人,因为孩子是男人会是矛盾的。但父母不能成为女性,因为只有一句话必须是假的。但这不是因为孩子是男孩,他当然不会说谎。此外,孩子是一个男人,因此他不是女孩,因此这两个句子都是不真实的。孩子肯定不是男人。让孩子成为女人。由于孩子可能会说她是男人还是女人,因此这有点复杂。让孩子成为女人并说她是男人。让我们从父母2开始。这一定是一个男人,因为他说婴儿是一个女人并撒谎。父母1可以是女性,因为她说婴儿说她是男孩。女人可能会或可能不会撒谎。如果我们承认孩子可以有两个父亲,那也可能是一个男人。为了控制,让孩子成为女人并说她是女人。父母2必须是女性,因为她说婴儿是女孩,这是真的,但同时说她在撒谎,这是不正确的。父母1必须是男人,但不能因为男人总是说实话。但父母1说孩子说他是个男孩,这不是真的。只有孩子可以为父母生两个妻子,这才有可能。解决方案:孩子是女性,父母1是女性,父母2是男性。

我的Prolog程序说这个问题有多种解决方案。第一个说孩子和父母一样是男人。父母2是女人。正确的解决方案是第七个。我错过了一些“如果”或者!运营商在哪里?或者这种做法完全不好?

% split(+list, -listOfItemsAtEvenPositions, -listOfItemsAtOddPositions)

split([], [], []).
split([X|TList], Even, [X|TOdd]) :- rozdel(TList, TOdd, Even).

% says(+gender, +listOfSentences, -listOfTrueSentences)

% Men always say the truth.
says(man, X, X).

% Women never say two false sentences in sequence, or two true sentences in sequence.
says(woman, Sentences, TrueSentences) :-
   split(Sentences, _, TrueSentences); % Every odd sentence says the truth.
   split(Sentences, TrueSentences, _). % Every even sentence says the truth.

% solution(-genderOfChild, -genderOfFirstParent, -genderOfSecondParent)

solution(Child, Parent1, Parent2) :-

   % The child said something.
   says(Child, _, _),

   % The first parent says: "The child said he was a boy"
   says(Parent1, [says(Child, [Child=man], _)], _),

   % The second parent says: "The child is a girl, the child lied."
   says(Parent2, [Child=woman, says(Child, [Child=man], _)], _),

   % The child cannot have two parents of same gender.
   Parent1 \= Parent2.

我是Prolog的新手,所以就是这样。

1 个答案:

答案 0 :(得分:2)

这是我写的

:- use_module(library(clpb)).

solve(L) :-
    L = [A,B,C,D],
    % A : true means the child is a boy
    % B : true means the child tells the truth
    % C : true means person 1 is a man
    % D : true means person 2 is a man


    % person 1 : The child said he was a boy (and a man tells the truth)
    % if person 1 is a man
    sat(C =< A),
    % if person 1 is a woman, we can't write anything
    % because there's only one sentence


    % person 2 "The child is a girl, the child lied"
    % if person 2 is a man
    sat(D =< ~A * ~B),
    % if person 2 is a woman
    sat(~D =< ((~A # B) # (A # ~B))),

    % Prolog works
    labeling([A,B,C,D]).

我明白了:

?- solve(L).
L = [0, 0, 0, 1].

这意味着孩子是女孩,她也是1个人。人2是男人。

请注意,人1可以忽略:

:- use_module(library(clpb)).

solve(L) :-
    L = [A,B,C],
    % A : true means the child is a boy
    % B : true means the child tells the truth
    % C : true means person 2 is a man


    % person 2 "The child is a girl, the child lied"
    % if person 2 is a man
    sat(C =< ~A * ~B),
    % if person 2 is a woman
    sat(~C =< ((~A # B) # (A # ~B))),

    % Prolog works
    labeling([A,B,C]).

回答:

?- solve(L).
L = [0, 0, 1].