`

Revisit again: 一道应聘智力题的编程求解, Einstein puzzle

阅读更多

Continue on: http://jellyfish.iteye.com/admin/blogs/610841, but this time we take a different approach, using ranged variables.

 

First, define all the attributes we need with a range. The reason we need this twist is that later on we can "rule out" (remove values which are not possible based on deduction).

 

import java.util.HashSet;

public class Nationality
{
    public static final Nationality BRITISH = new Nationality("British");
    public static final Nationality GERMAN = new Nationality("German");
    public static final Nationality DENMARK = new Nationality("Denmark");
    public static final Nationality SWEDISH = new Nationality("Swedish");
    public static final Nationality NORWEGIAN = new Nationality("Norwegian");

    public static final Nationality[] ALL = new Nationality[]
            { BRITISH, GERMAN, DENMARK, SWEDISH, NORWEGIAN };

    private static final String UNKNOWN = "Unknown";

    private String name;
    private HashSet<Nationality> range = new HashSet<Nationality>();

    private Nationality(String name)
    {
        this.name = name;
    }

    public static Nationality unknown()
    {
        Nationality ret = new Nationality(UNKNOWN);
        ret.addRange(BRITISH);
        ret.addRange(GERMAN);
        ret.addRange(DENMARK);
        ret.addRange(SWEDISH);
        ret.addRange(NORWEGIAN);

        return ret;
    }

    public boolean isKnown()
    {
        return !this.name.equals(UNKNOWN);
    }

    public void addRange(Nationality nationality)
    {
        this.range.add(nationality);
    }

    public void removeRange(HashSet<Nationality> range)
    {
        this.range.removeAll(range);
    }

    public void removeRange(Nationality nationality)
    {
        this.range.remove(nationality);
    }

    public boolean contains(Nationality nationality)
    {
        return range.contains(nationality);
    }

    public int hashCode() { return name.hashCode(); }

    public boolean equals(Object obj)
    {
        if (!(obj instanceof Nationality)) return false;

        Nationality n = (Nationality) obj;
        return this.name.equals(n.name);
    }

    public String toString()
    {
        if (range.size() == 0) return name;

        String ret = "";
        for (Nationality a : range) ret += a + ",";
        return name + "{" + ret.substring(0, ret.length()-1) + "}";
    }
}

 

 

and

 

import java.util.HashSet;

public class Pet
{
    public static final Pet CAT = new Pet("Cat");
    public static final Pet DOG = new Pet("Dog");
    public static final Pet FISH = new Pet("Fish");
    public static final Pet BIRD = new Pet("Bird");
    public static final Pet HORSE = new Pet("Horse");

    private static final String UNKNOWN = "Unknown";

    private String name;
    private HashSet<Pet> range = new HashSet<Pet>();

    private Pet(String name)
    {
        this.name = name;
    }

    public static Pet unknown()
    {
        Pet ret = new Pet(UNKNOWN);
        ret.addRange(CAT);
        ret.addRange(DOG);
        ret.addRange(FISH);
        ret.addRange(BIRD);
        ret.addRange(HORSE);

        return ret;
    }

    public boolean isKnown()
    {
        return !this.name.equals(UNKNOWN);
    }

    public void addRange(Pet pet)
    {
        this.range.add(pet);
    }

    public boolean removeRange(HashSet<Pet> range)
    {
        return this.range.removeAll(range);
    }

    public boolean removeRange(Pet pet)
    {
        return this.range.remove(pet);
    }

    public boolean contains(Pet pet)
    {
        return range.contains(pet);
    }

    public HashSet<Pet> getRange()
    {
        return range;
    }

    public int hashCode() { return name.hashCode(); }

    public boolean equals(Object obj)
    {
        if (!(obj instanceof Pet)) return false;

        Pet p = (Pet) obj;
        return this.name.equals(p.name);
    }

    public String toString()
    {
        if (range.size() == 0) return name;

        String ret = "";
        for (Pet a : range) ret += a + ",";
        return name + "{" + ret.substring(0, ret.length()-1) + "}";
    }
}

 

 

and

import java.util.HashSet;

public class HouseColor
{
    public static final HouseColor RED = new HouseColor("Red");
    public static final HouseColor GREEN = new HouseColor("Green");
    public static final HouseColor YELLOW = new HouseColor("Yellow");
    public static final HouseColor WHITE = new HouseColor("White");
    public static final HouseColor BLUE = new HouseColor("Blue");

    private static final String UNKNOWN = "Unknown";

    private String name;
    private HashSet<HouseColor> range = new HashSet<HouseColor>();

    private HouseColor(String name)
    {
        this.name = name;
    }

    public static HouseColor unknown()
    {
        HouseColor ret = new HouseColor(UNKNOWN);
        ret.addRange(RED);
        ret.addRange(GREEN);
        ret.addRange(YELLOW);
        ret.addRange(WHITE);
        ret.addRange(BLUE);

        return ret;
    }

    public boolean isKnown()
    {
        return !this.name.equals(UNKNOWN);
    }

    public void addRange(HouseColor houseColor)
    {
        this.range.add(houseColor);
    }

    public void removeRange(HashSet<HouseColor> range)
    {
        this.range.removeAll(range);
    }

    public boolean removeRange(HouseColor houseColor)
    {
        return this.range.remove(houseColor);
    }

    public boolean contains(HouseColor houseColor)
    {
        return range.contains(houseColor);
    }

    public HashSet<HouseColor> getRange()
    {
        return range;
    }

    public int hashCode() { return name.hashCode(); }

    public boolean equals(Object obj)
    {
        if (!(obj instanceof HouseColor)) return false;

        HouseColor c = (HouseColor) obj;
        return this.name.equals(c.name);
    }

    public String toString()
    {
        if (range.size() == 0) return name;

        String ret = "";
        for (HouseColor a : range) ret += a + ",";
        return name + "{" + ret.substring(0, ret.length()-1) + "}";
    }
}

 

 

and

import java.util.HashSet;

public class Cigarette
{
    public static final Cigarette PALL_MALL = new Cigarette("Pall Mall");
    public static final Cigarette DUNHILL = new Cigarette("Dunhill");
    public static final Cigarette BLUE_MASTER = new Cigarette("Blue Master");
    public static final Cigarette PRINCE = new Cigarette("Prince");
    public static final Cigarette BLEND = new Cigarette("Blend");

    private static final String UNKNOWN = "Unknown";

    private String name;
    private HashSet<Cigarette> range = new HashSet<Cigarette>();

    private Cigarette(String name)
    {
        this.name = name;
    }

    public static Cigarette unknown()
    {
        Cigarette ret = new Cigarette(UNKNOWN);
        ret.addRange(PALL_MALL);
        ret.addRange(DUNHILL);
        ret.addRange(BLUE_MASTER);
        ret.addRange(PRINCE);
        ret.addRange(BLEND);

        return ret;
    }

    public boolean isKnown()
    {
        return !this.name.equals(UNKNOWN);
    }

    public void addRange(Cigarette cigarette)
    {
        this.range.add(cigarette);
    }

    public void removeRange(HashSet<Cigarette> range)
    {
        this.range.removeAll(range);
    }

    public boolean removeRange(Cigarette cigarette)
    {
        return range.remove(cigarette);
    }

    public boolean contains(Cigarette cigarette)
    {
        return range.contains(cigarette);
    }

    public HashSet<Cigarette> getRange()
    {
        return range;
    }

    public int hashCode() { return name.hashCode(); }

    public boolean equals(Object obj)
    {
        if (!(obj instanceof Cigarette)) return false;

        Cigarette c = (Cigarette) obj;
        return this.name.equals(c.name);
    }

    public String toString()
    {
        if (range.size() == 0) return name;

        String ret = "";
        for (Cigarette a : range) ret += a + ",";
        return name + "{" + ret.substring(0, ret.length()-1) + "}";
    }
}

 

 

and

import java.util.HashSet;

public class Drink
{
    public static final Drink BEER = new Drink("Beer");
    public static final Drink TEA = new Drink("Tea");
    public static final Drink MILK = new Drink("Milk");
    public static final Drink WATER = new Drink("Water");
    public static final Drink COFFEE = new Drink("Coffee");

    private static final String UNKNOWN = "Unknown";

    private String name;
    private HashSet<Drink> range = new HashSet<Drink>();

    private Drink(String name)
    {
        this.name = name;
    }

    public static Drink unknown()
    {
        Drink ret = new Drink(UNKNOWN);
        ret.addRange(BEER);
        ret.addRange(TEA);
        ret.addRange(MILK);
        ret.addRange(WATER);
        ret.addRange(COFFEE);

        return ret;
    }

    public boolean isKnown()
    {
        return !this.name.equals(UNKNOWN);
    }

    public void addRange(Drink drink)
    {
        this.range.add(drink);
    }

    public void removeRange(HashSet<Drink> range)
    {
        this.range.removeAll(range);
    }

    public boolean removeRange(Drink drink)
    {
        return this.range.remove(drink);
    }

    public boolean contains(Drink drink)
    {
        return range.contains(drink);
    }

    public HashSet<Drink> getRange()
    {
        return range;
    }

    public int hashCode() { return name.hashCode(); }

    public boolean equals(Object obj)
    {
        if (!(obj instanceof Drink)) return false;

        Drink d = (Drink) obj;
        return this.name.equals(d.name);
    }

    public String toString()
    {
        if (range.size() == 0) return name;

        String ret = "";
        for (Drink a : range) ret += a + ",";
        return name + "{" + ret.substring(0, ret.length()-1) + "}";
    }
}

 

 

and

import java.util.HashSet;

public class HouseLocation
{
    public static final HouseLocation ONE = new HouseLocation("1");
    public static final HouseLocation TWO = new HouseLocation("2");
    public static final HouseLocation THREE = new HouseLocation("3");
    public static final HouseLocation FOUR = new HouseLocation("4");
    public static final HouseLocation FIVE = new HouseLocation("5");

    private static final String UNKNOWN = "Unknown";

    private String name;
    private HashSet<HouseLocation> range = new HashSet<HouseLocation>();

    private HouseLocation(String name)
    {
        this.name = name;
    }

    public static HouseLocation unknown()
    {
        HouseLocation ret = new HouseLocation(UNKNOWN);
        ret.addRange(ONE);
        ret.addRange(TWO);
        ret.addRange(THREE);
        ret.addRange(FOUR);
        ret.addRange(FIVE);

        return ret;
    }

    public boolean isKnown()
    {
        return !this.name.equals(UNKNOWN);
    }

    public void addRange(HouseLocation houseLocation)
    {
        this.range.add(houseLocation);
    }

    public boolean removeRange(HashSet<HouseLocation> range)
    {
        return this.range.removeAll(range);
    }

    public boolean removeRange(HouseLocation houseLocation)
    {
        return this.range.remove(houseLocation);
    }

    public boolean contains(HouseLocation houseLocation)
    {
        return range.contains(houseLocation);
    }

    public HashSet<HouseLocation> getRange()
    {
        return range;
    }

    public HouseLocation next()
    {
        if (this == ONE) return TWO;
        else if (this == TWO) return THREE;
        else if (this == THREE) return FOUR;
        else if (this == FOUR) return FIVE;
        else return unknown();
    }
    public HouseLocation previous()
    {
        if (this == TWO) return ONE;
        else if (this == THREE) return TWO;
        else if (this == FOUR) return THREE;
        else if (this == FIVE) return FOUR;
        else return unknown();
    }

    public boolean isLarger(HouseLocation loc)
    {
        if (!loc.isKnown()) throw new RuntimeException("try to compare to unknown!");

        int a = Integer.parseInt(name);
        int b = Integer.parseInt(loc.name);
        return a > b;
    }

    public int hashCode() { return name.hashCode(); }

    public boolean equals(Object obj)
    {
        if (!(obj instanceof HouseLocation)) return false;

        HouseLocation c = (HouseLocation) obj;
        return this.name.equals(c.name);
    }

    public String toString()
    {
        if (range.size() == 0) return name;

        String ret = "";
        for (HouseLocation a : range) ret += a + ",";
        return name + "{" + ret.substring(0, ret.length()-1) + "}";
    }
}

 

These classes more or less have the same structure. Now we use these classes to define the Person class:

 

public class Person
{
    public Nationality nationality;
    public HouseColor houseColor;
    public Pet pet;
    public Drink drink;
    public Cigarette cigarette;
    public HouseLocation houseLocation;
    public Person leftNeighbour;
    public Person rightNeighbour;

    public Person(boolean hasNeighbour)
    {
        nationality = Nationality.unknown();
        houseColor = HouseColor.unknown();
        pet = Pet.unknown();
        drink = Drink.unknown();
        cigarette = Cigarette.unknown();
        houseLocation = HouseLocation.unknown();
        if (hasNeighbour)
        {
            leftNeighbour = new Person(false); // null means no neighbour on this side
            rightNeighbour = new Person(false); // null means no neighbour on this side
        }
    }

    public String toString()
    {
        return "{" + nationality + ":" + houseColor + ":" + pet + ":" + drink + ":"
                + cigarette + ":" + houseLocation + "}" ;
    }
}

 Here the only thing unusual is the if block in the constructor because we don't want infinite recursion.

 

Now we define the clue interface:

import java.util.HashSet;

public interface Clue
{
    void apply(HashSet<Person> state);
}

 

The clue will apply to a Person set (we could use an ArrayList to avoid the hashing implicitly called by the HashSet).

 

Now the fun part is how to interpret the clues in code. As we know, some of the clues are simple and straight forward, but there are a few complex ones. Given the context of the previous post, I won't explain them

 

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Nationality;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseColor;

import java.util.HashSet;

/**
 * Set to british the color to red to remove red from all other possibilities.
 * This rule should apply only once for performance reason since once is
 * enough.
 */
public class Clue01BritishIsRed implements Clue
{
    public void apply(HashSet<Person> state)
    {
        boolean applied = false;

        for (Person p : state)
        {
            if (p.nationality == Nationality.BRITISH)
            {
                p.houseColor = HouseColor.RED;
            }
            else
            {
                if (p.houseColor.removeRange(HouseColor.RED))
                    applied = true;
            }
        }

        if (applied)
            System.out.println("rule 01 applied: British hourse color is red.");
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Nationality;
import my.test.brainteaser.einsteinpuzzle.rulebased.Pet;

import java.util.HashSet;

/**
 * set to the swedish the dog and remove dog from all other probabilities
 */
public class Clue02SwedishHasDog implements Clue
{
    public void apply(HashSet<Person> state)
    {
        boolean applied = false;

        for (Person p : state)
        {
            if (p.nationality == Nationality.SWEDISH)
            {
                p.pet = Pet.DOG;
            }
            else
            {
                if (p.pet.removeRange(Pet.DOG))
                    applied = true;
            }
        }

        if (applied)
            System.out.println("rule 02 applied: Swedish has dog.");
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Nationality;
import my.test.brainteaser.einsteinpuzzle.rulebased.Drink;

import java.util.HashSet;

public class Clue03DenmarkDrinkTea implements Clue
{
    public void apply(HashSet<Person> state)
    {
        boolean applied = false;

        for (Person p : state)
        {
            if (p.nationality == Nationality.DENMARK)
            {
                p.drink = Drink.TEA;
            }
            else
            {
                if (p.drink.removeRange(Drink.TEA))
                    applied = true;

            }
        }

        if (applied)
            System.out.println("rule 03 applied: Denmark drinks tea.");
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseColor;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseLocation;

import java.util.HashSet;
import java.util.Iterator;

public class Clue04GreenHouseIsLeftOfWhiteHouse implements Clue
{
    public void apply(HashSet<Person> state)
    {
        boolean applied = false;

        Person greenHouse = null, whiteHouse = null;
        for (Person p : state)
        {
            if (p.houseColor == HouseColor.GREEN)
            {
                greenHouse = p;
                p.rightNeighbour.houseColor = HouseColor.WHITE;
            }
            else if (p.rightNeighbour == null)
            {
                if (p.houseColor.removeRange(HouseColor.GREEN))
                    applied = true;
            }
            else if (!p.rightNeighbour.houseColor.contains(HouseColor.WHITE))
            {
                if (p.houseColor.removeRange(HouseColor.GREEN))
                    applied = true;
            }
            
            if (p.houseColor == HouseColor.WHITE)
            {
                whiteHouse = p;
                p.leftNeighbour.houseColor = HouseColor.GREEN;
            }
            else if (p.leftNeighbour == null)
            {
                if (p.houseColor.removeRange(HouseColor.WHITE))
                    applied = true;
            }
            else if (!p.leftNeighbour.houseColor.contains(HouseColor.GREEN))
            {
                if (p.houseColor.removeRange(HouseColor.WHITE))
                    applied = true;
            }

            if (greenHouse != null && whiteHouse != null)
            {
                HashSet<HouseLocation> locations = greenHouse.houseLocation.getRange();
                if (locations.size() == 2 &&
                    locations.containsAll(whiteHouse.houseLocation.getRange())) // they have same range.
                {
                    Iterator<HouseLocation> it = greenHouse.houseLocation.getRange().iterator();
                    HouseLocation ha = it.next();
                    HouseLocation hb = it.next();
                    if (ha.isLarger(hb))
                    {
                        greenHouse.houseLocation = hb;
                        whiteHouse.houseLocation = ha;
                    }
                    else
                    {
                        greenHouse.houseLocation = ha;
                        whiteHouse.houseLocation = hb;
                    }
                }
            }
        }

        if (applied)
                System.out.println("rule 04 applied: Green house is left neighbour of white house.");
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseColor;
import my.test.brainteaser.einsteinpuzzle.rulebased.Drink;

import java.util.HashSet;

public class Clue05GreenHouseHostDrinkCoffee implements Clue
{
    public void apply(HashSet<Person> state)
    {
        boolean applied = false;

        for (Person p : state)
        {
            if (p.houseColor == HouseColor.GREEN)
            {
                p.drink = Drink.COFFEE;
                for (Person pp : state)
                    if (pp.drink.removeRange(Drink.COFFEE))
                        applied = true;
            }
            else if (!p.houseColor.contains(HouseColor.GREEN))
            {
                if (p.drink.removeRange(Drink.COFFEE))
                    applied = true;
            }

            if (p.drink == Drink.COFFEE)
            {
                p.houseColor = HouseColor.GREEN;
                for (Person pp : state)
                    if (pp.houseColor.removeRange(HouseColor.GREEN))
                        applied = true;
            }
            else if (!p.drink.contains(Drink.COFFEE))
            {
                if (p.houseColor.removeRange(HouseColor.GREEN))
                    applied = true;
            }
        }

        if (applied)
            System.out.println("rule 05 applied: Green house host drinks coffee");
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Pet;
import my.test.brainteaser.einsteinpuzzle.rulebased.Cigarette;

import java.util.HashSet;

public class Clue06PallMallSmokerHasBird implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.cigarette == Cigarette.PALL_MALL)
            {
                p.pet = Pet.BIRD;
                for (Person pp : state)
                    pp.pet.removeRange(Pet.BIRD);
            }
            else if (!p.cigarette.contains(Cigarette.PALL_MALL))
                p.pet.removeRange(Pet.BIRD);

            if (p.pet == Pet.BIRD)
            {
                p.cigarette = Cigarette.PALL_MALL;
                for (Person pp : state)
                    pp.cigarette.removeRange(Cigarette.PALL_MALL);
            }
            else if (!p.pet.contains(Pet.BIRD))
                p.cigarette.removeRange(Cigarette.PALL_MALL);
        }
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Cigarette;
import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseColor;

import java.util.HashSet;

public class CLue07YellowHouseHostSmokeDunhill implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.houseColor == HouseColor.YELLOW)
            {
                p.cigarette = Cigarette.DUNHILL;
                for (Person pp : state)
                    pp.cigarette.removeRange(Cigarette.DUNHILL);
            }
            else if (!p.houseColor.contains(HouseColor.YELLOW))
                p.cigarette.removeRange(Cigarette.DUNHILL);

            if (p.cigarette == Cigarette.DUNHILL)
            {
                p.houseColor = HouseColor.YELLOW;
                for (Person pp : state)
                    pp.houseColor.removeRange(HouseColor.YELLOW);
            }
            else if (!p.cigarette.contains(Cigarette.DUNHILL))
                p.houseColor.removeRange(HouseColor.YELLOW);
        }
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Drink;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseLocation;

import java.util.HashSet;

public class Clue08MiddleHouseHostDrinkMilk implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.houseLocation == HouseLocation.THREE)
            {
                p.drink = Drink.MILK;
                for (Person pp : state)
                    pp.drink.removeRange(Drink.MILK);
            }
            else if (!p.houseLocation.contains(HouseLocation.THREE))
                p.drink.removeRange(Drink.MILK);

            if (p.drink == Drink.MILK)
            {
                p.houseLocation = HouseLocation.THREE;
                for (Person pp : state)
                    pp.houseLocation.removeRange(HouseLocation.THREE);
            }
            else if (!p.drink.contains(Drink.MILK))
                p.houseLocation.removeRange(HouseLocation.THREE);
        }
    }
}

 and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Nationality;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseLocation;

import java.util.HashSet;

public class Clue09NorwegianLiveIn1stHouse implements Clue
{
    public void apply(HashSet<Person> state)
    {
        boolean applied = false;

        for (Person p : state)
        {
            if (p.nationality == Nationality.NORWEGIAN)
            {
                p.houseLocation = HouseLocation.ONE;
                p.leftNeighbour = null;
            }
            else
            {
                if (p.houseLocation.removeRange(HouseLocation.ONE))
                    applied = true;
            }
        }

        if (applied)
            System.out.println("rule 09 applied: Norwegian lives in the 1st housr.");
    }
}

 

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Cigarette;
import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Pet;

import java.util.HashSet;

public class Clue10BlendSmokerIsNeighbourOfCatOwner implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.cigarette == Cigarette.BLEND)
            {
                if (p.leftNeighbour == null) p.rightNeighbour.pet = Pet.CAT;
                else if (p.rightNeighbour == null) p.leftNeighbour.pet = Pet.CAT;
                else if (p.leftNeighbour.pet.isKnown() && p.leftNeighbour.pet != Pet.CAT)
                    p.rightNeighbour.pet = Pet.CAT;
                else if (p.rightNeighbour.pet.isKnown() && p.rightNeighbour.pet != Pet.CAT)
                    p.leftNeighbour.pet = Pet.CAT;
            }
            else if (p.cigarette.contains(Cigarette.BLEND))
            {
                if ((p.leftNeighbour == null || !p.leftNeighbour.pet.contains(Pet.CAT)) &&
                    (p.rightNeighbour == null || !p.rightNeighbour.pet.contains(Pet.CAT)))
                    p.cigarette.removeRange(Cigarette.BLEND);
            }
            else if (p.pet == Pet.CAT)
            {
                if (p.leftNeighbour == null) p.rightNeighbour.cigarette = Cigarette.BLEND;
                else if (p.rightNeighbour == null) p.leftNeighbour.cigarette = Cigarette.BLEND;
                else if (p.leftNeighbour.cigarette.isKnown() && p.leftNeighbour.cigarette != Cigarette.BLEND)
                    p.rightNeighbour.cigarette = Cigarette.BLEND;
                else if (p.rightNeighbour.cigarette.isKnown() && p.rightNeighbour.cigarette != Cigarette.BLEND)
                    p.leftNeighbour.cigarette = Cigarette.BLEND;
            }
            else if (p.pet.contains(Pet.CAT))
            {
                if ((p.leftNeighbour == null || !p.leftNeighbour.cigarette.contains(Cigarette.BLEND)) &&
                    (p.rightNeighbour == null || !p.rightNeighbour.cigarette.contains(Cigarette.BLEND)))
                    p.pet.removeRange(Pet.CAT);
            }
        }
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Cigarette;
import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Pet;

import java.util.HashSet;

public class Clue11HorseOwnerIsNeighbourOfDunhillSmoker implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.cigarette == Cigarette.DUNHILL)
            {
                if (p.leftNeighbour == null) p.rightNeighbour.pet = Pet.HORSE;
                else if (p.rightNeighbour == null) p.leftNeighbour.pet = Pet.HORSE;
                else if (p.leftNeighbour.pet.isKnown() && p.leftNeighbour.pet != Pet.HORSE)
                    p.rightNeighbour.pet = Pet.HORSE;
                else if (p.rightNeighbour.pet.isKnown() && p.rightNeighbour.pet != Pet.HORSE)
                    p.leftNeighbour.pet = Pet.HORSE;
            }
            else if (p.cigarette.contains(Cigarette.DUNHILL))
            {
                if ((p.leftNeighbour == null || !p.leftNeighbour.pet.contains(Pet.HORSE)) &&
                    (p.rightNeighbour == null || !p.rightNeighbour.pet.contains(Pet.HORSE)))
                    p.cigarette.removeRange(Cigarette.DUNHILL);
            }

            if (p.pet == Pet.HORSE)
            {
                if (p.leftNeighbour == null) p.rightNeighbour.cigarette = Cigarette.DUNHILL;
                else if (p.rightNeighbour == null) p.leftNeighbour.cigarette = Cigarette.DUNHILL;
                else if (p.leftNeighbour.cigarette.isKnown() && p.leftNeighbour.cigarette != Cigarette.DUNHILL)
                    p.rightNeighbour.cigarette = Cigarette.DUNHILL;
                else if (p.rightNeighbour.cigarette.isKnown() && p.rightNeighbour.cigarette != Cigarette.DUNHILL)
                    p.leftNeighbour.cigarette = Cigarette.DUNHILL;
            }
            else if (p.pet.contains(Pet.HORSE))
            {
                if ((p.leftNeighbour == null || !p.leftNeighbour.cigarette.contains(Cigarette.DUNHILL)) &&
                    (p.rightNeighbour == null || !p.rightNeighbour.cigarette.contains(Cigarette.DUNHILL)))
                    p.pet.removeRange(Pet.HORSE);
            }
        }
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Cigarette;
import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Drink;

import java.util.HashSet;

public class Clue12BlueMasterSmokerDrinkBeer implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.cigarette == Cigarette.BLUE_MASTER)
            {
                p.drink = Drink.BEER;
                for (Person pp : state)
                    pp.drink.removeRange(Drink.BEER);
            }
            else if (!p.cigarette.contains(Cigarette.BLUE_MASTER))
                p.drink.removeRange(Drink.BEER);

            if (p.drink == Drink.BEER)
            {
                p.cigarette = Cigarette.BLUE_MASTER;
                for (Person pp : state)
                    pp.cigarette.removeRange(Cigarette.BLUE_MASTER);
            }
            else if (!p.drink.contains(Drink.BEER))
                p.cigarette.removeRange(Cigarette.BLUE_MASTER);
        }
    }
}

 

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Cigarette;
import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Nationality;

import java.util.HashSet;

public class Clue13GermanSmokePrince implements Clue
{
    public void apply(HashSet<Person> state)
    {
        boolean applied = false;

        for (Person p : state)
        {
            if (p.nationality == Nationality.GERMAN)
            {
                p.cigarette = Cigarette.PRINCE;
            }
            else
            {
                if (p.cigarette.removeRange(Cigarette.PRINCE))
                    applied = true;
            }
        }

        if (applied)
            System.out.println("rule 13 applied: German smokes prince.");
    }
}

 

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Nationality;
import my.test.brainteaser.einsteinpuzzle.rulebased.HouseColor;

import java.util.HashSet;

public class Clue14NorwegianIsNeighbourOfBlueHouse implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.nationality.equals(Nationality.NORWEGIAN))
            {
                p.houseColor.removeRange(HouseColor.BLUE);

                if (p.leftNeighbour == null)
                    p.rightNeighbour.houseColor = HouseColor.BLUE;
                else if (p.leftNeighbour.houseColor.isKnown() && p.leftNeighbour.houseColor != HouseColor.BLUE)
                    p.rightNeighbour.houseColor = HouseColor.BLUE;
                else if (p.rightNeighbour == null)
                    p.leftNeighbour.houseColor = HouseColor.BLUE;
                else if (p.rightNeighbour.houseColor.isKnown() && p.rightNeighbour.houseColor != HouseColor.BLUE)
                    p.leftNeighbour.houseColor = HouseColor.BLUE;
            }
        }
    }
}

 

and

import my.test.brainteaser.einsteinpuzzle.rulebased.Cigarette;
import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;
import my.test.brainteaser.einsteinpuzzle.rulebased.Person;
import my.test.brainteaser.einsteinpuzzle.rulebased.Drink;

import java.util.HashSet;

public class Clue15BlendSmokerIsNeighourOfWaterDrinker implements Clue
{
    public void apply(HashSet<Person> state)
    {
        for (Person p : state)
        {
            if (p.cigarette == Cigarette.BLEND)
            {
                if (p.leftNeighbour == null) p.rightNeighbour.drink = Drink.WATER;
                else if (p.rightNeighbour == null) p.leftNeighbour.drink = Drink.WATER;
                else if (p.leftNeighbour.drink.isKnown() && p.leftNeighbour.drink != Drink.WATER)
                    p.rightNeighbour.drink = Drink.WATER;
                else if (p.rightNeighbour.drink.isKnown() && p.rightNeighbour.drink != Drink.WATER)
                    p.leftNeighbour.drink = Drink.WATER;                
            }
            else if (p.cigarette.contains(Cigarette.BLEND))
            {
                if ((p.leftNeighbour == null || !p.leftNeighbour.drink.contains(Drink.WATER)) &&
                    (p.rightNeighbour == null || !p.rightNeighbour.drink.contains(Drink.WATER)))
                    p.cigarette.removeRange(Cigarette.BLEND);
            }

            if (p.drink == Drink.WATER)
            {
                if (p.leftNeighbour == null) p.rightNeighbour.cigarette = Cigarette.BLEND;
                else if (p.rightNeighbour == null) p.leftNeighbour.cigarette = Cigarette.BLEND;
                else if (p.leftNeighbour.cigarette.isKnown() && p.leftNeighbour.cigarette != Cigarette.BLEND)
                    p.rightNeighbour.cigarette = Cigarette.BLEND;
                else if (p.rightNeighbour.cigarette.isKnown() && p.rightNeighbour.cigarette != Cigarette.BLEND)
                    p.leftNeighbour.cigarette = Cigarette.BLEND;
            }
            else if (p.drink.contains(Drink.WATER))
            {
                if ((p.leftNeighbour == null || !p.leftNeighbour.cigarette.contains(Cigarette.BLEND)) &&
                    (p.rightNeighbour == null || !p.rightNeighbour.cigarette.contains(Cigarette.BLEND)))
                    p.drink.removeRange(Drink.WATER);
            }
        }        
    }
}

 

A factory class to initiate all of them:

 

import my.test.brainteaser.einsteinpuzzle.rulebased.Clue;

public class ClueFactory
{
    public static Clue[] clues = new Clue[] {
            new Clue01BritishIsRed(),
            new Clue02SwedishHasDog(),
            new Clue03DenmarkDrinkTea(),
            new Clue04GreenHouseIsLeftOfWhiteHouse(),
            new Clue05GreenHouseHostDrinkCoffee(),
            new Clue06PallMallSmokerHasBird(),
            new CLue07YellowHouseHostSmokeDunhill(),
            new Clue08MiddleHouseHostDrinkMilk(),
            new Clue09NorwegianLiveIn1stHouse(),
            new Clue10BlendSmokerIsNeighbourOfCatOwner(),
            new Clue11HorseOwnerIsNeighbourOfDunhillSmoker(),
            new Clue12BlueMasterSmokerDrinkBeer(),
            new Clue13GermanSmokePrince(),
            new Clue14NorwegianIsNeighbourOfBlueHouse(),
            new Clue15BlendSmokerIsNeighourOfWaterDrinker()
    };
    
    public static Clue[] create()
    {
        return clues;
    }
}

 

With all these, we are ready for the puzzle class:

 

import my.test.brainteaser.einsteinpuzzle.rulebased.clues.ClueFactory;

import java.util.HashSet;

/**
 * Einstein Brain Teaser
 *
 * Rules:
 * 1. There are 5 houses in 5 different colours.
 * 2. In each house lives a person with a different nationality.
 * 3. These 5 owners drink a certain beverage, smoke a certain brand of cigarette and keep a certain pet.
 * 4. No owners have the same pet, brand of cigarette, or drink.
 *
 * Clues:
 * 1. The Brit lives in a red house
 * 2. The Swede keeps a dog
 * 3. The Dane drinks tea
 * 4. The green house is on the left of the white house.
 * 5. The green house owner drinks coffee.
 * 6. The person who smokes Pall Mall keeps birds.
 * 7. The owner of the yellow house smokes Dunhill.
 * 8. The man living in the house right in the center drinks milk
 * 9. The Norwegian lives in the first house.
 * 10. The man who smokes Blend lives next to the one who keeps cats
 * 11. The man who keeps horses lives next to the man who smokes Dunhill
 * 12. The owner who smokes Camel drinks beer
 * 13. The German smokes Marlborough.
 * 14. The Norwegian lives next to the blue house
 * 15. The man who smokes Blend has a neighbour who drinks water.
 */
public class EinsteinPuzzle
{
    public static void main(String[] args)
    {
        long begin = System.currentTimeMillis();

        EinsteinPuzzle puzzle = new EinsteinPuzzle();
        puzzle.solve();

        System.out.println("time taken=" + (System.currentTimeMillis() - begin));
    }

    public void solve()
    {
        HashSet<Person> states = init();
        Clue[] clues = ClueFactory.clues;
        int limit = 1;

        do
        {
            for (Clue c : clues)
            {
                c.apply(states);
            }

            reconAttributes(states);

            reconPeople(states);

            System.out.println("step=" + limit);
            print(states);

            limit++;
        } while (checkAttributes(states));
    }

    private void reconAttributes(HashSet<Person> states)
    {
        for (Person p : states)
        {
            if (p.houseColor.getRange().size() == 1)
            {
                p.houseColor = p.houseColor.getRange().iterator().next();
                for (Person pp : states)
                    pp.houseColor.removeRange(p.houseColor);
            }
            if (p.houseLocation.getRange().size() == 1)
            {
                p.houseLocation = p.houseLocation.getRange().iterator().next();
                for (Person pp : states)
                    pp.houseLocation.removeRange(p.houseLocation);
            }
            if (p.pet.getRange().size() == 1)
            {
                p.pet = p.pet.getRange().iterator().next();
                for (Person pp : states)
                    pp.pet.removeRange(p.pet);
            }
            if (p.drink.getRange().size() == 1)
            {
                p.drink = p.drink.getRange().iterator().next();
                for (Person pp : states)
                    pp.drink.removeRange(p.drink);
            }
            if (p.cigarette.getRange().size() == 1)
            {
                p.cigarette = p.cigarette.getRange().iterator().next();
                for (Person pp : states)
                    pp.cigarette.removeRange(p.cigarette);
            }
        }
    }

    private void reconPeople(HashSet<Person> states)
    {
        for (Person p : states)
        {
            HashSet<Person> people = new HashSet<Person>(states);
            if (p.leftNeighbour != null)
            {
                removeUnmatched(states, people, p.leftNeighbour);
            }

            if (people.size() == 1)
            {
                Person n = people.iterator().next();
                merge(n, p.leftNeighbour, states);
                p.leftNeighbour = n;
                if (p.houseLocation.isKnown())
                    n.houseLocation = p.houseLocation.previous();
            }
        }
                          
        for (Person p : states)
        {
            HashSet<Person> people = new HashSet<Person>(states);
            if (p.rightNeighbour != null)
            {
                removeUnmatched(states, people, p.rightNeighbour);
            }
            if (people.size() == 1)
            {
                Person n = people.iterator().next();
                merge(n, p.rightNeighbour, states);
                p.rightNeighbour = n;
                if (p.houseLocation.isKnown())
                    n.houseLocation = p.houseLocation.next();
            }
        }
    }

    private void merge(Person mergeTo, Person toBeMerged, HashSet<Person> people)
    {
        if (toBeMerged.nationality.isKnown())
        {
            mergeTo.nationality = toBeMerged.nationality;
            for (Person p : people)
            {
                p.nationality.removeRange(toBeMerged.nationality);
            }
        }
        if (toBeMerged.houseColor.isKnown())
        {
            mergeTo.houseColor = toBeMerged.houseColor;
            for (Person p : people)
            {
                p.houseColor.removeRange(toBeMerged.houseColor);
            }
        }
        if (toBeMerged.houseLocation.isKnown())
        {
            mergeTo.houseLocation = toBeMerged.houseLocation;
            for (Person p : people)
            {
                p.houseLocation.removeRange(toBeMerged.houseLocation);
            }
        }
        if (toBeMerged.pet.isKnown())
        {
            mergeTo.pet = toBeMerged.pet;
            for (Person p : people)
            {
                p.pet.removeRange(toBeMerged.pet);
            }
        }
        if (toBeMerged.drink.isKnown())
        {
            mergeTo.drink = toBeMerged.drink;
            for (Person p : people)
            {
                p.drink.removeRange(toBeMerged.drink);
            }
        }
        if (toBeMerged.cigarette.isKnown())
        {
            mergeTo.cigarette = toBeMerged.cigarette;
            for (Person p : people)
            {
                p.cigarette.removeRange(toBeMerged.cigarette);
            }
        }
    }
    private void removeUnmatched(HashSet<Person> states, HashSet<Person> people, Person neighbour)
    {
        if (neighbour.houseColor.isKnown())
        {
            for (Person pp : states)
            {
                if (pp.houseColor != neighbour.houseColor &&
                    !pp.houseColor.contains(neighbour.houseColor))
                    people.remove(pp);
            }
        }

        if (neighbour.houseLocation.isKnown())
        {
            for (Person pp : states)
            {
                if (pp.houseLocation != neighbour.houseLocation &&
                    !pp.houseLocation.contains(neighbour.houseLocation))
                    people.remove(pp);
            }
        }

        if (neighbour.pet.isKnown())
        {
            for (Person pp : states)
            {
                if (pp.pet != neighbour.pet &&
                    !pp.pet.contains(neighbour.pet))
                    people.remove(pp);
            }
        }

        if (neighbour.drink.isKnown())
        {
            for (Person pp : states)
            {
                if (pp.drink != neighbour.drink &&
                    !pp.drink.contains(neighbour.drink))
                    people.remove(pp);
            }
        }

        if (neighbour.cigarette.isKnown())
        {
            for (Person pp : states)
            {
                if (pp.cigarette != neighbour.cigarette &&
                    !pp.cigarette.contains(neighbour.cigarette))
                    people.remove(pp);
            }
        }
    }

    private void print(HashSet<Person> states)
    {
        int i=0;
        for (Person p : states)
        {
            System.out.println("state(" + i + ")=" + p);
            i++;
        }
        System.out.println("========================================================");
    }

    private boolean checkAttributes(HashSet<Person> states)
    {
        for (Person p : states)
        {
            if (!p.houseColor.isKnown()) return true;
            if (!p.houseLocation.isKnown()) return true;
            if (!p.pet.isKnown()) return true;
            if (!p.drink.isKnown()) return true;
            if (!p.cigarette.isKnown()) return true;
        }

        return false;
    }

    public HashSet<Person> init()
    {
        HashSet<Person> initialState = new HashSet<Person>();

        Person p;
        for (Nationality n : Nationality.ALL)
        {
            p = new Person(true);
            p.nationality = n;
            initialState.add(p);
        }

        return initialState;
    }
}

 

I believe I forget the package names, but you can easily fix that.

 

The result is like this:

 

rule 01 applied: British hourse color is red.
rule 02 applied: Swedish has dog.
rule 03 applied: Denmark drinks tea.
rule 05 applied: Green house host drinks coffee
rule 09 applied: Norwegian lives in the 1st housr.
rule 13 applied: German smokes prince.
step=1
state(0)={German:Unknown{Blue,White,Green,Yellow}:Unknown{Bird,Cat,Horse,Fish}:Unknown{Coffee,Beer,Milk,Water}:Prince:Unknown{3,2,5,4}}
state(1)={Denmark:Unknown{Blue,White,Yellow}:Unknown{Bird,Cat,Horse,Fish}:Tea:Unknown{Pall Mall,Blend,Dunhill}:Unknown{2,5,4}}
state(2)={Norwegian:Unknown{White,Green,Yellow}:Unknown{Bird,Cat,Horse,Fish}:Unknown{Coffee,Beer,Milk,Water}:Unknown{Blue Master,Pall Mall,Blend,Dunhill}:1}
state(3)={Swedish:Unknown{Blue,White,Green,Yellow}:Dog:Unknown{Coffee,Beer,Milk,Water}:Unknown{Blue Master,Blend,Dunhill}:Unknown{3,2,5,4}}
state(4)={British:Red:Unknown{Bird,Cat,Horse,Fish}:Unknown{Beer,Milk,Water}:Unknown{Blue Master,Pall Mall,Blend}:Unknown{3,2,5,4}}
========================================================
rule 04 applied: Green house is left neighbour of white house.
rule 05 applied: Green house host drinks coffee
step=2
state(0)={German:Unknown{Blue,White,Green}:Unknown{Cat,Horse,Fish}:Unknown{Coffee,Milk,Water}:Prince:Unknown{3,2,5,4}}
state(1)={Denmark:Unknown{Blue,White}:Unknown{Bird,Cat,Horse,Fish}:Tea:Unknown{Pall Mall,Blend,Dunhill}:Unknown{2,5,4}}
state(2)={Norwegian:Yellow:Unknown{Bird,Cat,Horse,Fish}:Unknown{Beer,Water}:Unknown{Blue Master,Pall Mall,Blend,Dunhill}:1}
state(3)={Swedish:Unknown{Blue,White,Green}:Dog:Unknown{Coffee,Beer,Milk,Water}:Unknown{Blue Master,Blend,Dunhill}:Unknown{3,2,5,4}}
state(4)={British:Red:Unknown{Bird,Cat,Horse,Fish}:Unknown{Beer,Milk,Water}:Unknown{Blue Master,Pall Mall,Blend}:Unknown{3,2,5,4}}
========================================================
step=3
state(0)={German:Unknown{Blue,White,Green}:Unknown{Cat,Horse,Fish}:Unknown{Coffee,Milk}:Prince:Unknown{3,2,5,4}}
state(1)={Denmark:Unknown{Blue,White}:Unknown{Bird,Cat,Horse,Fish}:Tea:Unknown{Pall Mall,Blend}:Unknown{2,5,4}}
state(2)={Norwegian:Yellow:Unknown{Bird,Cat,Horse,Fish}:Water:Dunhill:1}
state(3)={Swedish:Unknown{Blue,White,Green}:Dog:Unknown{Coffee,Beer,Milk}:Unknown{Blue Master,Blend}:Unknown{3,2,5,4}}
state(4)={British:Red:Unknown{Bird,Cat,Horse,Fish}:Unknown{Beer,Milk}:Unknown{Blue Master,Pall Mall,Blend}:Unknown{3,2,5,4}}
========================================================
step=4
state(0)={German:Unknown{White,Green}:Unknown{Cat,Fish}:Unknown{Coffee,Milk}:Prince:Unknown{3,2,5,4}}
state(1)={Denmark:Blue:Horse:Tea:Blend:2}
state(2)={Norwegian:Yellow:Unknown{Cat,Fish}:Water:Dunhill:1}
state(3)={Swedish:Unknown{White,Green}:Dog:Unknown{Coffee,Beer,Milk}:Unknown{Blue Master}:Unknown{3,2,5,4}}
state(4)={British:Red:Unknown{Bird,Cat,Fish}:Unknown{Beer,Milk}:Unknown{Blue Master,Pall Mall}:Unknown{3,2,5,4}}
========================================================
step=5
state(0)={German:Unknown{White,Green}:Unknown{Cat}:Unknown{Coffee,Milk}:Prince:Unknown{3,5,4}}
state(1)={Denmark:Blue:Horse:Tea:Blend:2}
state(2)={Norwegian:Yellow:Fish:Water:Dunhill:1}
state(3)={Swedish:Unknown{White,Green}:Dog:Unknown{Coffee,Beer,Milk}:Blue Master:Unknown{3,5,4}}
state(4)={British:Red:Unknown{Bird,Cat}:Unknown{Beer,Milk}:Pall Mall:Unknown{3,5,4}}
========================================================
step=6
state(0)={German:Unknown{White,Green}:Cat:Unknown{Coffee}:Prince:Unknown{3,5,4}}
state(1)={Denmark:Blue:Horse:Tea:Blend:2}
state(2)={Norwegian:Yellow:Fish:Water:Dunhill:1}
state(3)={Swedish:Unknown{White,Green}:Dog:Beer:Blue Master:Unknown{3,5,4}}
state(4)={British:Red:Bird:Milk:Pall Mall:Unknown{3,5,4}}
========================================================
rule 05 applied: Green house host drinks coffee
step=7
state(0)={German:Unknown{Green}:Cat:Coffee:Prince:Unknown{5,4}}
state(1)={Denmark:Blue:Horse:Tea:Blend:2}
state(2)={Norwegian:Yellow:Fish:Water:Dunhill:1}
state(3)={Swedish:White:Dog:Beer:Blue Master:Unknown{5,4}}
state(4)={British:Red:Bird:Milk:Pall Mall:3}
========================================================
step=8
state(0)={German:Green:Cat:Coffee:Prince:Unknown{5,4}}
state(1)={Denmark:Blue:Horse:Tea:Blend:2}
state(2)={Norwegian:Yellow:Fish:Water:Dunhill:1}
state(3)={Swedish:White:Dog:Beer:Blue Master:Unknown{5,4}}
state(4)={British:Red:Bird:Milk:Pall Mall:3}
========================================================
step=9
state(0)={German:Green:Cat:Coffee:Prince:4}
state(1)={Denmark:Blue:Horse:Tea:Blend:2}
state(2)={Norwegian:Yellow:Fish:Water:Dunhill:1}
state(3)={Swedish:White:Dog:Beer:Blue Master:5}
state(4)={British:Red:Bird:Milk:Pall Mall:3}
========================================================
time taken=31

Process finished with exit code 0

 

The only thing I don't like is the puzzle class is too large, about <300 lines. I would've refactor it to <200 lines.

分享到:
评论

相关推荐

    github-revisit:修订git和github

    Git是一款分布式版本控制系统,而GitHub则是一个基于Git的在线托管平台,提供了丰富的社交编程功能。本篇文章将深入探讨Git的基础命令以及如何在GitHub上进行有效的协作。 首先,我们需要了解Git的基本操作。在本地...

    revisit_watcher:监控revisitvocab.com的可访问性

    : :red_square: 完全中断该存储库包含由支持的的开源正常运行时间监控器和状态页面。 借助 ,您可以获得自己不受限制的免费正常运行时间监控器和状态页面,该页面完全由GitHub存储库提供支持。...

    clvisit:reVisit 客户端的通讯器

    **clvisit:reVisit 客户端通讯器详解** `clvisit:reVisit` 是一个专为实现客户端与服务器端高效通信的工具,其主要功能是处理客户沟通的重访需求。在现代软件开发中,尤其是在构建Web应用或移动应用时,实时通信是...

    Rethink, Revisit, Revise A Spiral Reinforced Self-Revised Networ

    总结起来,"Rethink, Revisit, Revise A Spiral Reinforced Self-Revised Network for Zero-Shot Learning" 提出了一种新颖的策略,通过螺旋式学习和自我修订,改进了ZSL中的语义关联学习。这种方法不仅提高了模型的...

    revisit-severson-et-al:论文“用于精确和可解释的电池寿命预测的统计学习”资料库

    该存储库包含有关我们的工作的代码,题为“统计学习以进行准确且可解释的电池寿命预测”,这是的后续论文 有关Zenodo的这项工作的永久档案可在这里找到: 我们的关键脚本和功能总结如下: featuregeneration.m ...

    Introductory Chapter_ A Revisit to Optical Amplifiers.pdf

    第一章 引言:光放大器的再探讨 班纳吉·库马尔·乔杜里 更多信息可在章节末尾获取 DOI:10.5772/intechopen.78671 暂定章节 引言 信息时代可以被视为快速、高带宽通信的时代,其中光纤通信系统发挥了关键作用。...

    huashiyiqike/LSTM-MATLAB:LSTM_MATLAB 旨在简洁、说明性和仅用于研究目的。-matlab开发

    附有论文供参考:[Revisit Long Short-Term Memory: An Optimization Perspective],NIPS 深度学习研讨会,2014。 #特征- 原始的长期短期记忆- 所有连接窥视Kong- CPU 或 GPU 加速- Mapreduce 并行化- 梯度检查- ...

    Multi-View Stereo Representation Revisit Region-Aware MVSNet.pdf

    多视图立体三维重建MVS论文

    (Colored ICP算法)ICCV2017_Colored Point Cloud Registration Revisit

    在计算机视觉、计算机图形学和机器人领域,一个常见的问题是给定两个充分对齐的三维点云,计算它们之间的紧密对齐。... ...现代深度相机可以生成深度和颜色图像对,许多工业3D扫描仪也配备了同步色彩摄像头,并能将颜色...

    港股公司研究-信达国际控股-信利国际00732.HKIts time to revisit.pdf

    【信达国际控股对信利国际00732.HK的研究报告】 信利国际,成立于1978年,是中国最大的手机显示屏供应商和第二大电容触摸屏供应商,客户群多元化,主要针对国内品牌,包括三星、小米、OPPO、Vivo等。...

    英语CET4等级考试资料

    - **Revisit**:重新访问 - **Revise**:修订 - **Super-**:表示“在……之上”,例如: - **Supervise**:监督 - **Tele-**:表示“远距离”,例如: - **Television**:电视 #### 4. 词汇变化 - **Let**:...

    hadoop中文文档

    2. **自适应重访主机队列(Adaptive Revisit Host Queue)**: - 功能:按主机分组管理待处理URL。 - 作用:提高处理效率。 3. **自适应重访队列列表(Adaptive Revisit Queue List)**: - 功能:管理多个...

    react-code-revisit-v17

    Create React App入门该项目是通过引导的。可用脚本在项目目录中,可以运行:npm start 在开发模式下运行应用程序。 打开在浏览器中查看它。 如果您进行编辑,则页面将重新加载。 您还将在控制台中看到任何棉绒错误...

    The Python Master

    Our books, which use Python 3, follow a spiral curriculum: We introduce topics gently and then revisit them on multiple occasions to add the depth required to support your progression as a Python ...

    Deep Learning: Recurrent Neural Networks in Python

    We are going to revisit the XOR problem, but we’re going to extend it so that it becomes the parity problem - you’ll see that regular feedforward neural networks will have trouble solving this ...

    STK覆盖模块教材

    ### STK覆盖模块教材知识点详解 #### 一、概述 STK (Satellite Tool Kit) 是一款著名的卫星仿真软件,广泛应用于卫星系统的设计与分析之中。本教材主要介绍STK9.0版本中的覆盖模块,该模块专注于分析一颗或多颗卫星...

    15个实用可视化工具.pptx

    11. **Revisit**:这可能是一个时间轴工具,用于创建和分享历史事件、项目进度或其他按时间顺序排列的内容的可视化。 12. **Google Fusion Tables**:谷歌提供的数据管理和可视化服务,让用户能够轻松整合、存储和...

    Revisit to the symmetry relations in diffusely backscattered polarization patterns of turbid media

    As there exists an inconsistency in claiming the symmetrical relations in the 16 Mueller matrix elements used to describe a turbid medium, the author restudies the symmetrical relationships between ...

    meta标签详解

    - **Revisit-After**: 建议搜索引擎重新访问页面的时间间隔。 - 示例:`&lt;meta name="revisit-after" content="7 days"&gt;` - **Author**: 指定页面作者或创作团队的信息。 - 示例:`张三"&gt;` - **Copyright**: 指定...

Global site tag (gtag.js) - Google Analytics