使用Prolog

时间:2018-02-22 03:54:29

标签: prolog zebra-puzzle

我被要求用Prolog解决类似斑马拼图的拼图。相反,我试图找到吃馅饼的个人的国籍。我知道这个问题有不同的解决方案,但我试图通过使用约束和排列来解决这个难题。但是,运行pie_eater谓词将返回false,并且在跟踪代码时它不会停止运行。

约束列表如下:

1) the Irish person lives next to the yellow house

2) the person who likes donuts lives next to the person who enjoys embroidery

3) the person who enjoys trainspotting lives next to the one who likes pizza

4) the person who enjoys pachinko likes beets

5) the Czech lives in the purple house

6) the person living in the center house listens to grunge

7) the person who enjoys glassblowing listens to hip hop

8) the American likes tofu

9) the Dutch person listens to J-Pop

10) the pink house's owner listens to country

11) the owner of the green house enjoys embroidery

12) the Irish person lives in the first house

13) the pink house is on the left of the orange house

14) the Japanese person enjoys gardening

15) the person who enjoys trainspotting has a neighbor who listens to jazz

在我的代码中,我定义了一个包含5个房屋的列表 Street 。然后,我为列表的每个元素定义了每个相应形容词的变量,以用于我的排列猜测。我将每个约束转换为代码。为了生成答案,我为每个房子的每组变量创建了排列。 在底部,我定义了谓词 leftof nextto ,以便满足问题的一些约束。

代码如下:

%who eats pie
pie_eater(PieEater) :-
        puzzle(X),
        member(house(PieEater, _, _, _, pie), X).


puzzle(Street) :- 

        Street = [H1, H2, H3, H4, H5], %street of 5 houses

        %vars for permutation
        H1 = house(Nat1, Col1, Mus1, Hob1, Food1),
        H2 = house(Nat2, Col2, Mus2, Hob2, Food2),
        H3 = house(Nat3, Col3, Mus3, Hob3, Food3),
        H4 = house(Nat4, Col4, Mus4, Hob4, Food4),
        H5 = house(Nat5, Col5, Mus5, Hob5, Food5),

        % facts
        nextto(house(irish, _, _, _, _), house(_, yellow, _, _, _), Street), %irish next to yellow house
        nextto(house(_, _, _, _, donuts), house(_, _, _, embroidery, _), Street), %donut next to embrodier lover
        nextto(house(_, _, _, trainspotting, _), house(_, _, _, _, pizza), Street),  %trainspotting next to pizza ouse      
        member(house(_, _, _, pachinko, beets), Street), %pachinko person eats beets
        member(house(czech, purple, _, _, _), Street), %czech person lives in purple house
        [_, _, house(_, _, grunge, _, _), _, _] = Street, %middle house listens to grunge
        member(house(_, _, hiphop, glassblowing, _), Street), %hiphop lover likes glassblowing
        member(house(american, _, _, _, tofu), Street), %american likes tofu
        member(house(dutch, _, jpop, _, _), Street), %dutch person likes jpop
        member(house(_, pink, country, _, _), Street),  %pink house person likes country music
        member(house(_, green, _, embroidery, _), Street), %green house person likes embroidery
        [house(irish, _, _, _, _), _, _, _, _] = Street, %irish person in first house
        leftof(house(_, pink, _, _, _),house(_, orange, _, _, _), Street),  %pink house left of orange house
        member(house(japanese, _, _, gardening, _), Street), %japanese person likes gardening
        member(house(_, _, jazz, trainspotting, _), Street), %trainspotting person likes jazz
        member(house(_, _, _, _, pie), Street), %one person likes pie

        %permutation guesses
        permutation([irish, czech, american, dutch, japanese],[Nat1, Nat2, Nat3, Nat4, Nat5]), %nat permutations
        permutation([yellow, purple, pink, green, orange],[Col1, Col2, Col3, Col4, Col5]), %color permutations
        permutation([grunge, hiphop, jpop, country, jazz],[Mus1, Mus2, Mus3, Mus4, Mus5]), %music permutation
        permutation([trainspotting, pachinko, glassblowing, embroidery, gardening],[Hob1, Hob2, Hob3, Hob4, Hob5]), %hobby permutation
        permutation([donuts, beets, pizza, tofu, pie],[Food1, Food2, Food3, Food4, Food5]). %food permutation

 %defining other predicates to help solve puzzle
 nextto(X, Y, List) :- leftof(X, Y, List). 
 nextto(X, Y, List) :- leftof(Y, X, List).

 %check if left of
 leftof(L, R, [L,R|_]).
 leftof(L, R, [_ | Rest]) :- leftof(L, R, Rest).

盯着我的代码几个小时,我觉得好像它应该工作,但我仍然无法弄清楚为什么我不能生成一个正确的排列,因为我已经定义了所有的约束。此时我被困住了。

自己做问题,我相信日本人就是答案。

3 个答案:

答案 0 :(得分:0)

约束15未正确表示。将其更改为

