Prolog 程序根据以下事实找出罪犯

Prolog program that finds the culprit of a crime given the following facts

Facts about the situation -- image

(免费在线 OCR:) 警方正试图追查三个偷南瓜的孩子。到目前为止,他们已经确定了以下事实:孩子们的名字是安吉拉、玛丽和大卫;一个是5个,一个是7个,一个是8个;一个姓戴蒙德,一个姓格兰特的比姓梁的大三岁。您可以假设 Angela 和 Mary 是女性,而 David 是男性。

使用 class 中讨论的斑马示例中显示的技术(代码可在课程网页上获得)找到该帮派的缺失信息:每个 child年龄、性别、名字和姓氏,与上面的数据一致。按原样对上述数据进行编码,不要添加额外的事实。适当地记录您的代码。此外,使用您的 Prolog 代码来显示计算的信息是否唯一地标识了罪魁祸首。在文件 q2testa.txt 中提交这些测试结果及其含义的简短解释。

(Zebra Technique Example.)

相信嫌疑人可以这样组织:

suspect(Angela, _, _, female)
suspect(Mary, _, _, female)
suspect(David, _, _, male)

我也知道年龄排列如下:

suspect( _, Leung, 5, _)
suspect(_, Diamond, 7, _)
suspect(_, Grant,    8, _)

这就是我在如何创建 Prolog 函数以根据上述信息生成完整的 table 嫌疑犯的地方。一些帮助将不胜感激。


:- op(1,'xfy','contains') .

puzzle(CULPRITs)
:-
there_are_three_culprits(CULPRITs) ,
the_set_of_first_names_is_known(CULPRITs) ,
the_set_of_last_names_is_known(CULPRITs) ,
the_set_of_ages_is_known(CULPRITs) ,
one_is_three_years_older(CULPRITs)
.

there_are_three_culprits(CULPRITs)
:-
length(CULPRITs,3)
.

the_set_of_first_names_is_known(CULPRITs)
:-
CULPRITs contains {first_name:'Angela',last_name:_,age:_} ,
CULPRITs contains {first_name:'Mary',last_name:_,age:_} ,
CULPRITs contains {first_name:'David',last_name:_,age:_}
.

the_set_of_last_names_is_known(CULPRITs)
:-
CULPRITs contains {first_name:_,last_name:'Diamond',age:_} ,
CULPRITs contains {first_name:_,last_name:'Grant',age:_} ,
CULPRITs contains {first_name:_,last_name:'Leung',age:_}
.

the_set_of_ages_is_known(CULPRITs)
:-
CULPRITs contains {first_name:_,last_name:_,age:5} ,
CULPRITs contains {first_name:_,last_name:_,age:7} ,
CULPRITs contains {first_name:_,last_name:_,age:8}
.

one_is_three_years_older(CULPRITs)
:-
CULPRITs contains {first_name:_,last_name:'Grant',age:AGE_GRANT} ,
CULPRITs contains {first_name:_,last_name:'Leung',age:AGE_LEUNG} ,
AGE_GRANT is AGE_LEUNG + 3
.

CULPRITs contains CULPRIT
:-
prolog:member(CULPRIT,CULPRITs)
.


这个谜题没有明确的答案。 根据给定的线索,仍有 36 种可能的解决方案。

/*
?- puzzle(CULPRITs).

CULPRITs = [{first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Grant', age:8}, {first_name:'David', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Leung', age:5}, {first_name:'David', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Angela', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Angela', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Angela', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Leung', age:5}, {first_name:'David', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'Angela', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Grant', age:8}, {first_name:'David', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Angela', last_name:'Grant', age:8}, {first_name:'David', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Angela', last_name:'Leung', age:5}, {first_name:'David', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Angela', last_name:'Grant', age:8}, {first_name:'David', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'Angela', last_name:'Leung', age:5}, {first_name:'David', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Grant', age:8}, {first_name:'David', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Leung', age:5}, {first_name:'David', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Mary', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Mary', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Mary', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Leung', age:5}, {first_name:'David', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'Mary', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Grant', age:8}, {first_name:'David', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'David', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'David', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'David', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'David', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'David', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'David', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'David', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Mary', last_name:'Grant', age:8}, {first_name:'David', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'Mary', last_name:'Leung', age:5}, {first_name:'David', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'Mary', last_name:'Grant', age:8}, {first_name:'David', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'Mary', last_name:'Leung', age:5}, {first_name:'David', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'David', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'David', last_name:'Diamond', age:7}, {first_name:'Mary', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'David', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Leung', age:5}] ;
CULPRITs = [{first_name:'David', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Diamond', age:7}, {first_name:'Angela', last_name:'Grant', age:8}] ;
CULPRITs = [{first_name:'David', last_name:'Grant', age:8}, {first_name:'Mary', last_name:'Leung', age:5}, {first_name:'Angela', last_name:'Diamond', age:7}] ;
CULPRITs = [{first_name:'David', last_name:'Leung', age:5}, {first_name:'Mary', last_name:'Grant', age:8}, {first_name:'Angela', last_name:'Diamond', age:7}] ;
false .
*/

