[rules-users] Can I solve the 'Zebra Puzzle' in drools?

Miles Wen miles.wy.1 at gmail.com
Wed Jun 15 04:25:52 EDT 2011


hello everybody,
I have some trouble in solving the 'Zebra
Puzzle<http://en.wikipedia.org/wiki/Zebra_Puzzle>'
using drools5.
I defined a class named 'House' to represent the data, and the corresponding
enums as well : Color.java, Nation.java, Pet.java, Drink.java,
Cigarette.java, here are those sources:

House.java:
public class House {

    // 颜色
    public Color color;
    // 房子从左数的位置 1-5
    public int position;
    public Nation nation;
    public Pet pet;
    public Drink drink;
    public Cigarette cigarette;
......

Color.java:

public enum Color {
    red, yellow, blue, green, ivory
}

Nation.java:

public enum Nation {
    englishman, spaniard, norwegian, ukrainian, japanese
}

Pet.java:

public enum Pet {
    dog, fox, snails, horse, zebra
}

Drink.java:

public enum Drink {
    orangeJuice, tea, coffee, milk, water
}

Cigarette.java:

public enum Cigarette {
    kools, chesterfields, winston, luckyStrike, parliaments
}

And this is my drl file:

package com.sample

import com.sample.fh.*

rule "英国人住在红色的房子里"
    when
        $h1:House(nation == Nation.englishman, color != Color.red)
        $h2:House(color == Color.red)
    then
        System.out.println("英国人(englishman)住在红色(red)的房子里");
        modify($h2){setColor($h1.color)};
        modify($h1){setColor(Color.red)};
end

rule "西班牙人养了一条狗"
    when
        $h1:House(nation == Nation.spaniard)
        $h2:House(pet == Pet.dog, nation != Nation.spaniard)
    then
        System.out.println("西班牙人(spaniard)养了一条狗(dog)");
        modify($h2){setPet($h1.pet)};
        modify($h1){setPet(Pet.dog)};
end

rule "挪威人住在左边的第一个房子里"
    when
        $h1:House(position == 1, nation != Nation.norwegian)
        $h2:House(nation == Nation.norwegian)
    then
        System.out.println("挪威人(norwegian)住在左边的第一个房子里");
        modify($h2){setNation($h1.nation)};
        modify($h1){setNation(Nation.norwegian)};
end

rule "黄房子里的人喜欢抽kools牌的香烟"
    when
        $h1:House(color == Color.yellow, cigarette != Cigarette.kools)
        $h2:House(cigarette == Cigarette.kools)
    then
        System.out.println("黄房子(yellow)里的人喜欢抽kools牌的香烟");
        modify($h2){setCigarette($h1.cigarette)};
        modify($h1){setCigarette(Cigarette.kools)};
end

rule "抽chesterfields牌香烟的人与养狐狸的人是邻居"
    when
        $h1:House(cigarette == Cigarette.chesterfields, pet != Pet.fox)
        $h2:House(pet == Pet.fox)
        $h3:House(eval(position - $h2.position == 1) || eval(position -
$h2.position == -1))
        eval($h1.position - $h2.position != 1 && $h1.position - $h2.position
!= -1)
    then
        System.out.println("抽chesterfields牌香烟的人与养狐狸(fox)的人是邻居");
        int tmp = $h3.position;
        modify($h3){setPosition($h1.position)};
        modify($h1){setPosition(tmp)};
end
rule "抽chesterfields牌香烟的人与养狐狸的人是同一人"
    when
        $h1:House(cigarette == Cigarette.chesterfields, pet == Pet.fox)
        $h2:House(eval(position - $h1.position == 1) || eval(position -
$h1.position == -1))
    then
        System.out.println("抽chesterfields牌香烟的人与养狐狸的人是同一人");
        modify($h1){setPet($h2.pet)};
        modify($h2){setPet(Pet.fox)};
end

rule "挪威人住在蓝色的房子旁边"
    when
        $h1:House(nation == Nation.norwegian)
        $h2:House(color == Color.blue)
        $h3:House(eval(position - $h2.position == 1) || eval(position -
$h2.position == -1))
        eval($h1.position - $h2.position != 1 && $h1.position - $h2.position
!= -1)
    then
        System.out.println("挪威人(norwegian)住在蓝色(blue)的房子旁边");
        modify($h1){setNation($h3.nation)};
        modify($h3){setNation(Nation.norwegian)};
end

rule "抽winston牌香烟的人养了一只蜗牛"
    when
        $h1:House(cigarette == Cigarette.winston)
        $h2:House(pet == Pet.snails, cigarette != Cigarette.winston)
    then
        System.out.println("抽winston牌香烟的人养了一只蜗牛(Snails)");
        modify($h2){setPet($h1.pet)};
        modify($h1){setPet(Pet.snails)};
end

rule "抽LuckyStrike牌香烟的人喜欢喝桔子汁"
    when
        $h1:House(cigarette == Cigarette.luckyStrike)
        $h2:House(drink == Drink.orangeJuice, cigarette !=
Cigarette.luckyStrike)
    then
        System.out.println("抽Lucky Strike牌香烟的人喜欢喝桔子汁(orange juice)");
        modify($h2){setDrink($h1.drink)};
        modify($h1){setDrink(Drink.orangeJuice)};
end

rule "乌克兰人喜欢喝茶"
    when
        $h1:House(nation == Nation.ukrainian)
        $h2:House(drink == Drink.tea, nation != Nation.ukrainian)
    then
        System.out.println("乌克兰人(ukrainian)喜欢喝茶(tea)");
        modify($h2){setDrink($h1.drink)};
        modify($h1){setDrink(Drink.tea)};
end

rule "日本人抽parliaments牌的烟"
    when
        $h1:House(nation == Nation.japanese)
        $h2:House(cigarette == Cigarette.parliaments, nation !=
Nation.japanese)
    then
        System.out.println("日本人(japanese)抽parliaments牌的烟");
        modify($h2){setCigarette($h1.cigarette)};
        modify($h1){setCigarette(Cigarette.parliaments)}
end

rule "抽kools牌的香烟的人与养马的人是邻居"
    when
        $h1:House(cigarette == Cigarette.kools)
        $h2:House(pet == Pet.horse)
        $h3:House(eval(position - $h2.position == 1) || eval(position -
$h2.position == -1))
        eval($h1.position - $h2.position != 1 && $h1.position - $h2.position
!= -1)
    then
        System.out.println("抽kools牌的香烟的人与养马(horse)的人是邻居");
        modify($h1){setCigarette($h3.cigarette)};
        modify($h3){setCigarette(Cigarette.kools)};
end

rule "喜欢喝咖啡的人住在绿房子里"
    when
        $h1:House(drink == Drink.coffee)
        $h2:House(color == Color.green, drink != Drink.coffee)
    then
        System.out.println("喜欢喝咖啡(coffee)的人住在绿(green)房子里");
        modify($h2){setColor($h1.color)};
        modify($h1){setColor(Color.green)};
end

rule "绿房子在象牙白房子的右边"
    when
        $h1:House(color == Color.green, position != 1)
        $h2:House(color == Color.ivory, position != 5)
        $h3:House(eval(position == $h2.position + 1), color != Color.green)
    then
        System.out.println("绿(green)房子在象牙白(ivory)房子的右边(图中的右边)");
        modify($h1){setColor($h3.color)};
        modify($h3){setColor(Color.green)};
end
rule "白房子已经在最右边了"
    when
        $h1:House(color == Color.ivory, position == 5)
        $h2:House(color == Color.green, position != 1)
        $h3:House(eval(position == $h2.position -1))
    then
        System.out.println("白房子已经在最右边了");
        $h3.setPosition($h1.position);
        $h1.setPosition($h2.position - 1);
        update($h3);
        update($h1);
end
rule "绿房子已经在最左边了"
    when
        $h1:House(color == Color.green, position == 1)
        $h2:House(color == Color.ivory, position != 5)
        $h3:House(eval(position == $h2.position + 1))
    then
        System.out.println("绿房子已经在最左边了");
        modify($h3){setPosition($h1.position)};
        modify($h1){setPosition($h2.position + 1)};
end
rule "绿房子在最左边且白房子在最右边"
    when
        $h1:House(color == Color.green, position == 1)
        $h2:House(color == Color.ivory, position == 5)
        $h3:House()
        $h4:House(eval(position - $h3.position == 1))
    then
        System.out.println("绿房子在最左边且白房子在最右边");
        modify($h2){setPosition($h3.position)};
        modify($h3){setPosition(5)};
        modify($h1){setPosition($h4.position)};
        modify($h4){setPosition(1)};
end

rule "中间那个房子里的人喜欢喝牛奶"
    when
        $h1:House(position == 3, drink != Drink.milk)
        $h2:House(drink == Drink.milk)
    then
        System.out.println("中间那个房子里的人喜欢喝牛奶");
        modify($h2){setDrink($h1.drink))};
        modify($h1){setDrink(Drink.milk)};