nextto(house(_, _, _, trainspotting, _), house(_, _, jazz, _, _), Street)

允许代码工作。

答案 1 :(得分:0)

使用debbuger运行代码,看起来这部分从未成功过。



    member(house(_, _, jazz, trainspotting, _), Street), 

调用它时,变量的内容是:

 

     H1 = house(irish, green, Mus1, embroidery, pizza)
     H2 = house(dutch, yellow, jpop, trainspotting, donuts)
     H3 = house(czech, purple, grunge, pachinko, beets)
     H4 = house(japanese, pink, country, gardening, Food4)
     H5 = house(american, orange, hiphop, glassblowing, tofu)

这些信息有帮助吗?  derpnallday的建议可能是真的(我不知道为什么他的答案被低估了。)

顺便说一句,我曾经用clpfd解决了另一个斑马问题。

以下版本的谜题出现在1962年的国际生活中:

有五所房子。 英国人住在红房子里。 西班牙人拥有这条狗。 绿房子里喝着咖啡。 乌克兰人喝茶。 温室就在象牙屋的右边。 老金吸烟者拥有蜗牛。 Kools在黄色房子里抽烟。 牛奶在中间的房子里喝醉了。 挪威人居住在第一所房子里。 吸烟切斯特菲尔德的男人和狐狸一起住在旁边的房子里。 在保留马的房子旁边的房子里抽着Kools。 Lucky Strike吸烟者喝橙汁。 日本人吸烟议会。 挪威人住在蓝屋旁边。 现在,谁喝水?谁拥有斑马?

为了清楚起见,必须补充的是,五个房屋中的每一个都被涂成不同的颜色,他们的居民有不同的国家提取,拥有不同的宠物,喝不同的饮料和吸食不同品牌的美国卷烟[原文如此] ]。另一件事:在声明6中,正确意味着你的权利。

:-use_module(library(clpfd)).

zebra_prob:-

% left ------> right
House=[Color1,Color2,Color3,Color4,Color5],
Pet=[Pet1,Pet2,Pet3,Pet4,Pet5],
Race=[Race1,Race2,Race3,Race4,Race5],
Drink=[Bev1,Bev2,Bev3,Bev4,Bev5],
Smoke=[Cig1,Cig2,Cig3,Cig4,Cig5],

% Race 1:English 2:Spaniard 3:Ukrainian 4:Norwegian 5:Japanese
% HouseColor 1:red 2:green 3:ivory 4:yellow 5:blue
% Pet 1:dog 2:snails 3:fox 4:horse 5:zebra
% Drink 1:coffee 2:tea 3:milk 4:orange juice 5:water
% Smoke 1:Old Gold 2:Kool 3:Chesterfields 4:Lucky Strike 5:Parliaments

all_different(House), %house
all_different(Pet), %pet
all_different(Race), %country
all_different(Drink), %drink
all_different(Smoke), %smoke

House ins 1..5,
Pet ins 1..5,
Race ins 1..5,
Drink ins 1..5,
Smoke ins 1..5,

% The Englishman(1) lives in the red house(1).
Race1 #= 1 #<==> Color1 #= 1,
Race2 #= 1 #<==> Color2 #= 1,
Race3 #= 1 #<==> Color3 #= 1,
Race4 #= 1 #<==> Color4 #= 1,
Race5 #= 1 #<==> Color5 #= 1,

% The Spaniard(2) owns the dog(1).
Race1 #= 2 #<==> Pet1 #= 1,
Race2 #= 2 #<==> Pet2 #= 1,
Race3 #= 2 #<==> Pet3 #= 1,
Race4 #= 2 #<==> Pet4 #= 1,
Race5 #= 2 #<==> Pet5 #= 1,

% Coffee(1) is drunk in the green house(2).
Bev1 #= 1 #<==> Color1 #= 2,
Bev2 #= 1 #<==> Color2 #= 2,
Bev3 #= 1 #<==> Color3 #= 2,
Bev4 #= 1 #<==> Color4 #= 2,
Bev5 #= 1 #<==> Color5 #= 2,

% The Ukrainian(3) drinks tea(2).
Race1 #= 3 #<==> Bev1 #= 2,
Race2 #= 3 #<==> Bev2 #= 2,
Race3 #= 3 #<==> Bev3 #= 2,
Race4 #= 3 #<==> Bev4 #= 2,
Race5 #= 3 #<==> Bev5 #= 2,

% The green house(2) is immediately to the right of the ivory house(3).
Color1 #= 3 #<==> Color2 #= 2 ,
Color2 #= 3 #<==> Color3 #= 2 ,
Color3 #= 3 #<==> Color4 #= 2 ,
Color4 #= 3 #<==> Color5 #= 2 ,

% So, green house(2) is not leftmost.
Color1 #\= 2,

% The Old Gold(1) smoker owns snails(2).
Cig1 #= 1 #<==> Pet1 #= 2,
Cig2 #= 1 #<==> Pet2 #= 2,
Cig3 #= 1 #<==> Pet3 #= 2,
Cig4 #= 1 #<==> Pet4 #= 2,
Cig5 #= 1 #<==> Pet5 #= 2,