一些基本的谓词就很简单了:

members([],_).
members([M|Ms],Xs) :- select(M,Xs,Ys),members(Ms,Ys).

clue1(Suspects) :- members([[angela,_,_,female],[mary,_,_,female],[david,_,_,male]],Suspects).
clue2(Suspects) :- members([[_,leung,5,_],[_,diamond,7,_],[_,grant,8,_]],Suspects).

solve(Suspects) :-
    Suspects = [[_,_,_,_],[_,_,_,_],[_,_,_,_]],
    clue1(Suspects),
    clue2(Suspects).

这给了我:

?- solve(X).
X = [[angela, leung, 5, female], [mary, diamond, 7, female], [david, grant, 8, male]] ;
X = [[angela, leung, 5, female], [mary, grant, 8, female], [david, diamond, 7, male]] ;
X = [[angela, diamond, 7, female], [mary, leung, 5, female], [david, grant, 8, male]] ;
X = [[angela, grant, 8, female], [mary, leung, 5, female], [david, diamond, 7, male]] ;
X = [[angela, diamond, 7, female], [mary, grant, 8, female], [david, leung, 5, male]] ;
X = [[angela, grant, 8, female], [mary, diamond, 7, female], [david, leung, 5, male]] ;
X = [[angela, leung, 5, female], [david, diamond, 7, male], [mary, grant, 8, female]] ;
X = [[angela, leung, 5, female], [david, grant, 8, male], [mary, diamond, 7, female]] ;
X = [[angela, diamond, 7, female], [david, leung, 5, male], [mary, grant, 8, female]] ;
X = [[angela, grant, 8, female], [david, leung, 5, male], [mary, diamond, 7, female]] ;
X = [[angela, diamond, 7, female], [david, grant, 8, male], [mary, leung, 5, female]] ;
X = [[angela, grant, 8, female], [david, diamond, 7, male], [mary, leung, 5, female]] ;
X = [[mary, leung, 5, female], [angela, diamond, 7, female], [david, grant, 8, male]] ;
X = [[mary, leung, 5, female], [angela, grant, 8, female], [david, diamond, 7, male]] ;
X = [[mary, diamond, 7, female], [angela, leung, 5, female], [david, grant, 8, male]] ;
X = [[mary, grant, 8, female], [angela, leung, 5, female], [david, diamond, 7, male]] ;
X = [[mary, diamond, 7, female], [angela, grant, 8, female], [david, leung, 5, male]] ;
X = [[mary, grant, 8, female], [angela, diamond, 7, female], [david, leung, 5, male]] ;
X = [[david, leung, 5, male], [angela, diamond, 7, female], [mary, grant, 8, female]] ;
X = [[david, leung, 5, male], [angela, grant, 8, female], [mary, diamond, 7, female]] ;
X = [[david, diamond, 7, male], [angela, leung, 5, female], [mary, grant, 8, female]] ;
X = [[david, grant, 8, male], [angela, leung, 5, female], [mary, diamond, 7, female]] ;
X = [[david, diamond, 7, male], [angela, grant, 8, female], [mary, leung, 5, female]] ;
X = [[david, grant, 8, male], [angela, diamond, 7, female], [mary, leung, 5, female]] ;
X = [[mary, leung, 5, female], [david, diamond, 7, male], [angela, grant, 8, female]] ;
X = [[mary, leung, 5, female], [david, grant, 8, male], [angela, diamond, 7, female]] ;
X = [[mary, diamond, 7, female], [david, leung, 5, male], [angela, grant, 8, female]] ;
X = [[mary, grant, 8, female], [david, leung, 5, male], [angela, diamond, 7, female]] ;
X = [[mary, diamond, 7, female], [david, grant, 8, male], [angela, leung, 5, female]] ;
X = [[mary, grant, 8, female], [david, diamond, 7, male], [angela, leung, 5, female]] ;
X = [[david, leung, 5, male], [mary, diamond, 7, female], [angela, grant, 8, female]] ;
X = [[david, leung, 5, male], [mary, grant, 8, female], [angela, diamond, 7, female]] ;
X = [[david, diamond, 7, male], [mary, leung, 5, female], [angela, grant, 8, female]] ;
X = [[david, grant, 8, male], [mary, leung, 5, female], [angela, diamond, 7, female]] ;
X = [[david, diamond, 7, male], [mary, grant, 8, female], [angela, leung, 5, female]] ;
X = [[david, grant, 8, male], [mary, diamond, 7, female], [angela, leung, 5, female]].

