爱因斯坦谜语与术语列表

Posted

技术标签:

【中文标题】爱因斯坦谜语与术语列表【英文标题】:Einstein Riddle with List of terms 【发布时间】:2016-08-13 02:44:08 【问题描述】:

我在 Prolog 中实现了 Einstein Riddle,我正试图找出谁在家里养了一条鱼。 我在此代码中找不到错误,并且跟踪选项对解决此问题没有帮助;)

规则:

    挪威人住在第一宫 英国人住在红房子里。 温室就位于白宫的左侧。 丹麦人喝茶。 轻度吸烟者生活在猫饲养者旁边。 黄房子的居民抽着雪茄。 德国人抽水烟。 中心住宅的一位居民喝牛奶。 轻度吸烟者有一个喝水的邻居。 不带过滤嘴的香烟会繁殖鸟类。 瑞典犬。 挪威人住在蓝房子旁边。 饲养马的人住在黄房子旁边。 抽薄荷醇喝啤酒。 他们在温室里喝咖啡。

这是我的代码:

on_the_left(X, Y, N) :-
    Y is X - 1,
    \+ Y < 1,
    \+ X > N.

next_to(X, Y, N) :-
    ( Y is X + 1;
      Y is X - 1),
    \+ X > N,
    \+ Y > N,
    \+ X < 1,
    \+ Y < 1.

fish(Who) :-
    Houses = [
        house(1, _Color1, _From1, _Animal1, _Drink1, _Smoke1),
        house(2, _Color2, _From2, _Animal2, _Drink2, _Smoke2),
        house(3, _Color3, _From3, _Animal3, _Drink3, _Smoke3),
        house(4, _Color4, _From4, _Animal4, _Drink4, _Smoke4),
        house(5, _Color5, _From5, _Animal5, _Drink5, _Smoke5) ],
    N is 5,
    %-- hint 1
    member(house(1, _, norway, _, _, _), Houses),
    %-- hint 2
    member(house(_, red, england, _, _, _), Houses),
    %-- hint 3 - on_the_left
    member(house(GREEN, green, _, _, _, _), Houses),
    member(house(WHITE, white, _, _, _, _), Houses),
    on_the_left(GREEN, WHITE, N),
    %-- hint 4
    member(house(_, _, denmark, _, tea, _), Houses),
    %-- hint 5 - next_to
    member(house(LIGHT, _, _, _, _, light), Houses),
    member(house(CAT, _, _, cat, _, light), Houses),
    next_to(LIGHT, CAT, N),
    %-- hint 6
    member(house(_, yellow, _, _, _, cigar), Houses),
    %-- hint 7
    member(house(_, _, germany, _, _, waterpipe), Houses),
    %-- hint 8
    member(house(3, _, _, _, milk, _), Houses),
    %-- hint 9 - next_to
    member(house(WATER, _, _, _, water, _), Houses),
    next_to(LIGHT, WATER, N),
    %-- hint 10
    member(house(_, _, _, bird, _, nofilter), Houses),
    %-- hint 11
    member(house(_, _, sweden, dog, _, _), Houses),
    %-- hint 12 - next_to
    member(house(NORWAY, _, norway, _, _, _), Houses),
    member(house(BLUE, blue, _, _, _, _), Houses),
    next_to(NORWAY, BLUE, N),
    %-- hint 13 - next_to
    member(house(HORSE, _, _, horse, _, _), Houses),
    next_to(HORSE, GREEN, N),
    %-- hint 14
    member(house(_, _, _, _, beer, menthol), Houses),
    %-- hint 15
    member(house(_, green, _, _, coffee, _), Houses),

    %-- FINAL QUESTION - WHO LET THE FISH OUT?
    member(house(_, _, _, fish, _, _), Houses),
    member(house(_, _, Who, fish, _, _), Houses).

我尝试了很多组合但是:

?- 鱼(谁)。 假的。

编辑: 代码现在可以工作了,我改变了什么:

1* 来自:

%-- hint 5 - next_to
member(house(LIGHT, _, _, _, _, light), Houses),
member(house(CAT, _, _, cat, _, light), Houses),

收件人:

%-- hint 5 - next_to
    member(house(LIGHT, _, _, _, _, light), Houses),
    member(house(CAT, _, _, cat, _, _), Houses),

2* 来自:

%-- hint 13 - next_to   
member(house(HORSE, _, _, horse, _, _), Houses),
next_to(HORSE, GREEN, N),

收件人:

%-- hint 13 - next_to
member(house(YELLOW, yellow, _, _, _, _), Houses),
member(house(HORSE, _, _, horse, _, _), Houses),
next_to(HORSE, YELLOW, N),

如果您正在阅读这篇文章,请查看关于辅助谓词中结构的 @Enigmativity 评论。

【问题讨论】:

真的,谢谢。我添加了一条规则。 5提示中的错误已修复,但程序仍然无法运行。 【参考方案1】:

你的线索中有两个错误 - 第一个你已经用 light 吸烟者修复了。第二个是horse的主人住在yellow房子旁边,而不是green

现在,我的序言被 \+ 运算符卡住了,所以我重新编写了您的辅助谓词。这就是我所做的:

首先(H,[H|_])。 on_the_left(X,Y,[X,Y|_])。 on_the_left(X,Y,[_|Hs]) :- on_the_left(X,Y,Hs)。 next_to(X,Y,[X,Y|_])。 next_to(X,Y,[Y,X|_])。 next_to(X,Y,[_|Hs]) :- next_to(X,Y,Hs)。 中间(X,[_,_,X,_,_])。