% Kools(2) are smoked in the yellow(4) house.
Cig1 #= 2 #<==> Color1 #= 4,
Cig2 #= 2 #<==> Color2 #= 4,
Cig3 #= 2 #<==> Color3 #= 4,
Cig4 #= 2 #<==> Color4 #= 4,
Cig5 #= 2 #<==> Color5 #= 4,

% Milk(3) is drunk in the middle house.
Bev3 #= 3,

% The Norwegian(4) lives in the first house. (I assume that "first" means leftmost)
Race1 #= 4,

% The man who smokes Chesterfields(3) lives in the house next to the man with the fox(3).
(Cig1 #= 3 #/\ Pet2 #= 3) #\/
(Cig2 #= 3 #/\ Pet3 #= 3) #\/
(Cig3 #= 3 #/\ Pet4 #= 3) #\/
(Cig4 #= 3 #/\ Pet5 #= 3) #\/
(Pet1 #= 3 #/\ Cig2 #= 3) #\/
(Pet2 #= 3 #/\ Cig3 #= 3) #\/
(Pet3 #= 3 #/\ Cig4 #= 3) #\/
(Pet4 #= 3 #/\ Cig5 #= 3) ,

% Kools(2) are smoked in the house next to the house where the horse(4) is kept.
(Cig1 #= 2 #/\ Pet2 #= 4) #\/
(Cig2 #= 2 #/\ Pet3 #= 4) #\/
(Cig3 #= 2 #/\ Pet4 #= 4) #\/
(Cig4 #= 2 #/\ Pet5 #= 4) #\/
(Pet1 #= 4 #/\ Cig2 #= 2) #\/
(Pet2 #= 4 #/\ Cig3 #= 2) #\/
(Pet3 #= 4 #/\ Cig4 #= 2) #\/
(Pet4 #= 4 #/\ Cig5 #= 2) ,

% The Lucky Strike(4) smoker drinks orange juice(4).
Cig1 #= 4 #<==> Bev1 #= 4,
Cig2 #= 4 #<==> Bev2 #= 4,
Cig3 #= 4 #<==> Bev3 #= 4,
Cig4 #= 4 #<==> Bev4 #= 4,
Cig5 #= 4 #<==> Bev5 #= 4,

% The Japanese(5) smokes Parliaments(5).
Race1 #= 5 #<==> Cig1 #= 5,
Race2 #= 5 #<==> Cig2 #= 5,
Race3 #= 5 #<==> Cig3 #= 5,
Race4 #= 5 #<==> Cig4 #= 5,
Race5 #= 5 #<==> Cig5 #= 5,

% The Norwegian(4) lives next to the blue house(5).
(Race1 #= 4 #/\ Color2 #= 5) #\/
(Race2 #= 4 #/\ Color3 #= 5) #\/
(Race3 #= 4 #/\ Color4 #= 5) #\/
(Race4 #= 4 #/\ Color5 #= 5) #\/
(Color1 #= 5 #/\ Race2 #= 4) #\/
(Color2 #= 5 #/\ Race3 #= 4) #\/
(Color3 #= 5 #/\ Race4 #= 4) #\/
(Color4 #= 5 #/\ Race5 #= 4) ,

label(House),
label(Pet),
label(Race),
label(Smoke),
label(Drink),

write('house:'),write(House),nl,
write('pet:'),write(Pet),nl,
write('race:'),write(Race),nl,
write('drink:'),write(Drink),nl,
write('smoke:'),write(Smoke),nl,nl.
 

[3] 23 ?- zebra_prob.
house:[4,5,1,3,2]
pet:[3,4,2,1,5]
race:[4,3,1,2,5]
drink:[5,2,3,4,1]
smoke:[2,3,1,4,5]

true ;
false.



% Race  1:English 2:Spaniard 3:Ukrainian 4:Norwegian 5:Japanese
% HouseColor 1:red 2:green 3:ivory 4:yellow 5:blue
% Pet 1:dog 2:snails 3:fox 4:horse 5:zebra
% Drink 1:coffee 2:tea 3:milk 4:orange juice 5:water
% Smoke 1:Old Gold 2:Kool 3:Chesterfields 4:Lucky Strike 5:Parliaments

Now, who drinks water? Who owns the zebra?
5:water is drunk by 4:Norwegian
5:zebra is tamed by 5:Japanese

答案 2 :(得分:0)

以下是我过去使用过的代码:

print (df3)
  Len Bar  Amount
0   x   a       4
1   y   a       2
2   z   a       6
3   x   b       2
4   y   b       7

输出:

[house(irish, green, jazz, embroidery, pizza), house(dutch, yellow, jpop, trainspotting, donuts), house(czech, purple, grunge, pachinko, beets), house(japanese, pink, country, gardening, pie), house(american, orange, hiphop, glassblowing, tofu)]
japanese