end

rule "output"
    when
        $h1:House(position == 1)
        $h2:House(position == 2)
        $h3:House(position == 3)
        $h4:House(position == 4)
        $h5:House(position == 5)

        House(nation == Nation.englishman, color == Color.red)

        House(nation == Nation.spaniard, pet == Pet.dog)

        House(position == 1, nation == Nation.norwegian)

        House(color == Color.yellow, cigarette == Cigarette.kools)

        $h6:House(cigarette == Cigarette.chesterfields)
        $h7:House(pet == Pet.fox)
        eval($h6.position - $h7.position == 1 || $h6.position - $h7.position
== -1)

        $h8:House(nation == Nation.norwegian)
        $h9:House(color == Color.blue)
        eval($h8.position - $h9.position == 1 || $h8.position - $h9.position
== -1)

        House(cigarette == Cigarette.winston, pet == Pet.snails)

        House(cigarette == Cigarette.luckyStrike, drink ==
Drink.orangeJuice)

        House(nation == Nation.ukrainian, drink == Drink.tea)

        House(cigarette == Cigarette.parliaments, nation == Nation.japanese)

        $h10:House(cigarette == Cigarette.kools)
        $h11:House(pet == Pet.horse)
        eval($h10.position - $h11.position == 1 || $h10.position -
$h11.position == -1)

        House(drink == Drink.coffee, color == Color.green)

        $h12:House(color == Color.green)
        $h13:House(color == Color.ivory)
        eval($h12.position - $h13.position == 1)

        House(position == 3, drink == Drink.milk)
    then
        System.out.println("从左到右:");