现在这个谜题很好地利用了这些线索:

鱼(谁):- 房子= [ 房子(_Color1,_From1,_Animal1,_Drink1,_Smoke1), 房子(_Color2,_From2,_Animal2,_Drink2,_Smoke2), 房子(_Color3,_From3,_Animal3,_Drink3,_Smoke3), 房子(_Color4,_From4,_Animal4,_Drink4,_Smoke4), 房子(_Color5,_From5,_Animal5,_Drink5,_Smoke5)], first(house(_, norway, _, _, _), Houses), %-- 提示 1 member(house(red, england, _, _, _), Houses), %-- 提示 2 on_the_left(房子(绿色,_,_,_,_),房子(白色,_,_,_,_),房子),%--提示 3 - on_the_left member(house(_, denmark, _, tea, _), Houses), %-- 提示 4 next_to(house(_, _, _, _, light), house(_, _, cat, _, _), Houses), %-- 提示 5 - next_to member(house(yellow, _, _, _, cigar), Houses), %-- 提示 6 成员(房屋(_,德国,_,_,水管),房屋),%--提示 7 中间(房子(_,_,_,牛奶,_),房子),%--提示8 next_to(house(_, _, _, _, light), house(_, _, _, water, _), Houses), %-- 提示 9 - next_to member(house(_, _, bird, _, nofilter), Houses), %-- 提示 10 member(house(_, sweden, dog, _, _), Houses), %-- 提示 11 next_to(house(_, norway, _, _, _), house(blue, _, _, _, _), Houses), %-- 提示 12 - next_to next_to(house(_, _, horse, _, _), house(yellow, _, _, _, _), Houses), %-- 提示 13 - next_to member(house(_, _, _, beer, menthol), Houses), %-- 提示 14 member(house(green, _, _, coffee, _), Houses), %-- 提示 15 成员(房子(_,谁,鱼,_,_),房子), 写(房屋),NL。

我明白了:

[房子(黄色,挪威,猫,水,雪茄),房子(蓝色,丹麦,马,茶,灯),房子(红色,英国,鸟,牛奶,无过滤器),房子(绿色,德国,鱼,咖啡,水烟), 房子(白, 瑞典, 狗, 啤酒, 薄荷)] 德国

【讨论】:

谢谢,我修复了第二个错误,现在运行良好。我需要适当的睡眠;)它与我的辅助谓词版本一起使用,但像你一样编写它是更好的做法,对吧? @CryptoNewbie - 我尽量避免数字操作。 Prolog 最擅长结构化解决方案 - 所以像 middle(X,[_,_,X,_,_]). 这样的谓词既简单又结构化。我还尝试将每个线索作为fish/1 谓词中的一个术语来实现——这使得它更容易阅读,因此更容易调试和维护。这是我给你的两个建议。 哪个 Prolog 在 (\+)/1 上窒息?? @false 适用于 SWI-Prolog(多线程,64 位,版本 7.2.0) @false - Strawberry Prolog 阻塞 - “警告 4:字符串 \+ 不是运算符。”【参考方案2】:

只是为了展示另一种编码方案:

solve :- solve(Sol, From), writeln(From), maplist(writeln, Sol).

solve(Sol, From) :-
    phrase( (from(1, norway)
        ,color(red) = from(england)
        ,color(GREEN, green), color(WHITE, white), GREEN is WHITE-1
        ,from(denmark) = drink(tea)
        ,smoke(Light, light), animal(Cat, cat), next_to(Light, Cat)
        ,color(Yellow, yellow), smoke(Yellow, cigar)
        ,from(germany) = smoke(waterpipe)
        ,drink(3, milk)
        ,drink(Water, water), next_to(Light, Water)
        ,animal(bird) = smoke(nofilter)
        ,from(sweden) = animal(dog)
        ,from(NORWAY, norway), color(BLUE, blue), next_to(NORWAY, BLUE)
        ,animal(HORSE, horse), next_to(HORSE, GREEN) % next_to(HORSE, Yellow)
        ,drink(beer) = smoke(menthol)
        ,color(green) = drink(coffee)
        ,animal(Fish, fish), from(Fish, From)
    ), [[1,_,_,_,_,_],
        [2,_,_,_,_,_],
        [3,_,_,_,_,_],
        [4,_,_,_,_,_],
        [5,_,_,_,_,_]
    ], Sol).

state(S), [A,B,C,D,E] --> [A,B,C,D,E], member(S, [A,B,C,D,E]).

color(A, B)  --> state([A,B,_,_,_,_]).
from(A, B)   --> state([A,_,B,_,_,_]).
animal(A, B) --> state([A,_,_,B,_,_]).
drink(A, B)  --> state([A,_,_,_,B,_]).
smoke(A, B)  --> state([A,_,_,_,_,B]).

X = Y --> 
    X=..[Fx|Ax], Y=..[Fy|Ay],
    Xs=..[Fx,S|Ax], Ys=..[Fy,S|Ay]
, call(Xs), call(Ys).

next_to(X, Y) --> 1 is abs(X-Y).

【讨论】:

太棒了!目前,这也只产生false @mat:我留下评论了更正% next_to(HORSE, Yellow)。寻找错误的功劳确实归功于 Enigmativity

以上是关于爱因斯坦谜语与术语列表的主要内容,如果未能解决你的问题,请参考以下文章

爱因斯坦谜语中的数值比较

爱因斯坦谜语使用 Prolog

爱因斯坦之谜

列表中的唯一元素(Prolog)

[OpenGL] 斯坦福兔子与显示列表

单利与复利