Prolog 有没有办法扩展爱因斯坦';序言中的谜语是什么?

Prolog 有没有办法扩展爱因斯坦';序言中的谜语是什么?,prolog,zebra-puzzle,Prolog,Zebra Puzzle,首先,谢谢你来问我的问题。关于这个问题,我一直在编写一个序言代码来模拟爱因斯坦的谜语。我认为这是一个非常优雅的解决方案,它基本上是一个元组列表,包含某些字段,如房屋颜色、宠物、国籍等。我对列表进行了建模,并提供了提示,但我在尝试建模问题时遇到了困难 问题是,我不想只停留在一个简单的问题上:“谁拥有这条鱼?”。我想模拟一个更难的问题。例如:“住在红房子右边房子里的人拥有什么宠物?”。这似乎是一个简单的检查列表中的索引i,该索引包含颜色为red的元组,并返回列表中索引i+1处元组的字段pet,但我使

首先,谢谢你来问我的问题。关于这个问题,我一直在编写一个序言代码来模拟爱因斯坦的谜语。我认为这是一个非常优雅的解决方案,它基本上是一个元组列表,包含某些字段,如房屋颜色、宠物、国籍等。我对列表进行了建模,并提供了提示,但我在尝试建模问题时遇到了困难

问题是,我不想只停留在一个简单的问题上:“谁拥有这条鱼?”。我想模拟一个更难的问题。例如:“住在红房子右边房子里的人拥有什么宠物?”。这似乎是一个简单的检查列表中的索引
i
,该索引包含颜色为
red
的元组,并返回列表中索引
i+1
处元组的字段
pet
,但我使用Prolog的经验非常有限(这实际上是我第一次使用它)我真的不知道如何实现它。我将提供下面的代码。我感谢所有的答案。多谢各位

persoane(0, []) :- ! .
persoane(N, [(_Men, _Color, _Drink, _Smoke, _Animal)|T]) :- N1 is N-1, persoane(N1,T) .

persoana(1, [H|_], H) :- ! .
persoana(N, [_|T], R) :- N1 is N-1, persoana(N1, T, R)

% Function that tests if A is to the right of B (will be used in the final question)
right(A, B, List) :- nextto(B, A, List).

% The Brit lives in the red house
hint1([(brit, red, _, _, _)|_]) .
hint1([_|T]) :- hint1(T) .

% The Swede keeps dogs as pets
hint2([(swede, _, _, _, dog)|_]) .
hint2([_|T]) :- hint2(T) .

% The Dane drinks tea
hint3([(dane, _, tea, _, _)|_]) .
hint3([_|T]) :- hint3(T) .

% The green house is on the left of the white house
hint4([(_, green, _, _, _,),(_, white, _, _, _)|_]) .
hint4([_|T]) :- hint4(T) .

% The green house owner drinks coffee
hint5([(_, green, cofee, _, _)|_]) .
hint5([_|T]) :- hint5(T) .

% The person who smokes Pall Mall rears birds
hint6([(_, _, _, pallmall, bird)|_]) .
hint6([_|T]) :- hint6(T) .

% The owner of the yellow house smokes Dunhill
hint7([(_, yellow, _, dunhill, _)|_]) .
hint7([_|T]) :- hint7(T) .

% The man living in the center house drinks milk
hint8(persoane) :- persoana(3, persoane, (_, _, milk, _, _)) .

% The Norwegian lives in the first house
hint9(persoane) :- persoana(1, persoane, (norwegian, _, _, _, _)) .

% The man who smokes Blends lives next to the one who keeps cats
hint10([(_, _, _, blend, _),(_, _, _, _, cat)|_]) .
hint10([(_, _, _, _, cat),(_, _, _, blend, _)|_]) .
hint10([_|T]) :- hint10(T) .

% The man who keeps horses lives next to the man who smokes Dunhill
hint11([(_, _, _, dunhill, _),(_, _, _, _, horse)|_]) .
hint11([(_, _, _, _, horse),(_, _, _, dunhill, _)|_]) .
hint11([_|T]) :- hint11(T) .

% The owner who smokes BlueMaster drinks beer
hint12([(_, _, beer, bluemaster, _)|_]) .
hint12([_|T]) :- hint12(T) .

% The German smokes Prince
hint13([(german, _, _, prince, _)|_]) .
hint13([_|T]) :- hint13(T) .

% The Norwegian lives next to the blue house
hint14([(norwegian, _, _, _, _),(_, blue, _, _, _)|_]) .
hint14([(_, blue, _, _, _),(norwegian, _, _, _, _)|_]) .
hint14([_|T]) :- hint14(T) .

% The man who smokes Blend has a neighbour who drinks water
hint15([(_, _, _, blend, _),(_, _, water, _, _)|_]) .
hint15([(_, _, water, _, _),(_, _, _, blend, _)|_]) .
hint15([_|T]) :- hint15(T) .

% The question: What pet does the man who lives to the right of the red house have ?
% question (right((_, _, _, _, _), (_, red, _, _, _), persoane)) .
question([(_, red, _, _, _),()])
question([_|T]) :- question(T) .

