×

Zebra Puzzle Problem in Java

Complex puzzles like the zebra puzzle demand a lot of work and mental training to complete. Because it was created by renowned German scientist Albert Einstein, it is also sometimes referred to as Einstein's Puzzle or Einstein's Riddle.

The challenge is frequently employed in testing computer algorithms for resolving constraint satisfaction issues (CSP). The majority of AI-related issues may be described as constraint satisfaction issues (CSP).

Problem with Constraint Satisfaction (Constraint Satisfaction Problem CSP)

The CSP issue typically consists of a set of constraints, some discrete collection of variables, each with a defined range of values. Each constraint limits the simultaneous values that these variables can take and is specified over a fraction of the originating set of variables. In certain issues, the objective is to locate all such assignments. The challenge is to determine the allocation of such a number for every variable that ensures that the assignments fulfil all the criteria.

As a result, we may characterize CSP as a collection of objects whose current state must adhere to a variety of restrictions or limits.

The N-queen’s problem, the graph colouring problem, the crossword puzzle, etc. are a few instances of the problem that are frequently used.

General Techniques for CSP Solutions

The generate-and-test technique is the standard strategy for solving a CSP. Iteratively created and then examined to see if each potential combination of variable values fulfils all the restrictions. The answer is the initial assignment that complies with every restriction. The quantity of assignments that must be taken into account in the worst-case scenario, or while trying to discover every possible solution for a CSP, is similar to the size of both the Denotes the set of each of the variable domains. As a result, this method's temporal complexity grows as the number evaluated variables. This approach performs terribly in empirical studies.

Randomized generate-and-test algorithms, which choose the assigned tasks to test at random in accordance with some biassed distribution (for example, the distribution might be biassed by the most recent tests, as in randomised hill-climbing), can occasionally perform incredibly well, but regrettably lose systematicity. That is, given that they do not definitely test all assignments, these randomised approaches cannot establish that there is no solution.

The CSP may be solved using the following three methods:

  • The Tree search
  • Propagation of constraints
  • Combining constraints propagation and backtracking search

Zebra Puzzle

The puzzle comes in a variety of forms. In other puzzles, other colours, countries, cigarette brands, beverages, and pets are swapped for those in the Life International problem. But the reasoning won't be altered. The variation shown below was printed in Life International.

  1. Five dwellings are present.
  2. The red home is where the Englishman resides.
  3. He owns a dog, the Swede.
  4. Dane people sip tea.
  5. Directly towards the left of such white home is the green house.
  6. In the greenhouse, people sip coffee.
  7. Birds are owned by the Pall Mall smoker.
  8. They smoke Dunhill in the yellow home.
  9. They sip milk inside the middle home.
  10. In the first home resides the Norwegian.
  11. The neighbouring home to the cat-owning home is where the Blend-smoking man resides.
  12. They smoke Dunhill at a home next to the one where they keep a horse.
  13. Beer is consumed by the Blue Master smoker.
  14. Prince is smoked by the German.
  15. The blue home is near to the Norwegian's residence.
  16. In a home close to the one where they smoke Blend, they sip water.

Each of the five residences is painted a different colour, and the occupants come from various national backgrounds, own various animals, indulge in various drinks, and smoke various kinds of American cigarettes. One more thing: Left in statement 5 refers to your right.

The zebra's ownership is in dispute. Also, include a list of each house's answer. Indicate the uniqueness of the answer, if desired.

The Zebra Puzzle's Answer

Backtracking, minimal leftover numbers , advance stacking , minimal conflicts, etc. are a few of the methods that have been proposed in the last several years to solve this issue. However, we'll utilise the more common generate-and-test methodology in this part.

Let's list the characteristics of the problem based on the aforementioned 16 limitations (statements).

Colour: Reddish, Greenish, Ivory, Yellowish, Blueish

Nationality: Englishmenn, Spanish, Ukrainin, Norweygin, Japanese

Drink: Caffain, Bru, Doodh, lemon juice, Water

Smoke: Gold flake, Black light, Tipper, Beedi, Parliamentary

Pet: Cat, Rabbit, Ware wolf, Donkey, Giraffe

