【问题标题】:Prolog program that finds the culprit of a crime given the following factsProlog 程序根据以下事实找出犯罪的罪魁祸首
【发布时间】:2020-10-21 21:32:25
【问题描述】:

Facts about the situation -- image

(免费在线 OCR:) 警方正试图追查三个正在炼南瓜的孩子的团伙。到目前为止,他们已经确定了以下事实:孩子们的名字是安吉拉、玛丽和大卫;一个是5,一个是7,一个是8;一个姓Diamond,姓Grant的比姓Leung的大3岁。您可以假设安吉拉和玛丽是女性,而大卫是男性。

使用课堂上讨论的斑马示例中显示的技术(代码可在课程网页上找到)查找有关帮派的缺失信息:每个孩子的年龄、性别、名字和姓氏,与上面的数据。按原样对上述数据进行编码,不要添加额外的事实。适当地记录您的代码。此外,使用您的 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 函数以根据上述信息生成完整的嫌疑人表时遇到的问题。一些帮助将不胜感激。

【问题讨论】:

  • 寻找类似的问题。许多已在 StackOverflow 上发布并使用 Prolog 解决。这里还有一个常见的标签,在标签的描述中包含了Einstein这个词。
  • 作业说明“使用课堂上讨论的斑马示例中显示的技术”。你能提供课堂上的例子吗?在 Prolog 中有许多解决斑马谜题的方法你的解决方案应该符合预期的技术。
  • 我添加了斑马的例子,所以如果你能帮我把这个问题联系起来,那将不胜感激
  • 这对于 Prolog 来说似乎是一个相当糟糕的问题,因为它只是两组线索的笛卡尔积。当然 Prolog 可以做到,但其中的“逻辑”很少。

标签: prolog zebra-puzzle


【解决方案1】:

:- 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 .
*/

【讨论】:

  • 请注意,一些解决方案只是列表中术语的重新排列。实际上有 6 个独特的解决方案,其他 30 个只是重新排列。
【解决方案2】:

使用一些基本谓词非常简单:

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).

这给了我:

?- 解决(X)。 X = [[安吉拉,梁,5,女],[玛丽,钻石,7,女],[大卫,格兰特,8,男]]; X = [[安吉拉,梁,5,女],[玛丽,格兰特,8,女],[大卫,钻石,7,男]]; X = [[安吉拉,钻石,7,女],[玛丽,梁,5,女],[大卫,格兰特,8,男]]; X = [[安吉拉,格兰特,8,女],[玛丽,梁,5,女],[大卫,钻石,7,男]]; X = [[安吉拉,钻石,7,女],[玛丽,格兰特,8,女],[大卫,梁,5,男]]; X = [[安吉拉,格兰特,8,女],[玛丽,钻石,7,女],[大卫,梁,5,男]]; X = [[安吉拉,梁,5,女],[大卫,钻石,7,男],[玛丽,格兰特,8,女]]; X = [[安吉拉,梁,5,女],[大卫,格兰特,8,男],[玛丽,钻石,7,女]]; X = [[安吉拉,钻石,7,女],[大卫,梁,5,男],[玛丽,格兰特,8,女]]; X = [[安吉拉,格兰特,8,女],[大卫,梁,5,男],[玛丽,钻石,7,女]]; X = [[安吉拉,钻石,7,女],[大卫,格兰特,8,男],[玛丽,梁,5,女]]; X = [[angela,grant,8,女],[david,diamond,7,男],[mary,leung,5,女]]; X = [[玛丽,梁,5,女],[安吉拉,钻石,7,女],[大卫,格兰特,8,男]]; X = [[玛丽,梁,5,女],[安吉拉,格兰特,8,女],[大卫,钻石,7,男]]; X = [[玛丽,钻石,7,女],[安吉拉,梁,5,女],[大卫,格兰特,8,男]]; X = [[mary,grant,8,女],[angela,leung,5,女],[david,diamond,7,男]]; X = [[玛丽,钻石,7,女],[安吉拉,格兰特,8,女],[大卫,梁,5,男]]; X = [[玛丽,格兰特,8,女],[安吉拉,钻石,7,女],[大卫,梁,5,男]]; X = [[大卫,梁,5,男],[安吉拉,钻石,7,女],[玛丽,格兰特,8,女]]; X = [[大卫,梁,5,男],[安吉拉,格兰特,8,女],[玛丽,钻石,7,女]]; X = [[大卫,钻石,7,男],[安吉拉,梁,5,女],[玛丽,格兰特,8,女]]; X = [[大卫,格兰特,8,男],[安吉拉,梁,5,女],[玛丽,钻石,7,女]]; X = [[大卫,钻石,7,男],[安吉拉,格兰特,8,女],[玛丽,梁,5,女]]; X = [[大卫,格兰特,8,男],[安吉拉,钻石,7,女],[玛丽,梁,5,女]]; X = [[玛丽,梁,5,女],[大卫,钻石,7,男],[安吉拉,格兰特,8,女]]; X = [[玛丽,梁,5,女],[大卫,格兰特,8,男],[安吉拉,钻石,7,女]]; X = [[玛丽,钻石,7,女],[大卫,梁,5,男],[安吉拉,格兰特,8,女]]; X = [[玛丽,格兰特,8,女],[大卫,梁,5,男],[安吉拉,钻石,7,女]]; X = [[玛丽,钻石,7,女],[大卫,格兰特,8,男],[安吉拉,梁,5,女]]; X = [[玛丽,格兰特,8,女],[大卫,钻石,7,男],[安吉拉,梁,5,女]]; X = [[大卫,梁,5,男],[玛丽,钻石,7,女],[安吉拉,格兰特,8,女]]; X = [[大卫,梁,5,男],[玛丽,格兰特,8,女],[安吉拉,钻石,7,女]]; X = [[大卫,钻石,7,男],[玛丽,梁,5,女],[安吉拉,格兰特,8,女]]; X = [[大卫,格兰特,8,男],[玛丽,梁,5,女],[安吉拉,钻石,7,女]]; X = [[大卫,钻石,7,男],[玛丽,格兰特,8,女],[安吉拉,梁,5,女]]; X = [[大卫,格兰特,8,男],[玛丽,钻石,7,女],[安吉拉,梁,5,女]]。

【讨论】:

  • members 不是一个好的名称members(Es, S) 建议每个E 都是member(E, S)。我们可以称它为select,不同的arity 将使其分开。更有趣的是,我们也可以拥有 representation derived by Prolog
  • members 不正是按照您所说的去做吗? Es 中的每个 E 都是 S 的成员。
  • members([1,1,1],[1,2,3,4]) 是假的,不是吗。正如我所说的那样,在这里,最好将其命名为“select”。仅从这个名字我就可以期待members([A|B],C):- member(A,C), members(B,C).
  • @WillNess - 哦,是的,我明白你现在在说什么了。
【解决方案3】:

要遵循你的方法,你需要做的就是把它写下来:

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 个解决方案)。

【讨论】:

    猜你喜欢
    • 2015-04-09
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    相关资源
    最近更新 更多