有没有办法在 Prolog 中扩展爱因斯坦的谜语? [英] Is there a way to extend Einstein's Riddle in Prolog?

查看:37
本文介绍了有没有办法在 Prolog 中扩展爱因斯坦的谜语?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,感谢您回答我的问题.关于这个问题,我一直在研究 Prolog 代码来模拟爱因斯坦的谜语.我认为这是一个非常优雅的解决方案,它基本上是一个包含某些字段的元组列表,例如房屋颜色、宠物、国籍等.我对列表进行了建模并且提示也在那里,但是我在尝试建模时遇到了麻烦问题.

First off, thank you for dropping by my question. On to the question, I have been working on a Prolog code to model Einstein's riddle. I think it's a pretty elegant solution, it's basically a list of tuples with certain fields such as house color, pet, nationality etc. I have the list modeled and the hints are there as well, but I'm having trouble trying to model the question.

问题是,我不想拘泥于一个简单的问题:谁拥有?".我想模拟一个更难的问题.例如:住在红色房子右边的房子里的人宠物做了什么拥有?".这似乎是对列表中索引 i 的简单检查,该列表具有颜色为 red 的元组,并返回字段 pet列表中索引 i+1 处的元组,但我使用 Prolog 的经验非常有限(这实际上是我第一次使用它),我不确定如何实现它.我将提供我在下面的代码.我感谢所有的答案.谢谢.

The thing is, I didn't want to stick to just a simple question of "Who owns the fish?". I wanted to model a harder question. For example: "What pet does the person who lives in the house which is to the right of the red house own?". It appears to be a simple check for the index i in the list which has the tuple with the color red, and return the field pet of the tuple at the index i+1 in the list, but my experience with Prolog is pretty limited (it is virtually my first time using it) and I'm not really sure how to implement it. I'll provide the code I have below. I appreciate all answers. Thank you.

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

推荐答案

我们可以对其进行编码自顶向下的风格.这意味着使用一些虚构的谓词,然后根据我们刚刚使用它们的方式来实现它们:

We can code it top-down style. This means using some made-up predicates and implementing them later, according to how we've just used them:

puzzle( P, Pet ) :- length( P, _ ),
    clue( P, [house-red , nation-brit ] ),    % (* 1. The Brit lives in red house *)
    clue( P, [keeps-dogs, nation-swede] ),    % (* 2. The Swede has dogs as pets  *)
    clue( P, [drinks-tea, nation-dane ] ),                      % (* 3. .....  *)
    clue( P,  left_of, [[house -red   ], [house -white  ]] ),   % (* 4. .....  *)
    clue( P, [house-green,  drinks-coffee  ] ),                 % (*  .......  *)
    clue( P, [keeps-birds,  smokes-pallmall] ),                   
    clue( P, [house-yellow, smokes-dunhill ] ),                   
    clue( P,  center,  [[drinks-milk  ]                  ] ),     
    clue( P,  first,   [[nation-norse ]                  ] ),     
    clue( P,  next_to, [[smokes-blends], [keeps -cats   ]] ),     
    clue( P,  next_to, [[keeps -horses], [smokes-dunhill]] ),     
    clue( P, [smokes-bluemaster, drinks-beer  ] ),                
    clue( P, [nation-german    , smokes-prince] ),
    clue( P,  next_to, [[nation-norse ], [house -blue   ]] ),
    clue( P,  next_to, [[smokes-blends], [drinks-water  ]] ),
    %% (* Who has the zebra ? *)
    clue( P, [keeps-zebra, nation- _Who] ),
    %% (* What pet the man owns who lives to the right of the red house? *)
    clue( P, right_of, [[keeps-Pet   ], [house -red    ]] ),
    maplist( length, P, _ ).

clue( P, AS ) :- member( H, P ), attrs( H, AS ).
clue( P, C, ASs ) :- G =.. [ C, P | ASs], G.

left_of(  P, AS1, AS2 ) :- append( _, [H1, H2 | _], P ),
                                           attrs( H1, AS1 ),
                                           attrs( H2, AS2 ).
next_to(  P, AS1, AS2 ) :- left_of( P, AS1, AS2 ) ; right_of( P, AS1, AS2 ).
right_of( P, AS1, AS2 ) :- left_of( P, AS2, AS1 ).
center(   P,      AS  ) :- middle( P, H ), attrs( H , AS  ).
first(  [H | _],  AS  ) :-                 attrs( H , AS  ).
middle( [H    ], H ).
middle( [_ | R], H ) :- append( X, [_], R ), middle( X, H ).

剩下的就是定义attrs/2,实现各种可扩展记录,并将它们用作基本的对象系统,以便程序学习"关于所涉及的对象的属性(这里是)只是来自他们的使用——而不是人类程序员注入他们的 通过预先确定程序中所述对象的特定表示(例如 5 元组等)来理解.

What's left is to define attrs/2, implementing extensible records of sorts, and using them as a rudimentary object system so that the program "learns" about the properties of the objects involved (here, people) just from their use -- instead of the human programmer infusing their understanding by fixing a specific representation of said objects in the program a priori (as e.g. 5-tuples, etc).

最终目标 maplist( length, P, _ ) 冻结"通过将 [] 放入它们的标记(例如,尝试 X = [1, 2 | _], length( X, _) 看看它做了什么)

The final goal maplist( length, P, _ ) "freezes" those extensible records (implemented as open-ended lists, for simplicity) by putting the [] into their sentinels (try e.g. X = [1, 2 | _], length( X, _ ) to see what it does).

开始时的目标 length( P, _ ) 提供了迭代深化方法.不幸的是,没有它,谓词循环.

The goal length( P, _ ) right at the start provides for the iterative deepening approach. Without it the predicate loops, unfortunately.

为了漂亮的打印输出,我们可以运行它

For nice printout we can run it through

test :- puzzle( P, Pet ), 
        maplist( sort, P, PS ), maplist( writeln, PS ), nl, 
        writeln( Pet ).

产生输出(手动对齐)

62 ?- test, !.
[drinks-water, house-yellow,keeps-cats,  nation-norse, smokes-dunhill   ]
[drinks-tea,   house-blue,  keeps-horses,nation-dane,  smokes-blends    ]
[drinks-milk,  house-red,   keeps-birds, nation-brit,  smokes-pallmall  ]
[drinks-beer,  house-white, keeps-dogs,  nation-swede, smokes-bluemaster]
[drinks-coffee,house-green, keeps-zebra, nation-german,smokes-prince    ]

dogs
true.

这篇关于有没有办法在 Prolog 中扩展爱因斯坦的谜语?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