我想在prolog中解决这个谜语:
学生Lily,Jack和Daisy去了同一所大学。他们都来自不同的国家,有不同的爱好。他们都去了美国的一所大学,其中一所大学就住在那里。 Lily比来自意大利的成绩更好。杰克比那些喜欢看书的人有更好的成绩。最好的成绩是喜欢足球的人。杰克来自德国,戴西喜欢做饭。
谁是谁(姓名,国家,爱好,成绩)?
正确的解决方案应该是:
我现在面临的问题是,我不知道如何解决这个谜语。我该如何定义事实以及解决这个谜题的最佳方法是什么?
答案 0 :(得分:0)
首先,从填写第一个陈述中得到的内容,我们有以下内容。
(Lily, _, _, _)
(Jack,Germany, _, _)
(Daisy, _, Cooking, _)
我们不了解_
州的情况。我还应该说,这不一定是序言,它比任何事情更常见。
我们得到的短语"莉莉比来自意大利的人有更好的成绩",这意味着黛西来自德国,莉莉来自美国 - 自杰克来自德国。 / p>
(Lily, USA, _, Grade>Daisy)
(Jack,Germany, _, _)
(Daisy, Italy, Cooking, Grade<Lily)
接下来,我们有了#41;杰克的成绩比那些喜欢读书的人更好,这让我们知道他会成为足球运动员,下一行告诉我们他的成绩最好。然后我们可以迅速填写剩余的,我们得到:
(Lily, USA, Reading, Grade2)
(Jack,Germany, Football, Grade1)
(Daisy, Italy, Cooking, Grade3)
可能有一个用prolog编写的程序可以以非常迂回的方式解决这个难题,但这个难题比一般情况更具体。
答案 1 :(得分:0)
这是我的看法。它本质上是@RdR所具有的,只是我将逻辑分解为更多的谓词,也是为了减少重载who()
主谓词。
name(lily). % (1)
name(jack).
name(daisy).
country(italy).
country(usa).
country(germany).
hobby(football).
hobby(cooking).
hobby(reading).
grade(1).
grade(2).
grade(3).
student(N,C,H,G):- % (2)
name(N), country(C), hobby(H), grade(G).
permute(P,X,Y,Z):- (4)
call(P,X), call(P,Y), call(P,Z) % (6)
, X\=Y, Y\=Z, X\=Z.
students(A,B,C):- (3)
permute(name,N1,N2,N3) % (5)
, permute(country,C1,C2,C3)
, permute(hobby,H1,H2,H3)
, permute(grade,G1,G2,G3)
, A = student(N1,C1,H1,G1) % (7)
, B = student(N2,C2,H2,G2)
, C = student(N3,C3,H3,G3)
.
who(A,B,C):- % (8)
students(A,B,C)
, A = student(lily,C1,H1,G1) % (9)
, B = student(jack,C2,H2,G2)
, C = student(daisy,C3,H3,G3)
, C2 = germany % (10)
, H3 = cooking
, (( C2=italy -> G1 < G2) % (11)
;( C3=italy -> G1 < G3))
, (( H1=reading -> G2 < G1)
;( H3=reading -> G2 < G3))
, (( H1=football -> G1 < G2, G1 < G3)
;( H2=football -> G2 < G1, G2 < G3)
;( H3=football -> G3 < G1, G3 < G2))
.
% Running it:
% ?- who(A,B,C).
% A = student(lily, usa, reading, 2),
% B = student(jack, germany, football, 1),
% C = student(daisy, italy, cooking, 3) ;
% false.
所以这里有很多内容(这引起了我的兴趣),并且可以做出不同的选择(因此它可能与@ RdR&#39的解决方案形成鲜明对比)。
student/4
(2)来简单地说明学生有这些
4个属性。这产生了所有可能的学生和他们的组合
属性,也允许它们都具有相同的名称,来自
同一个国家,asf。students/3
(3)中,我完全按照我提到的内容进行尝试
之前,创建至少不使用相同内容的学生实例
属性两次(就像两个学生有相同的爱好)。要实现这一点
必须运行我的所有属性事实(名称/ 1,国家/ 1,...),得到
每个都有三个值,并确保它们是成对不同的。permute/4
(4)
属性名称,它会将属性作为事实查找三次,
并确保绑定值都不相同。permute(name,N1,N2,N3)
(5)中致电students/3
时,会导致
查找call(P,X), call(P,Y), call(P,Z)
(6),结果与...相同
调用name(X), name(Y), name(Z)
。 (因为我正在收集3个不同的值
从总共3个具有相同属性的事实来看,这实际上与进行3个排列相同
一个3值集,因此是辅助谓词的名称。)student/4
谓词的情况下工作相同
在Prolog中即时编制这样的结构化术语。拥有student
谓词提供额外的好处,检查没有愚蠢的学生
可以构建,如学生(百合,23,asdf,-7.4)&#34;。):- students(A,B,C).
产生了3名学生的所有可能组合
他们的属性,没有使用任何涉及的属性两次。尼斯。
它还将(更难的)student()
结构包装得很方便
单字母变量,使界面更清晰。who/3
谓词(8)。它基本上使用students/3
作为生成器并尝试
通过添加更多约束来过滤掉所有不需要的解决方案(因此它有
与students/3
基本相同的签名。)student
实例,但也可以单独引用它们
(&#34; Daisy&#34;,&#34; Jack&#34;,...)和他们各自的属性(&#34; Daisy的爱好&#34;
等等。)。因此,在绑定我的结果变量A,B和C时,我进行了模式匹配
特别的名字。因此,(9)中的文字名lily
,jack
asf。这个
让我免于考虑Lily可能先进入的情况,或者作为
第二个,或第三个(因为students/3
会产生这样的排列)。所以
所有不能按顺序进入的3组学生都将被丢弃。N1 =
lily
asf这样的显式约束中完成此操作。我这样做现在执行杰克来自德国的简单事实
和雏菊喜欢烹饪(10)。当那些失败的Prolog回溯到了
初次调用students/3
,以获得可以尝试的另一组学生。student_from_attribute
需要另一个帮助器,通过名称在学生结构中找到一个值
并返回相应的值。易于支持某些语言的所有语言
一种对象/命名元组/记录,您可以在其中访问其中的字段
名称。但香草Prolog没有。所以有一些提升要做,
我无法脱离头顶的东西。who/3
谓词可以像你一样利用这个其他助手
需要从学生返回的不同属性
student_from_attribute
,就像&#39;等级&#39;,并将其与Lily的成绩进行比较。
这会使所有这些限制更好,比如
student_from_attribute([A,B,C], country, italy, S), attrib_by_name(S, grade,
G), G1 < G
。这可以以相同的方式应用于阅读和足球
约束。这不会更短,但更清洁,更通用。我不确定有人会读到这一切:-)。无论如何,这些考虑让我感到很有趣。