Mansion        1         2          3         4        5
Colouryellowishblueishreddishivorygreenish
NationalityNorweyginUkrainianEnglishmenSpanishJapanese
DrinkWaterBruDoodhOrange juiceCaffain
SmokeBlack lightTipperGold flakeBeediParliamentary
PetWare wolfDonkeyRabbitCatGiraffe

The four user-defined classes listed below are included in the following Java program:

  • The Zebra Group
  • The class of PossibilityLine
  • The Class of PossibleLine
  • Solution Class

Let the name of the file is ZebraDemo.java

import java.util.Arrays;  
import java.util.Iterator;  
import java.util.LinkedHashSet;  
import java.util.Objects;  
import java.util.Set;  
public class ZebraDemo {   
private static final int[] order = {1, 2, 3, 4, 5};  
private static final String[] nation = {"ENglishmen", "Danishian", "Germans", "Swdesian", "Norwegin"};  
private static final String[] animals = {"Giraffe", "Donkey", "Bird", "Cat", "Kittens"};  
private static final String[] drinks = {"Caffain", "Tea", "Budwiser", "Water", "Doodh"};  
private static final String[] cigarettes = {"Roman mall", "Blendon", "Antiquity", "Pierce", "Kesari"};  
private static final String[] colours = {"Reddish", "Greenish", "Whitish", "Blueish", "Yellowish"};  
static class Solver {  
    private final PossibleLine puzzledesk = new PossibleLine();  
    void solve() {  
        PossibleLine conditions = new PossibleLine();  
        conditions.add(new PossibleLine(null, "ENglishmen", "Reddish", null, null, null));  
        conditions.add(new PossibleLine(null, "Swdesian", null, "Cat", null, null));  
        conditions.add(new PossibleLine(null, "Danishian", null, null, "Tea", null));  
        conditions.add(new PossibleLine(null, null, "Greenish", null, "Caffain", null));  
        conditions.add(new PossibleLine(null, null, null, "Bird", null, "Roman mall"));  
        conditions.add(new PossibleLine(null, null, "Yellowish", null, null, "Kesari"));  
        conditions.add(new PossibleLine(3, null, null, null, "Doodh", null));  
        conditions.add(new PossibleLine(1, "Norwegin", null, null, null, null));  
        conditions.add(new PossibleLine(null, null, null, null, "Budwiser", "Antiquity"));  
        conditions.add(new PossibleLine(null, "Germans", null, null, null, "Pierce"));  
        conditions.add(new PossibleLine(2, null, "Blueish", null, null, null));  
        // Making every puzzle line combination imaginable.
        // There can be a maximum of 5^^6 lines (15625).
       // Only a few combination lines are produced at the end 
      // since each combined lines is tested against such a set of known facts.
        for (Integers orderUid : Giraffe.order) {  
            for (String nation : Giraffe.nation) {  
                for (String colour : Giraffe.colours) {  
                    for (String animal : Giraffe.animals) {  
                        for (String drink : Giraffe.drinks) {  
                            for (String cigarette : Giraffe.cigarettes) {  
                                addthepossibleneighbor(conditions, orderUid, nation, colour, animal, drink, cigarette);  
                            }  
                        }  
                    }  
                }  
            }  
        }  
        System.out.println("following broad rule set validation, there are still" +  
                puzzledesk.size() + " lines.");   
        for (Iterator<PossibleLine> iti = puzzledesk.iterator(); iti.hasNext(); ) {  
            boolean validLine = true;  
            PossibleLine possibleLine = iti.next();  
            if (possibleLine.leftneighbors != null) {  
                PossibleLine neighbors = possibleLine.leftneighbors;  
                if (neighbors.order < 1 || neighbors.order > 5) {  
                    validLine = false;  
                    iti.remove();  
                }  
            }  
            if (validLine && possibleLine.rightneighbors != null) {  
                PossibleLine neighbors = possibleLine.rightneighbors;  
                if (neighbors.order < 1 || neighbors.order > 5) {  
                    iti.remove();  
                }  
            }  
        }  
        System.out.println("Out-of-bounds neighbours have been removed, leaving" +  
                puzzledesk.size() + " lines.");   
        //establishing left- and right-side neighbours 
        for (PossibleLine puzzleLine : puzzledesk) {  
            for (PossibleLine leftneighbors : puzzleLine.neighbors) {  
                PossibleLine rightneighbors = leftneighbors.copy();  
                //make iti as the leftneighbours
                leftneighbors.order = puzzleLine.order - 1;  
                if (puzzledesk.consists(leftneighbors)) {  
                    if (puzzleLine.leftneighbors != null)  
                        puzzleLine.leftneighbors.merge(leftneighbors);  
                    else  
                        puzzleLine.setLeftNeighbor(leftneighbors);  
                }  
                rightneighbors.order = puzzleLine.order + 1;  
                if (puzzledesk.consists(rightneighbors)) {  
                    if (puzzleLine.rightneighbors != null)  
                        puzzleLine.rightneighbors.merge(rightneighbors);  
                    else  
                        puzzleLine.setasRihtneighbor(rightneighbors);  
                }  
            }  
        }  
        int iter = 1;  
        int finalsize = 0;  
        //Recursively validate against neighbors rules  
        while (puzzledesk.size() > 5 && finalsize != puzzledesk.size()) {  
            finalsize = puzzledesk.size();  
            puzzledesk.clearlineflag();  
            recursearch(null, puzzledesk, -1);  
            conditions.clear();  
           // We establish a new set of criteria with lines that contain no more than one occurrence of the same,
// assuming we'll obtain at least one valid line with each iteration. OrderUId.  
            for (int s = 1; s < 6; s++) {  
                if (puzzledesk.getLineCountByOrderId(s) == 1)  
                    conditions.addAll(puzzledesk.getSimilarLines(new PossibleLine(s, null, null, null, null,  
                            null)));  
            }  
            puzzledesk.takeoffif(puzzleLine -> !conditions.accepts(puzzleLine));  
            System.out.println("Later " + iter + " recursive iter, remains "  
                    + puzzledesk.size() + " lines");  
            iter++;  
        }  
        // The results is been printed here
        System.out.println("…………………………………………………………………….");  
        if (puzzledesk.size() == 5) {  
            for (PossibleLine puzzleLine : puzzledesk) {  
                System.out.println(puzzleLine.getWholeLine());  
            }  
        } else  
            System.out.println("Sorry to say that, the solution has not found!");  
    }  
    private void addthepossibleneighbor(  
            PossibleLine conditions, Integers orderUid, String nation,  
            String colour, String animals, String drink, String cigarette) {  
        boolean validLine = true;  
        PossibleLine pzlLine = new PossibleLine(orderUid,  
                nations,  
                colours,  
                animals,  
                drinks,  
                cigarette);  
        // comparing a collection of knowledgeable information
        if (conditions.accepts(pzlLine)) { 
                 // Extending the neighbourhood rules
if (cigarettes.equals("Black light")  
&& (animals.equals("Dog") || drinks.equals("Millis")))  
validLines = false;   
if (cigarettes.equals("Tipper")  
&& animals.equals("Donkey"))  
validLines = false;  
if (validLines) {  
puzzleDesk.add(pzlLines);  
//set neighbors constraints  
if (colours.equals("Greenish")) {  
pzlLines.setAsRightNeighbor(  
        new PossibleLines(null, null, "Whitish", null, null, null));  
}  
if (colours.equals("Whitish")) {  
pzlLines.setAsLeftneighbor(  
        new PossibleLines(null, null, "Greenish", null, null, null));  
}  
//  
if (animals.equals("Dog") && !cigarettes.equals("Black light")) {  
pzlLines.neighbors.add(new PossibleLines(null, null, null, null, null,  
        "Black light"));  
}  
if (cigarettes.equals("Black light") && !animals.equals("Dog")) {  
pzlLines.neighbors.add(new PossibleLines(null, null, null, "Dog", null  
        , null));  
}  
//  
if (drinks.equals("Millis")  
    && !animals.equals("Dog")  
    && !cigarettes.equals("Black light")) {  
pzlLines.neighbors.add(new PossibleLines(null, null, null, null, null,  
        "Black light"));  
}  


if (cigarettes.equals("Black light") && !drinks.equals("Millis")) {  
pzlLines.neighbors.add(new PossibleLines(null, null, null, null, "Millis"  
        , null));  
}  
//  
if (animals.equals("Donkey") && !cigarettes.equals("Tipper")) {  
pzlLines.neighbors.add(new PossibleLines(null, null, null, null, null,  
        "Tipper"));  
}  
if (cigarettes.equals("Tipper") && !animals.equals("Donkey")) {  
pzlLines.neighbors.add(new PossibleLines(null, null, null, "Donkey",  
        null, null));  
}  
}  
}  
}  


// The input set is checked recursively to make absolutely sure every line have the appropriate neighbours.
// There are three types of neighbours: left, right, and undefined.
// Movement: 1 right, 0 undef, and -1 left
private boolean recursearch(PossibleLines pzlNodeLines,  
                PossibleLines possibleLines, int dirct) {  
boolean correctLeaf = false;  
boolean haveNeighbors;  
PossibleLines puzlSubseq;  


for (Iter<PossibleLines> iti = possibleLines.iter(); iti.hasNext(); ) {  
PossibleLines pzzlLeafLine = iti.next();  
correctLeaf = false;  


haveNeighbors = pzzlLeafLine.haveNeighbors(dirct);  


if (haveNeighbors) {  
puzlSubseq = puzzleDesk.getSameLines(pzzlLeafLine.gettheneighbors(dirct));  
if (puzlSubseq != null) {  
if (pzlNodeLines != null)  
    correctLeaf = puzlSubseq.have(pzlNodeLines);  
else  
    correctLeaf = recursearch(pzzlLeafLine, puzlSubseq, -1 * dirct);  
}  
}  


if (!correctLeaf && pzzlLeafLine.haveNeighbors(-1 * dirct)) {  
haveNeighbors = true;  
puzlSubseq = puzzleDesk.getSameLines(pzzlLeafLine.gettheneighbors(-1 * dirct));  
if (puzlSubseq != null) {  
if (pzlNodeLines != null)  
    correctLeaf = puzlSubseq.have(pzlNodeLines);  
else  
    correctLeaf = recursearch(pzzlLeafLine, puzlSubseq, dirct);  
}  
}  


if (pzlNodeLines != null && correctLeaf)  
return true;  


if (pzlNodeLines == null && haveNeighbors && !correctLeaf) {  
iti.remove();  
}  


if (pzlNodeLines == null) {  
if (haveNeighbors && correctLeaf) {  
possibleLines.riseLineCountFlags(pzzlLeafLine.orders);  
}  
if (!haveNeighbors) {  
possibleLines.riseLineCountFlags(pzzlLeafLine.orders);  
}  
}  
}  
return correctLeaf;  
}  
}  


public static void main(String[] args) {  


Salaar salaar = new Salaar();  
salaar.sol();  
}  


static class PossibleLines extends LinkingHashSet<PossibleLines> {  


private final int[] count = new int[5];  


public PossibleLines get(int index) {  
return ((PossibleLines) toArray()[index]);  
}  


public PossibleLines getSameLines(PossibleLines findLine) {  
PossibleLines puzlSubseq = new PossibleLines();  
for (PossibleLines possibleLine : this) {  
if (possibleLine.getComnFactercount(findLine) == findLine.getFactdcount())  
puzlSubseq.add(possibleLine);  
}  
if (puzlSubseq.isEmpty())  
return null;  


return puzlSubseq;  
}  


public boolean have(PossibleLines findLine) {  
for (PossibleLines puzzleLine : this) {  
if (puzzleLine.getComnFactercount(findLine) == findLine.getFactdcount())  
return true;  
}  
return false;  
}  


public boolean accept(PossibleLines findLine) {  
int pass = 0;  
int notpass = 0;  


for (PossibleLines puzzleSetLines : this) {  
int lineFactsCnt = puzzleSetLines.getFactdcount();  
int comnFactsCnt = puzzleSetLines.getComnFactercount(findLine);  


if (lineFactsCnt != comnFactsCnt && lineFactsCnt != 0 && comnFactsCnt != 0) {  
notpass++;  
}  


if (lineFactsCnt == comnFactsCnt)  
pass++;  
}  
return pass >= 0 && notpass == 0;  
}  


public void riseLineCountFlags(int LineorderUid) {  
count[LineorderUid - 1]++;  
}  


public void clearLineCountFlags() {  
Arr.fill(count, 0);  
}  
public int getThelinecountorderuid(int LineorderUid) {  
return count[LineorderUid - 1];  
}  
}  
static class PossibleLines {  
Integ orders;  
String nations;  
String colours;  
String animals;  
String drinks;  
String cigarettes;  
PossibleLines rightneighbors;  
PossibleLines leftneighbors;  
Set<PossibleLines> neighbors = new LinkingHashSet<>();  
public PossibleLines(Integ orders, String nations, String colours,  
    String animals, String drinks, String cigarettes) {  
this.animals = animals;  
this.cigarettes = cigarettes;  
this.colours = colours;  
this.drinks = drinks;  
this.nations = nations;  
this.orders = orders;  
}  


@Override  
public boolean equals(Object sr) {  
return sr instanceofthe PossibleLines  
&& getThewholeLines().equals(((PossibleLines) sr).getThewholeLines());  
}  


public int getFactdcount() {  
int data = 0;  
data += orders != null ? 1 : 0;  
data += nations != null ? 1 : 0;  
data += colours != null ? 1 : 0;  
data += animals != null ? 1 : 0;  
data += cigarettes != null ? 1 : 0;  
data += drinks != null ? 1 : 0;  
return data;  
}  


private static int similar(Object a, Object b) {  
return a != null && Objects.equals(a, b) ? 1 : 0;  
}  


public int getComnFactercount(PossibleLines data) {  
return similar(orders, data.orders)  
+ similar(nations, data.nations)  
+ similar(colours, data.colours)  
+ similar(animals, data.animals)  
+ similar(cigarettes, data.cigarettes)  
+ similar(drinks, data.drinks);  
}  


public void setAsLeftneighbor(PossibleLines leftneighbors) {  
this.leftneighbors = leftneighbors;  
this.leftneighbors.orders = orders - 1;  
}  


public void setAsRightNeighbor(PossibleLines rightneighbors) {  
this.rightneighbors = rightneighbors;  
this.rightneighbors.orders = orders + 1;  
}  


public boolean haveNeighbors(int dirct) {  
return gettheneighbors(dirct) != null;  
}  


public PossibleLines gettheneighbors(int dirct) {  
if (dirct < 0)  
return leftneighbors;  
else  
return rightneighbors;  
}  


public String getThewholeLines() {  
return orders + " - " +  
nations + " - " +  
colours + " - " +  
animals + " - " +  
drinks + " - " +  
cigarettes;  
}  


@Override  
public int hashCode() {  
return Objects.hash(orders, nations, colours, animals, drinks, cigarettes);  
}  


public void merge(PossibleLines mergingthelines) {  
if (orders == null) orders = mergingthelines.orders;  
if (nations == null) nations = mergingthelines.nations;  
if (colours == null) colours = mergingthelines.colours;  
if (animals == null) animals = mergingthelines.animals;  
if (drinks == null) drinks = mergingthelines.drinks;  
if (cigarettes == null) cigarettes = mergingthelines.cigarettes;  
}  


public PossibleLines copy() {  
PossibleLines copy = new PossibleLines(orders, nations, colours, animals, drinks, cigarettes);  
copy.leftneighbors = leftneighbors;  
copy.rightneighbors = rightneighbors;  
copy.neighbors = neighbors; // It is the copy of shallow  
return copy;  
}  
}                         

Output:

following broad rule set validation, there are still 60 lines.
Out-of-bounds neighbours have been removed, same 52 lines.
Later 1 recur iter, same 17 lines
Later 2 recur iter, same 6 lines
Later 3 recur iter, same 5 lines
…………………………………………………………………….
1 - Norwegian - Yellowish - Dogs - Water - 
2 - Danish - Blueish - Donkey - bru – Black Light
3 - Englishmen - Reddish - Flies - Doodh – Erra pan
4 - Germanish - Green - Zebra - Coffee - Prince
5 - Swedish - Whitish - Cat - Deer - Antiquity

Related Topics

Method Overloading In Java

If the same class consists of different methods with the same name and the methods can vary by different number of parameters then it is known as Method Overloading. Method...

2 minutes read.

What is advance Java?

The definition of advance inside the dictionary refers to a forward motion, development, or progress, and the definition of enhancing is something that improves things. To become experts in that...

3 minutes read.

How to encrypt password in Java

Every software program needs a username and password to identify a legitimate user. A username can be any number of things, including an email address or a string of characters....

6 minutes read.

What is String in Java?

What is String in Java? Strings are a collection of characters that are commonly used in Java programming. Strings are regarded as objects in the Java programming language. “String” is a Java...

4 minutes read.

All the important string methods in Java

What is a String? Strings are a bundle of different characters that are normally used in Java programming language. Strings are regarded as objects in the Java programming language. “String” is a...

4 minutes read.

Java Integer compareUnsigned() method

The compareUnsigned() method of Integer class compares two int objects numerically by treating the values as unsigned. Syntax public static int compareUnsigned(int x , int y) Parameters The parameters ‘x’ and ‘y’ represent the...

1 minute read.

Check whether Java is installed or not

As we know that there are various operating systems, to check whether Java is installed or not in Windows and Mac we use the following ways.           Windows Operating System: There are several...

2 minutes read.

Java String copyValueOf() method

copyValueOf() method returns a String that holds the character sequence of the character array. Syntax: copyValueOf(char[] data) Parameters: data : the character array i.e. String Returns: It returns a String that contains the characters of the...

2 minutes read.

Java Future Example

Future is an interface in the Java language that is a part of  java.util.concurrent package. It serves as a symbol for the output of an asynchronous computation. The interface offers ways to determine whether a computation has finished,  wait for it to finish, and receive its result. Once the task or calculation is finished, it cannot be undone. A Future interface offers ways to determine whether the computation is finished, to wait for it to finish, and to receive the computation's results. When the computation...

3 minutes read.

Getter and Setter Method in Java Example

In Java programming, getter and setter methods are often employed. The values of class fields can be accessed and changed using Java's getter and setter methods. A private access specifier...

6 minutes read.

How to Convert Octal to Decimal in Java

How to Convert Octal to Decimal in Java There are two methods to convert Octal to Decimal: Using parseInt() method Using user-defined logic Using Integer.parseInt() method The Integer.parseInt() method is a static method...

2 minutes read.

Java Math floorMod() Method

The floorMod() method of Math class returns the floor modulus of the specified arguments. It firstly divides the dividend and divisor and then returns an integer that is equal to...

1 minute read.

Abstract Class Program in Java

Abstract Class Program in Java Abstraction is a technique by which a developer hides the implementation details from the user and shows only the functionality.It is not only confined to the...

6 minutes read.

Swastika Pattern in Java

This part teaches us how to create the Swastika Pattern in Java utilizing user-defined columns and rows as well as stars or other special characters.A Java pattern application that is...

2 minutes read.

Check if the given array is mirror inverse in Java

The primary objective is to check whether the given array is mirror inverse or not. The values and position of the specified array are switched, and a duplicate array is created....

3 minutes read.

Sleeping Barber Problem in Java

The barbershop in this issue has one barber, one barber chair, and N chairs for customers in the waiting area. We may demonstrate the issue by keeping with the original...

6 minutes read.

Java Vs C++

Java Vs C++ Java and C++ both are Object Oriented Programming languages. Both languages are popular for competitive programming. C++ is used by many coders who have just started learning programming...

4 minutes read.

Java Boolean toValue() Method

The valueOf() method of Java Boolean class returns a Boolean object representing the given Boolean or String value. It returns true, if the specified Boolean or string object is true...

2 minutes read.

Program to check whether a given character is present in a string or not

In this article, you will understand the logic to find out whether the given character is present in the string or not and find out the position of the specified...

3 minutes read.

What is string in Java why it's immutable

String in Java Strings are a series of characters commonly used in Java language, which are considered objects in the Java. To create and manipulate strings, java will provide the String...

4 minutes read.