System.out.println("第一间房子是"+$h1.color+"色的;住着"+$h1.nation+"人;养"+$h1.pet+"宠物;抽"+$h1.cigarette+"牌香烟;喝"+$h1.drink+"饮料;");

System.out.println("第二间房子是"+$h2.color+"色的;住着"+$h2.nation+"人;养"+$h2.pet+"宠物;抽"+$h2.cigarette+"牌香烟;喝"+$h2.drink+"饮料;");

System.out.println("第三间房子是"+$h3.color+"色的;住着"+$h3.nation+"人;养"+$h3.pet+"宠物;抽"+$h3.cigarette+"牌香烟;喝"+$h3.drink+"饮料;");

System.out.println("第四间房子是"+$h4.color+"色的;住着"+$h4.nation+"人;养"+$h4.pet+"宠物;抽"+$h4.cigarette+"牌香烟;喝"+$h4.drink+"饮料;");

System.out.println("第五间房子是"+$h5.color+"色的;住着"+$h5.nation+"人;养"+$h5.pet+"宠物;抽"+$h5.cigarette+"牌香烟;喝"+$h5.drink+"饮料;");
end

There's some unicode character in the file.But it shouldn't bother the
compilation>...<
The rule named 'output' describes when the computation should stop. The
other rules are absorbed from the original 'Zebra puzzle' problem and each
making a little change to the working memory in order to 'approach' the
solution...(I don't know if I'm doing this wrong..)

No matter how I modify this program, it always result in an infinite loop...
For example, the console prints these messages repeatedly:

白房子已经在最右边了
抽chesterfields牌香烟的人与养狐狸的人是同一人
抽kools牌的香烟的人与养马(horse)的人是邻居
黄房子(yellow)里的人喜欢抽kools牌的香烟
抽kools牌的香烟的人与养马(horse)的人是邻居
黄房子(yellow)里的人喜欢抽kools牌的香烟
抽kools牌的香烟的人与养马(horse)的人是邻居
黄房子(yellow)里的人喜欢抽kools牌的香烟
抽kools牌的香烟的人与养马(horse)的人是邻居
黄房子(yellow)里的人喜欢抽kools牌的香烟
抽kools牌的香烟的人与养马(horse)的人是邻居
黄房子(yellow)里的人喜欢抽kools牌的香烟
......................

I worked quite much time on this problem till now, and I referenced another
solution which is programmed in prolog, but still I didn't figured out the
drools solution to this problem.
Could somebody give a hint? Any help is appreciated,
Thanks!

-- 
Regards.
Miles. Wen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/rules-users/attachments/20110615/cd2ab1fd/attachment.html 


More information about the rules-users mailing list