要遵循您的方法,您需要做的就是将其写下来:

find4( Kids) :-
  Kids = [ suspect('Angela', _, _, female),
           suspect('Mary', _, _, female),
           suspect('David', _, _, male) ],
  member( suspect( _, 'Leung', 5, _), Kids),
  member( suspect(_, 'Diamond', 7, _), Kids),
  member( suspect(_, 'Grant',    8, _), Kids).

所以你实际上已经有了“按原样编码数据”的解决方案,尽管它打破了练习中指定的条件。

请注意,以大写字母开头的原子必须用单引号括起来,否则它们将被视为逻辑变量。

(之前版本的答案如下)。


循序渐进慢慢发展。

我们的第一次尝试不一定成功,只有最后一次成功。

known1(P) :-
  P = "the kids' first names are Angela, Mary, and David; 
       one is 5, one is 7, and one is 8; 
       one has the last name Diamond, and 
       the one with the last name Grant is 
          3 years older than the one with the Last name Leung. 
       Angela and Mary are female and David is male".

find1(Q) :-
  Q = "each child's age, gender, first name and last name".

known2(P) :-
  P = [ first_names = [Angela, Mary, David],
        ages =        [5,      7,    8    ],
        last_names =  [Diamond, Grant, X  ],
        ages_of = [[Grant, A1], [Leung, A2]],
        ages_diff = [      A1,          A2,    3],
        males =       [              David],
        females =     [Angela, Mary       ] ].

find2(Q) :-
  known2(P),
  ages(P,Q), genders(P,Q), first_names(P,Q), last_names(P,Q).

现在我们已经熟悉了情况,我们继续定义

find3( Kids ) :-
  Kids = [Angela, Mary, David],  first_name( Angela, angela),
                                 first_name( Mary, mary),
                                 first_name( David, david),
  member( Five,  Kids ),  age( Five, 5),
  member( Seven, Kids ),  age( Seven, 7),
  member( Eight, Kids ),  age( Eight, 8),
  member( Diamond, Kids ),  last_name( Diamond, 'Diamond'),
  member( Grant,   Kids ),  last_name( Grant, 'Grant'),
                            age(       Grant, A1),
  member( Leung,   Kids ),  last_name( Leung, 'Leung'),
                            age(       Leung,      A2),
                            3 is              A1 - A2,
                            female( Angela),
                            female( Mary),
                            male(   David).

既然我们到了这里,我们如何实现那些剩余的谓词 agemale 等?一厢情愿,原来如此:

first_name( A, N) :- attr( A, first_name-N).
age(        A, N) :- attr( A, age-N).
last_name(  A, N) :- attr( A, last_name-N).
male(       A   ) :- attr( A, gender-male).
female(     A   ) :- attr( A, gender-female).

所以我们已经到了不能再拖延实际实施的地步了:

%% (* our workhorse: *)
attr( Rep, Attr-Value) :- 
    memberchk( Attr-X, Rep),       % unique attribute names
    X = Value.

实际上就是这样:

17 ?- find3(_Kids), maplist(writeln, _Kids).
[first_name-angela,age-5,last_name-Leung,gender-female|_G5742]
[first_name-mary,age-7,last_name-Diamond,gender-female|_G5751]
[first_name-david,age-8,last_name-Grant,gender-male|_G5760]
true .

(还有 5 个解决方案)。