Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -0,0 +1,220 @@
package zebra;
public class LineOfPuzzle implements Cloneable{
private Integer order;
private String nation;
private String color;
private String animal;
private String drink;
private String cigarette;
private LineOfPuzzle rightNeighbor;
private LineOfPuzzle leftNeighbor;
private PuzzleSet<LineOfPuzzle> undefNeighbors;
public LineOfPuzzle (Integer order, String nation, String color,
String animal, String drink, String cigarette){
this.animal=animal;
this.cigarette=cigarette;
this.color=color;
this.drink=drink;
this.nation=nation;
this.order=order;
}
public Integer getOrder() {
return order;
}
public void setOrder(Integer order) {
this.order = order;
}
public String getNation() {
return nation;
}
public void setNation(String nation) {
this.nation = nation;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getAnimal() {
return animal;
}
public void setAnimal(String animal) {
this.animal = animal;
}
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
public String getCigarette() {
return cigarette;
}
public void setCigarette(String cigarette) {
this.cigarette = cigarette;
}
/**
* Overrides object equal method
* @param obj
* @return
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof LineOfPuzzle){
LineOfPuzzle searchLine = (LineOfPuzzle)obj;
return this.getWholeLine().equalsIgnoreCase(searchLine.getWholeLine());
}
else
return false;
}
public int getFactsCount(){
int facts = 0;
facts+=this.getOrder()!=null?1:0;
facts+=this.getNation()!=null?1:0;
facts+=this.getColor()!=null?1:0;
facts+=this.getAnimal()!=null?1:0;
facts+=this.getCigarette()!=null?1:0;
facts+=this.getDrink()!=null?1:0;
return facts;
}
public int getCommonFactsCount(LineOfPuzzle lineOfFacts){
int ordrCmp = (this.order!=null && lineOfFacts.getOrder()!= null &&
this.order.intValue()== lineOfFacts.getOrder().intValue())?1:0;
int natnCmp = (this.nation!=null && lineOfFacts.getNation()!= null &&
this.nation.equalsIgnoreCase(lineOfFacts.getNation()))?1:0;
int colrCmp = (this.color!=null && lineOfFacts.getColor()!= null &&
this.color.equalsIgnoreCase(lineOfFacts.getColor()))?1:0;
int petsCmp = (this.animal!=null && (lineOfFacts.getAnimal()!= null &&
this.animal.equalsIgnoreCase(lineOfFacts.getAnimal())))?1:0;
int cigrCmp = (this.cigarette!=null && lineOfFacts.getCigarette()!= null &&
this.cigarette.equalsIgnoreCase(lineOfFacts.getCigarette()))?1:0;
int drnkCmp = (this.drink!=null && lineOfFacts.getDrink()!= null &&
this.drink.equalsIgnoreCase(lineOfFacts.getDrink()))?1:0;
int result = (ordrCmp + natnCmp + colrCmp + petsCmp + cigrCmp + drnkCmp);
return result;
}
public void addUndefindedNeighbor(LineOfPuzzle newNeighbor){
if (this.undefNeighbors==null)
this.undefNeighbors = new PuzzleSet<>();
this.undefNeighbors.add(newNeighbor);
}
public boolean hasUndefNeighbors(){
return (this.undefNeighbors!=null);
}
public PuzzleSet<LineOfPuzzle> getUndefNeighbors(){
return this.undefNeighbors;
}
public void setLeftNeighbor(LineOfPuzzle leftNeighbor){
this.leftNeighbor = leftNeighbor;
this.leftNeighbor.setOrder(this.order - 1);
}
public void setRightNeighbor(LineOfPuzzle rightNeighbor){
this.rightNeighbor=rightNeighbor;
this.rightNeighbor.setOrder(this.order + 1);
}
public boolean hasLeftNeighbor(){
return (leftNeighbor!=null);
}
public LineOfPuzzle getLeftNeighbor(){
return this.leftNeighbor;
}
public boolean hasNeighbor(int direction){
if (direction < 0)
return (leftNeighbor!=null);
else
return (rightNeighbor!=null);
}
public boolean hasRightNeighbor(){
return (rightNeighbor!=null);
}
public LineOfPuzzle getRightNeighbor(){
return this.rightNeighbor;
}
public LineOfPuzzle getNeighbor(int direction){
if (direction < 0)
return this.leftNeighbor;
else
return this.rightNeighbor;
}
public String getWholeLine() {
String sLine = this.order + " - " +
this.nation + " - " +
this.color + " - " +
this.animal + " - " +
this.drink + " - " +
this.cigarette;
return sLine;
}
@Override
public int hashCode() {
int sLine = (this.order + " - " +
this.nation + " - " +
this.color + " - " +
this.animal + " - " +
this.drink + " - " +
this.cigarette
).hashCode();
return sLine;
}
public void merge(LineOfPuzzle mergedLine){
if (this.order == null) this.order = mergedLine.order;
if (this.nation == null) this.nation = mergedLine.nation;
if (this.color == null) this.color = mergedLine.color;
if (this.animal == null) this.animal = mergedLine.animal;
if (this.drink == null) this.drink = mergedLine.drink;
if (this.cigarette == null) this.cigarette = mergedLine.cigarette;
}
public LineOfPuzzle clone() {
try {
return (LineOfPuzzle) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}

View file

@ -0,0 +1,98 @@
package zebra;
import java.util.Iterator;
import java.util.LinkedHashSet;
public class PuzzleSet<T extends LineOfPuzzle> extends LinkedHashSet{
private T t;
private int countOfOne=0;
private int countOfTwo=0;
private int countOfThree=0;
private int countOfFour=0;
private int countOfFive=0;
PuzzleSet() {
super();
}
public void set(T t) { this.t = t; }
public T get(int index) {
return ((T)this.toArray()[index]);
}
public PuzzleSet<T> getSimilarLines(T searchLine) {
PuzzleSet<T> puzzleSubSet = new PuzzleSet<>();
for (Iterator<T> it = this.iterator(); it.hasNext();) {
T lineOfPuzzle = it.next();
if(lineOfPuzzle.getCommonFactsCount(searchLine) == searchLine.getFactsCount())
puzzleSubSet.add(lineOfPuzzle);
}
if (puzzleSubSet.isEmpty())
return null;
return puzzleSubSet;
}
public boolean contains(T searchLine) {
for (Iterator<T> it = this.iterator(); it.hasNext();) {
T puzzleLine = it.next();
if(puzzleLine.getCommonFactsCount(searchLine) == searchLine.getFactsCount())
return true;
}
return false;
}
public boolean accepts(T searchLine) {
int passed=0;
int notpassed=0;
for (Iterator<T> it = this.iterator(); it.hasNext();) {
T puzzleSetLine = it.next();
int lineFactsCnt = puzzleSetLine.getFactsCount();
int comnFactsCnt = puzzleSetLine.getCommonFactsCount(searchLine);
if( lineFactsCnt != comnFactsCnt && lineFactsCnt !=0 && comnFactsCnt !=0){
notpassed++;
}
if( lineFactsCnt == comnFactsCnt)
passed++;
}
return (passed >= 0 && notpassed == 0);
}
public void riseLineCountFlags(int lineOrderId){
switch (lineOrderId){
case 1: countOfOne++; break;
case 2: countOfTwo++; break;
case 3: countOfThree++; break;
case 4: countOfFour++; break;
case 5: countOfFive++; break;
default:;
}
}
public void clearLineCountFlags(){
countOfOne=0;
countOfTwo=0;
countOfThree=0;
countOfFour=0;
countOfFive=0;
}
public int getLineCountByOrderId(int lineOrderId){
switch (lineOrderId){
case 1: return countOfOne;
case 2: return countOfTwo;
case 3: return countOfThree;
case 4: return countOfFour;
case 5: return countOfFive;
default:return -1;
}
}
}

View file

@ -0,0 +1,317 @@
package zebra;
import java.util.ArrayList;
import java.util.Iterator;
public class Puzzle {
private static final ArrayList<Integer> orders = new ArrayList<>(5);
private static final ArrayList<String> nations = new ArrayList<>(5);
private static final ArrayList<String> animals = new ArrayList<>(5);
private static final ArrayList<String> drinks = new ArrayList<>(5);
private static final ArrayList<String> cigarettes = new ArrayList<>(5);
private static final ArrayList<String> colors = new ArrayList<>(5);
private static PuzzleSet<LineOfPuzzle> puzzleTable;
static
{
// House orders
orders.add(1);
orders.add(2);
orders.add(3);
orders.add(4);
orders.add(5);
// Man nations
nations.add("English");
nations.add("Danish");
nations.add("German");
nations.add("Swedesh");
nations.add("Norwegian");
//Animals
animals.add("Zebra");
animals.add("Horse");
animals.add("Birds");
animals.add("Dog");
animals.add("Cats");
//Drinks
drinks.add("Coffee");
drinks.add("Tea");
drinks.add("Beer");
drinks.add("Water");
drinks.add("Milk");
//Smokes
cigarettes.add("Pall Mall");
cigarettes.add("Blend");
cigarettes.add("Blue Master");
cigarettes.add("Prince");
cigarettes.add("Dunhill");
//Colors
colors.add("Red");
colors.add("Green");
colors.add("White");
colors.add("Blue");
colors.add("Yellow");
}
public static void main (String[] args){
boolean validLine=true;
puzzleTable = new PuzzleSet<>();
//Rules
LineOfPuzzle rule2 = new LineOfPuzzle(null, "English", "Red", null, null, null);
LineOfPuzzle rule3 = new LineOfPuzzle(null, "Swedesh", null, "Dog", null, null);
LineOfPuzzle rule4 = new LineOfPuzzle(null, "Danish", null, null, "Tea", null);
LineOfPuzzle rule6 = new LineOfPuzzle(null, null, "Green", null, "Coffee", null);
LineOfPuzzle rule7 = new LineOfPuzzle(null, null, null, "Birds", null, "Pall Mall");
LineOfPuzzle rule8 = new LineOfPuzzle(null, null, "Yellow", null, null, "Dunhill");
LineOfPuzzle rule9 = new LineOfPuzzle(3, null, null, null, "Milk", null);
LineOfPuzzle rule10 = new LineOfPuzzle(1, "Norwegian", null, null, null, null);
LineOfPuzzle rule13 = new LineOfPuzzle(null, null, null, null, "Beer", "Blue Master");
LineOfPuzzle rule14 = new LineOfPuzzle(null, "German", null, null, null, "Prince");
LineOfPuzzle rule15 = new LineOfPuzzle(2, null, "Blue", null, null, null);
PuzzleSet<LineOfPuzzle> ruleSet = new PuzzleSet<>();
ruleSet.add(rule2);
ruleSet.add(rule3);
ruleSet.add(rule4);
ruleSet.add(rule6);
ruleSet.add(rule7);
ruleSet.add(rule8);
ruleSet.add(rule9);
ruleSet.add(rule10);
ruleSet.add(rule13);
ruleSet.add(rule14);
ruleSet.add(rule15);
//Creating all possible combination of a puzzle line.
//The maximum number of lines is 5^^6 (15625).
//Each combination line is checked against a set of knowing facts, thus
//only a small number of line result at the end.
for (Integer orderId : Puzzle.orders) {
for (String nation : Puzzle.nations) {
for (String color : Puzzle.colors) {
for (String animal : Puzzle.animals) {
for (String drink : Puzzle.drinks) {
for (String cigarette : Puzzle.cigarettes) {
LineOfPuzzle pzlLine = new LineOfPuzzle(orderId,
nation,
color,
animal,
drink,
cigarette);
// Checking against a set of knowing facts
if (ruleSet.accepts(pzlLine)){
// Adding rules of neighbors
if (cigarette.equalsIgnoreCase("Blend")
&& (animal.equalsIgnoreCase("Cats")
|| drink.equalsIgnoreCase("Water")))
validLine = false;
if (cigarette.equalsIgnoreCase("Dunhill")
&& animal.equalsIgnoreCase("Horse"))
validLine = false;
if (validLine){
puzzleTable.add(pzlLine);
//set neighbors constraints
if (color.equalsIgnoreCase("Green")){
pzlLine.setRightNeighbor(new LineOfPuzzle(null, null, "White", null, null, null));
}
if (color.equalsIgnoreCase("White")){
pzlLine.setLeftNeighbor(new LineOfPuzzle(null, null, "Green", null, null, null));
}
//
if (animal.equalsIgnoreCase("Cats")
&& !cigarette.equalsIgnoreCase("Blend") ){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, null, "Blend"));
}
if (cigarette.equalsIgnoreCase("Blend")
&& !animal.equalsIgnoreCase("Cats")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, "Cats", null, null));
}
//
if (drink.equalsIgnoreCase("Water")
&& !animal.equalsIgnoreCase("Cats")
&& !cigarette.equalsIgnoreCase("Blend")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, null, "Blend"));
}
if (cigarette.equalsIgnoreCase("Blend")
&& !drink.equalsIgnoreCase("Water")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, "Water", null));
}
//
if (animal.equalsIgnoreCase("Horse")
&& !cigarette.equalsIgnoreCase("Dunhill")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, null, "Dunhill"));
}
if (cigarette.equalsIgnoreCase("Dunhill")
&& !animal.equalsIgnoreCase("Horse")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, "Horse", null, null));
}
}
validLine = true;
}
} //cigarette end
} //drinks end
} //animal end
} //color end
} //nations end
} //order end
System.out.println("After general rule set validation, remains "+
puzzleTable.size() + " lines.");
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();){
validLine=true;
LineOfPuzzle lineOfPuzzle = it.next();
if (lineOfPuzzle.hasLeftNeighbor()){
LineOfPuzzle neighbor = lineOfPuzzle.getLeftNeighbor();
if (neighbor.getOrder()<1 || neighbor.getOrder()>5){
validLine=false;
it.remove();
}
}
if (validLine && lineOfPuzzle.hasRightNeighbor()){
LineOfPuzzle neighbor = lineOfPuzzle.getRightNeighbor();
if (neighbor.getOrder()<1 || neighbor.getOrder()>5){
it.remove();
}
}
}
System.out.println("After removing out of bound neighbors, remains " +
puzzleTable.size() + " lines.");
//Setting left and right neighbors
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();) {
LineOfPuzzle puzzleLine = it.next();
if (puzzleLine.hasUndefNeighbors()){
for (Iterator<LineOfPuzzle> it1 = puzzleLine.getUndefNeighbors().iterator(); it1.hasNext();) {
LineOfPuzzle leftNeighbor = it1.next();
LineOfPuzzle rightNeighbor = leftNeighbor.clone();
//make it left neighbor
leftNeighbor.setOrder(puzzleLine.getOrder()-1);
if (puzzleTable.contains(leftNeighbor)){
if (puzzleLine.hasLeftNeighbor())
puzzleLine.getLeftNeighbor().merge(leftNeighbor);
else
puzzleLine.setLeftNeighbor(leftNeighbor);
}
rightNeighbor.setOrder(puzzleLine.getOrder()+1);
if (puzzleTable.contains(rightNeighbor)){
if (puzzleLine.hasRightNeighbor())
puzzleLine.getRightNeighbor().merge(rightNeighbor);
else
puzzleLine.setRightNeighbor(rightNeighbor);
}
}
}
}
int iteration=1;
int lastSize=0;
//Recursively validate against neighbor rules
while (puzzleTable.size()>5 && lastSize != puzzleTable.size()) {
lastSize = puzzleTable.size();
puzzleTable.clearLineCountFlags();
recursiveSearch(null, puzzleTable, -1);
ruleSet.clear();
// Assuming we'll get at leas one valid line each iteration, we create
// a set of new rules with lines which have no more then one instance of same OrderId.
for (int i = 1; i < 6; i++) {
if (puzzleTable.getLineCountByOrderId(i)==1)
ruleSet.addAll(puzzleTable.getSimilarLines(new LineOfPuzzle(i, null, null, null, null, null)));
}
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();) {
LineOfPuzzle puzzleLine = it.next();
if (!ruleSet.accepts(puzzleLine))
it.remove();
}
//
System.out.println("After " + iteration + " recursive iteration, remains "
+ puzzleTable.size() + " lines");
iteration+=1;
}
// Print the results
System.out.println("-------------------------------------------");
if (puzzleTable.size()==5){
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();) {
LineOfPuzzle puzzleLine = it.next();
System.out.println(puzzleLine.getWholeLine());
}
}else
System.out.println("Sorry, solution not found!");
}
// Recursively checks the input set to ensure each line has right neighbor.
// Neighbors can be of three type, left, right or undefined.
// Direction: -1 left, 0 undefined, 1 right
private static boolean recursiveSearch(LineOfPuzzle pzzlNodeLine,
PuzzleSet puzzleSet, int direction){
boolean validLeaf = false;
boolean hasNeighbor = false;
PuzzleSet<LineOfPuzzle> puzzleSubSet = null;
for (Iterator<LineOfPuzzle> it = puzzleSet.iterator(); it.hasNext();) {
LineOfPuzzle pzzlLeafLine = it.next();
validLeaf = false;
hasNeighbor = pzzlLeafLine.hasNeighbor(direction);
if (hasNeighbor){
puzzleSubSet = puzzleTable.getSimilarLines(pzzlLeafLine.getNeighbor(direction));
if (puzzleSubSet != null){
if (pzzlNodeLine !=null)
validLeaf = puzzleSubSet.contains(pzzlNodeLine);
else
validLeaf = recursiveSearch(pzzlLeafLine, puzzleSubSet, -1*direction);
}
else
validLeaf = false;
}
if (!validLeaf && pzzlLeafLine.hasNeighbor(-1*direction)){
hasNeighbor = true;
if (hasNeighbor){
puzzleSubSet = puzzleTable.getSimilarLines(pzzlLeafLine.getNeighbor(-1*direction));
if (puzzleSubSet != null){
if (pzzlNodeLine !=null)
validLeaf = puzzleSubSet.contains(pzzlNodeLine);
else
validLeaf = recursiveSearch(pzzlLeafLine, puzzleSubSet, direction);
}
else
validLeaf = false;
}
}
if (pzzlNodeLine != null && validLeaf)
return validLeaf;
if (pzzlNodeLine == null && hasNeighbor && !validLeaf){
it.remove();
}
if (pzzlNodeLine == null){
if (hasNeighbor && validLeaf){
puzzleSet.riseLineCountFlags(pzzlLeafLine.getOrder());
}
if (!hasNeighbor){
puzzleSet.riseLineCountFlags(pzzlLeafLine.getOrder());
}
}
}
return validLeaf;
}
}