solution(persoane) :-
   persoana(5, persoane),
   hint1(persoane),
   hint2(persoane),
   hint3(persoane),
   hint4(persoane),
   hint5(persoane),
   hint6(persoane),
   hint7(persoane),
   hint8(persoane),
   hint9(persoane),
   hint10(persoane),
   hint11(persoane),
   hint12(persoane),
   hint13(persoane),
   hint14(persoane),
   hint15(persoane),
   question(persoane) .


您可以按如下方式按位置访问列表:

index(one,   [One, _, _, _, _],   One).
index(two,   [_, Two, _, _, _],   Two).
index(three, [_, _, Three, _, _], Three).
index(four,  [_, _, _, Four, _],  Four).
index(five(, [_, _, _, _, Five],  Five).
您还可以用类似的方式定义的下一步:

next_to(List, A, B) :- left_right(List, A, B).
next_to(List, A, B) :- right_left(List, A, B).
right_left(List, A, B) :- left_right(List, B, A).
left_right([A,B,_,_,_], A,B).
left_right([_,A,B,_,_], A,B).
left_right([_,_,A,B,_], A,B).
left_right([_,_,_,A,B], A,B).
有更多的通用解决方案适用于任何长度的列表(左起为练习)。

我们可以用自顶向下的方式编写它。这意味着使用一些虚构的谓词,然后根据我们刚才使用它们的方式来实现它们:

puzzle(P,Pet):-长度(P,u),
线索(P,[红色房子,英国人],%(*1.英国人住在红色房子*)
线索(P,[养狗,瑞典人],%(*2.瑞典人养狗作为宠物*)
线索(P,[饮茶,丹麦民族],(*3……)
线索(P,左上角,[[house-red],[house-white]],%(*4……)
线索(P,[室内绿地,喝咖啡],%(*……*))
线索(P,[养鸟,吸烟],
线索(P,[房子黄色,吸烟登喜路],
线索(P,中间,[[喝牛奶]),
线索(P,第一,[[挪威民族]),
线索(P,接下来是,[[混合烟],[养猫]),
线索(P,紧挨着,[[养马],[吸登喜路]),
线索(P,[抽烟,喝啤酒],
线索(P,[德国民族,吸烟王子],
线索(P,紧挨着,[[挪威民族],[蓝色房子]),
线索(P,在[smokes blends]、[Cunds water]]的旁边,
%%(*谁有斑马?*)
线索(P,[饲养斑马,国家-_谁]),
%%(*住在红房子右边的男人有什么宠物?*)
线索(P,右边,[[养宠物],[红色房子]),
地图列表(长度,P,389;)。
线索(P,AS):-成员(H,P),属性(H,AS)。
线索(P,C,ASs):-G=。。[C,P|ASs],G。
(P,AS1,AS2)的左_:-追加(H1,H2 | P),
属性(H1,AS1),
属性(H2,AS2)。
(P,AS1,AS2)的下一个字母:(P,AS1,AS2)的左字母;(P,AS1,AS2)的右_。
(P,AS1,AS2)的右切面:-(P,AS2,AS1)的左切面。
中心(P,AS):-中间(P,H),属性(H,AS)。
第一([H | |,AS):-attrs(H,AS)。
中间([H],H)。
中间([|R],H):-附加(X,[|R],R),中间(X,H)。
剩下的就是定义、实现各种可扩展记录,并将它们用作基本的对象系统,以便程序“了解”所涉及对象的属性(这里是人)仅从它们的使用——而不是人类程序员通过在程序中预先固定所述对象的特定表示(例如5元组等)来灌输他们的理解

最后的目标是通过将
[]
放入它们的哨兵(例如,尝试
X=[1,2,|,|,|,|,|,|,|,|,|,|,|,|,|)来“冻结”这些可扩展记录(为简单起见,实现为开放式列表)

开始时的目标
长度(p,)
提供了迭代深化方法。不幸的是,如果没有它,谓词将循环

为了得到好的打印输出,我们可以运行它

test:-拼图(P,Pet),
映射列表(排序、P、PS)、映射列表(writeln、PS)、nl、,
写(宠物)。
生成输出(手动对齐)

62?-测试!。
[喝水,房子变黄,养猫,挪威民族,抽dunhill]
[喝茶,蓝色房子,养马,丹麦人,混合烟]
[喝牛奶,家红,养鸟,英国民族,吸烟]
[喝啤酒,白宫,养狗,瑞典人,抽烟,蓝领军]
[喝咖啡,室内绿化,养斑马,德国民族,吸烟王子]
狗
对。

您希望从诸如
persoane(2,X)
之类的查询中得到什么结果?(1,2,3,4,5)不是“元组”。它是
,'(1','(2','(3','(4,5))的缩写。(使用
write_canonical/1
查看此内容)。我认为您需要使用常规列表,例如
[1,2,3,4,5]
。你的系统可能有一个谓词
nth0/3
nth1/3
——看看它是如何实现的。我很确定persoane(2,X)只会返回索引2处“tuple”的信息,类似于(dane,blue,tea,blend,horse),因为这是解决爱因斯坦之谜的第二宫。我认为,如果不能从这些“元组”中提取特定的信息,比如宠物或房子的颜色,那就太好了。我转向Stackoverflow,因为我不知道如何处理这个问题。我记得我检查过像“斑马问题”这样的问题,但大多数问题都没有处理像我在问题中提到的那样更高级的问题。不过,我会研究你的建议,也许我能找到一些东西。我设法解决了这个谜,代码可以