有没有办法在爱洛格语中扩展爱因斯坦的谜语?

时间:2020-03-23 08:18:33

标签: prolog zebra-puzzle

首先,感谢您忽略我的问题。关于这个问题,我一直在研究Prolog代码以模拟爱因斯坦的谜语。我认为这是一个非常优雅的解决方案,它基本上是具有特定字段(例如房屋颜色,宠物,国籍等)的元组列表。我已经对列表进行了建模,提示也在那里,但是我在尝试建模时遇到了麻烦问题。

问题是,我不想仅仅回答一个简单的问题,即“谁拥有 ?”。我想建模一个更困难的问题。例如:“住在红色房子右边 的房子里的人是什么人? em>?”。这似乎是对列表中具有颜色i的元组的索引red的简单检查,然后在索引{{1}处返回元组的字段pet },但是我对Prolog的使用经验非常有限(这实际上是我第一次使用它),而且我不确定如何实现它。我将在下面提供我的代码。我感谢所有答案。谢谢。

i+1

2 个答案:

答案 0 :(得分:1)

您可以按位置访问这样的列表:

index(one,   [One, _, _, _, _],   One).
index(two,   [_, Two, _, _, _],   Two).
index(three, [_, _, Three, _, _], Three).
index(four,  [_, _, _, Four, _],  Four).
index(five(, [_, _, _, _, Five],  Five).

您还可以通过类似的方式定义next_to

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

还有更多适用于任何长度列表的通用解决方案(作为练习)。

答案 1 :(得分:1)

我们可以将其编码为自上而下的样式。这意味着使用一些虚构的谓词,并根据我们刚刚使用它们的方式在以后实现它们:

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元组等)。

最终目标maplist( length, P, _ )通过将[]放入其哨兵中来“冻结”那些可扩展记录(为简单起见,以开放式列表的形式实现)(例如尝试X = [1, 2 | _], length( X, _ )来查看哪些内容确实如此。)

一开始的目标length( P, _ )提供了迭代加深方法。不幸的是,没有它,谓词就会循环。

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

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.