Just another update
This commit is contained in:
parent
a25938f123
commit
00a190b0a6
6591 changed files with 94363 additions and 23227 deletions
|
|
@ -1,4 +1,6 @@
|
|||
The [[wp:Zebra puzzle|Zebra puzzle]], a.k.a. Einstein's Riddle, is a logic puzzle which is to be solved programmatically. It has several variants, one of them this:
|
||||
The [[wp:Zebra puzzle|Zebra puzzle]], a.k.a. Einstein's Riddle,
|
||||
is a logic puzzle which is to be solved programmatically. <br>
|
||||
It has several variants, one of them this:
|
||||
|
||||
#There are five houses.
|
||||
#The English man lives in the red house.
|
||||
|
|
@ -19,6 +21,7 @@ The [[wp:Zebra puzzle|Zebra puzzle]], a.k.a. Einstein's Riddle, is a logic puzzl
|
|||
|
||||
The question is, who owns the zebra?
|
||||
|
||||
Additionally, list the solution for all the houses. Optionally, show the solution is unique.
|
||||
Additionally, list the solution for all the houses.
|
||||
Optionally, show the solution is unique.
|
||||
|
||||
cf. [[Dinesman's multiple-dwelling problem]]
|
||||
cf. [[Dinesman's multiple-dwelling problem]], [[Twelve statements]]
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
---
|
||||
note: Logic puzzles
|
||||
category:
|
||||
- Constraint Handling Rules
|
||||
note: Puzzles
|
||||
|
|
|
|||
83
Task/Zebra-puzzle/Bracmat/zebra-puzzle.bracmat
Normal file
83
Task/Zebra-puzzle/Bracmat/zebra-puzzle.bracmat
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
( (English Swede Dane Norwegian German,)
|
||||
(red green white yellow blue,(red.English.))
|
||||
(dog birds cats horse zebra,(dog.?.Swede.))
|
||||
( tea coffee milk beer water
|
||||
, (tea.?.?.Dane.) (coffee.?.green.?.)
|
||||
)
|
||||
( "Pall Mall" Dunhill Blend "Blue Master" Prince
|
||||
, ("Blue Master".beer.?.?.?.)
|
||||
("Pall Mall".?.birds.?.?.)
|
||||
(Dunhill.?.?.yellow.?.)
|
||||
(Prince.?.?.?.German.)
|
||||
)
|
||||
( 1 2 3 4 5
|
||||
, (3.?.milk.?.?.?.) (1.?.?.?.?.Norwegian.)
|
||||
)
|
||||
: ?properties
|
||||
& ( relations
|
||||
= next leftOf
|
||||
. ( next
|
||||
= a b A B
|
||||
. !arg:(?S,?A,?B)
|
||||
& !S:? (?a.!A) ?:? (?b.!B) ?
|
||||
& (!a+1:!b|!b+1:!a)
|
||||
)
|
||||
& ( leftOf
|
||||
= a b A B
|
||||
. !arg:(?S,?A,?B)
|
||||
& !S:? (?a.!A) ?:? (?b.!B) ?
|
||||
& !a+1:!b
|
||||
)
|
||||
& leftOf
|
||||
$ (!arg,(?.?.?.green.?.),(?.?.?.white.?.))
|
||||
& next$(!arg,(Blend.?.?.?.?.),(?.?.cats.?.?.))
|
||||
& next
|
||||
$ (!arg,(?.?.horse.?.?.),(Dunhill.?.?.?.?.))
|
||||
& next
|
||||
$ (!arg,(?.?.?.?.Norwegian.),(?.?.?.blue.?.))
|
||||
& next$(!arg,(?.water.?.?.?.),(Blend.?.?.?.?.))
|
||||
)
|
||||
& ( props
|
||||
= a constraint constraints house houses
|
||||
, remainingToDo shavedToDo toDo value values z
|
||||
. !arg:(?toDo.?shavedToDo.?house.?houses)
|
||||
& ( !toDo:(?values,?constraints) ?remainingToDo
|
||||
& !values
|
||||
: ( ?a
|
||||
( %@?value
|
||||
& !constraints
|
||||
: ( ?
|
||||
( !value
|
||||
. ?constraint
|
||||
& !house:!constraint
|
||||
)
|
||||
?
|
||||
| ~( ?
|
||||
( ?
|
||||
. ?constraint
|
||||
& !house:!constraint
|
||||
)
|
||||
?
|
||||
| ? (!value.?) ?
|
||||
)
|
||||
)
|
||||
)
|
||||
( ?z
|
||||
& props
|
||||
$ ( !remainingToDo
|
||||
. !shavedToDo (!a !z,!constraints)
|
||||
. (!value.!house)
|
||||
. !houses
|
||||
)
|
||||
)
|
||||
|
|
||||
& relations$!houses
|
||||
& out$(Solution !houses)
|
||||
)
|
||||
| !toDo:
|
||||
& props$(!shavedToDo...!house !houses)
|
||||
)
|
||||
)
|
||||
& props$(!properties...)
|
||||
& done
|
||||
);
|
||||
147
Task/Zebra-puzzle/C++/zebra-puzzle.cpp
Normal file
147
Task/Zebra-puzzle/C++/zebra-puzzle.cpp
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define defenum(name, val0, val1, val2, val3, val4) \
|
||||
enum name { val0, val1, val2, val3, val4 }; \
|
||||
const char *name ## _str[] = { # val0, # val1, # val2, # val3, # val4 }
|
||||
|
||||
defenum( Attrib, Color, Man, Drink, Animal, Smoke );
|
||||
defenum( Colors, Red, Green, White, Yellow, Blue );
|
||||
defenum( Mans, English, Swede, Dane, German, Norwegian );
|
||||
defenum( Drinks, Tea, Coffee, Milk, Beer, Water );
|
||||
defenum( Animals, Dog, Birds, Cats, Horse, Zebra );
|
||||
defenum( Smokes, PallMall, Dunhill, Blend, BlueMaster, Prince );
|
||||
|
||||
void printHouses(int ha[5][5]) {
|
||||
const char **attr_names[5] = {Colors_str, Mans_str, Drinks_str, Animals_str, Smokes_str};
|
||||
|
||||
printf("%-10s", "House");
|
||||
for (const char *name : Attrib_str) printf("%-10s", name);
|
||||
printf("\n");
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
printf("%-10d", i);
|
||||
for (int j = 0; j < 5; j++) printf("%-10s", attr_names[j][ha[i][j]]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
struct HouseNoRule {
|
||||
int houseno;
|
||||
Attrib a; int v;
|
||||
} housenos[] = {
|
||||
{2, Drink, Milk}, // Cond 9: In the middle house they drink milk.
|
||||
{0, Man, Norwegian} // Cond 10: The Norwegian lives in the first house.
|
||||
};
|
||||
|
||||
struct AttrPairRule {
|
||||
Attrib a1; int v1;
|
||||
Attrib a2; int v2;
|
||||
|
||||
bool invalid(int ha[5][5], int i) {
|
||||
return (ha[i][a1] >= 0 && ha[i][a2] >= 0) &&
|
||||
((ha[i][a1] == v1 && ha[i][a2] != v2) ||
|
||||
(ha[i][a1] != v1 && ha[i][a2] == v2));
|
||||
}
|
||||
} pairs[] = {
|
||||
{Man, English, Color, Red}, // Cond 2: The English man lives in the red house.
|
||||
{Man, Swede, Animal, Dog}, // Cond 3: The Swede has a dog.
|
||||
{Man, Dane, Drink, Tea}, // Cond 4: The Dane drinks tea.
|
||||
{Color, Green, Drink, Coffee}, // Cond 6: drink coffee in the green house.
|
||||
{Smoke, PallMall, Animal, Birds}, // Cond 7: The man who smokes Pall Mall has birds.
|
||||
{Smoke, Dunhill, Color, Yellow}, // Cond 8: In the yellow house they smoke Dunhill.
|
||||
{Smoke, BlueMaster, Drink, Beer}, // Cond 13: The man who smokes Blue Master drinks beer.
|
||||
{Man, German, Smoke, Prince} // Cond 14: The German smokes Prince
|
||||
};
|
||||
|
||||
struct NextToRule {
|
||||
Attrib a1; int v1;
|
||||
Attrib a2; int v2;
|
||||
|
||||
bool invalid(int ha[5][5], int i) {
|
||||
return (ha[i][a1] == v1) &&
|
||||
((i == 0 && ha[i + 1][a2] >= 0 && ha[i + 1][a2] != v2) ||
|
||||
(i == 4 && ha[i - 1][a2] != v2) ||
|
||||
(ha[i + 1][a2] >= 0 && ha[i + 1][a2] != v2 && ha[i - 1][a2] != v2));
|
||||
}
|
||||
} nexttos[] = {
|
||||
{Smoke, Blend, Animal, Cats}, // Cond 11: The man who smokes Blend lives in the house next to the house with cats.
|
||||
{Smoke, Dunhill, Animal, Horse}, // Cond 12: In a house next to the house where they have a horse, they smoke Dunhill.
|
||||
{Man, Norwegian, Color, Blue}, // Cond 15: The Norwegian lives next to the blue house.
|
||||
{Smoke, Blend, Drink, Water} // Cond 16: They drink water in a house next to the house where they smoke Blend.
|
||||
};
|
||||
|
||||
struct LeftOfRule {
|
||||
Attrib a1; int v1;
|
||||
Attrib a2; int v2;
|
||||
|
||||
bool invalid(int ha[5][5]) {
|
||||
return (ha[0][a2] == v2) || (ha[4][a1] == v1);
|
||||
}
|
||||
|
||||
bool invalid(int ha[5][5], int i) {
|
||||
return ((i > 0 && ha[i][a1] >= 0) &&
|
||||
((ha[i - 1][a1] == v1 && ha[i][a2] != v2) ||
|
||||
(ha[i - 1][a1] != v1 && ha[i][a2] == v2)));
|
||||
}
|
||||
} leftofs[] = {
|
||||
{Color, Green, Color, White} // Cond 5: The green house is immediately to the left of the white house.
|
||||
};
|
||||
|
||||
bool invalid(int ha[5][5]) {
|
||||
for (auto &rule : leftofs) if (rule.invalid(ha)) return true;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
#define eval_rules(rules) for (auto &rule : rules) if (rule.invalid(ha, i)) return true;
|
||||
eval_rules(pairs);
|
||||
eval_rules(nexttos);
|
||||
eval_rules(leftofs);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void search(bool used[5][5], int ha[5][5], const int hno, const int attr) {
|
||||
int nexthno, nextattr;
|
||||
if (attr < 4) {
|
||||
nextattr = attr + 1;
|
||||
nexthno = hno;
|
||||
} else {
|
||||
nextattr = 0;
|
||||
nexthno = hno + 1;
|
||||
}
|
||||
|
||||
if (ha[hno][attr] != -1) {
|
||||
search(used, ha, nexthno, nextattr);
|
||||
} else {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (used[attr][i]) continue;
|
||||
used[attr][i] = true;
|
||||
ha[hno][attr] = i;
|
||||
|
||||
if (!invalid(ha)) {
|
||||
if ((hno == 4) && (attr == 4)) {
|
||||
printHouses(ha);
|
||||
} else {
|
||||
search(used, ha, nexthno, nextattr);
|
||||
}
|
||||
}
|
||||
|
||||
used[attr][i] = false;
|
||||
}
|
||||
ha[hno][attr] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
bool used[5][5] = {};
|
||||
int ha[5][5]; memset(ha, -1, sizeof(ha));
|
||||
|
||||
for (auto &rule : housenos) {
|
||||
ha[rule.houseno][rule.a] = rule.v;
|
||||
used[rule.a][rule.v] = true;
|
||||
}
|
||||
|
||||
search(used, ha, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
43
Task/Zebra-puzzle/Curry/zebra-puzzle.curry
Normal file
43
Task/Zebra-puzzle/Curry/zebra-puzzle.curry
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import Constraint (allC, anyC)
|
||||
import Findall (findall)
|
||||
|
||||
|
||||
data House = H Color Man Pet Drink Smoke
|
||||
|
||||
data Color = Red | Green | Blue | Yellow | White
|
||||
data Man = Eng | Swe | Dan | Nor | Ger
|
||||
data Pet = Dog | Birds | Cats | Horse | Zebra
|
||||
data Drink = Coffee | Tea | Milk | Beer | Water
|
||||
data Smoke = PM | DH | Blend | BM | Prince
|
||||
|
||||
|
||||
houses :: [House] -> Success
|
||||
houses hs@[H1,_,H3,_,_] = -- 1
|
||||
H _ _ _ Milk _ =:= H3 -- 9
|
||||
& H _ Nor _ _ _ =:= H1 -- 10
|
||||
& allC (`member` hs)
|
||||
[ H Red Eng _ _ _ -- 2
|
||||
, H _ Swe Dog _ _ -- 3
|
||||
, H _ Dan _ Tea _ -- 4
|
||||
, H Green _ _ Coffee _ -- 6
|
||||
, H _ _ Birds _ PM -- 7
|
||||
, H Yellow _ _ _ DH -- 8
|
||||
, H _ _ _ Beer BM -- 13
|
||||
, H _ Ger _ _ Prince -- 14
|
||||
]
|
||||
& H Green _ _ _ _ `leftTo` H White _ _ _ _ -- 5
|
||||
& H _ _ _ _ Blend `nextTo` H _ _ Cats _ _ -- 11
|
||||
& H _ _ Horse _ _ `nextTo` H _ _ _ _ DH -- 12
|
||||
& H _ Nor _ _ _ `nextTo` H Blue _ _ _ _ -- 15
|
||||
& H _ _ _ Water _ `nextTo` H _ _ _ _ Blend -- 16
|
||||
where
|
||||
x `leftTo` y = _ ++ [x,y] ++ _ =:= hs
|
||||
x `nextTo` y = x `leftTo` y
|
||||
? y `leftTo` x
|
||||
|
||||
|
||||
member :: a -> [a] -> Success
|
||||
member = anyC . (=:=)
|
||||
|
||||
|
||||
main = findall $ \(hs,who) -> houses hs & H _ who Zebra _ _ `member` hs
|
||||
|
|
@ -8,11 +8,11 @@ enum Content { Beer, Coffee, Milk, Tea, Water,
|
|||
enum Test { Drink, Person, Color, Smoke, Pet }
|
||||
enum House { One, Two, Three, Four, Five }
|
||||
|
||||
alias Content[EnumMembers!Test.length][EnumMembers!House.length] TM;
|
||||
alias TM = Content[EnumMembers!Test.length][EnumMembers!House.length];
|
||||
|
||||
bool finalChecks(in ref TM M) pure nothrow {
|
||||
bool finalChecks(in ref TM M) pure nothrow @safe @nogc {
|
||||
int diff(in Content a, in Content b, in Test ca, in Test cb)
|
||||
nothrow {
|
||||
nothrow @safe @nogc {
|
||||
foreach (immutable h1; EnumMembers!House)
|
||||
foreach (immutable h2; EnumMembers!House)
|
||||
if (M[ca][h1] == a && M[cb][h2] == b)
|
||||
|
|
@ -20,16 +20,15 @@ bool finalChecks(in ref TM M) pure nothrow {
|
|||
assert(0); // Useless but required.
|
||||
}
|
||||
|
||||
with (Content) with (Test) { // Braces required (8414).
|
||||
with (Content) with (Test)
|
||||
return abs(diff(Norwegian, Blue, Person, Color)) == 1 &&
|
||||
diff(Green, White, Color, Color) == -1 &&
|
||||
abs(diff(Horse, Dunhill, Pet, Smoke)) == 1 &&
|
||||
abs(diff(Water, Blend, Drink, Smoke)) == 1 &&
|
||||
abs(diff(Blend, Cat, Smoke, Pet)) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool constrained(in ref TM M, in Test atest) pure nothrow {
|
||||
bool constrained(in ref TM M, in Test atest) pure nothrow @safe @nogc {
|
||||
with (Content) with (Test) with (House)
|
||||
final switch (atest) {
|
||||
case Drink:
|
||||
|
|
@ -67,7 +66,7 @@ void show(in ref TM M) {
|
|||
writef("%5s: ", h);
|
||||
foreach (immutable t; EnumMembers!Test)
|
||||
writef("%10s ", M[t][h]);
|
||||
writeln();
|
||||
writeln;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
import std.stdio, std.math, std.traits, std.typetuple, permutations1;
|
||||
import std.stdio, std.math, std.traits, std.typecons, std.typetuple, permutations1;
|
||||
|
||||
uint factorial(in uint n) pure nothrow @nogc @safe
|
||||
in {
|
||||
assert(n <= 12);
|
||||
} body {
|
||||
uint result = 1;
|
||||
foreach (immutable i; 1 .. n + 1)
|
||||
result *= i;
|
||||
return result;
|
||||
}
|
||||
|
||||
enum Number { One, Two, Three, Four, Five }
|
||||
enum Color { Red, Green, Blue, White, Yellow }
|
||||
|
|
@ -7,42 +17,46 @@ enum Smoke { PallMall, Dunhill, Blend, BlueMaster, Prince }
|
|||
enum Pet { Dog, Cat, Zebra, Horse, Bird }
|
||||
enum Nation { British, Swedish, Danish, Norvegian, German }
|
||||
|
||||
bool isPossible(immutable Number[5]* number,
|
||||
immutable Color[5]* color=null,
|
||||
immutable Drink[5]* drink=null,
|
||||
immutable Smoke[5]* smoke=null,
|
||||
immutable Pet[5]* pet=null) pure nothrow {
|
||||
if ((number && (*number)[Nation.Norvegian] != Number.One) ||
|
||||
(color && (*color)[Nation.British] != Color.Red) ||
|
||||
(drink && (*drink)[Nation.Danish] != Drink.Tea) ||
|
||||
(smoke && (*smoke)[Nation.German] != Smoke.Prince) ||
|
||||
(pet && (*pet)[Nation.Swedish] != Pet.Dog))
|
||||
enum size_t M = EnumMembers!Number.length;
|
||||
|
||||
auto nullableRef(T)(ref T item) pure nothrow @nogc {
|
||||
return NullableRef!T(&item);
|
||||
}
|
||||
|
||||
bool isPossible(NullableRef!(immutable Number[M]) number,
|
||||
NullableRef!(immutable Color[M]) color=null,
|
||||
NullableRef!(immutable Drink[M]) drink=null,
|
||||
NullableRef!(immutable Smoke[M]) smoke=null,
|
||||
NullableRef!(immutable Pet[M]) pet=null) pure nothrow @safe @nogc {
|
||||
if ((!number.isNull && number[Nation.Norvegian] != Number.One) ||
|
||||
(!color.isNull && color[Nation.British] != Color.Red) ||
|
||||
(!drink.isNull && drink[Nation.Danish] != Drink.Tea) ||
|
||||
(!smoke.isNull && smoke[Nation.German] != Smoke.Prince) ||
|
||||
(!pet.isNull && pet[Nation.Swedish] != Pet.Dog))
|
||||
return false;
|
||||
|
||||
if (!number || !color || !drink || !smoke || !pet)
|
||||
if (number.isNull || color.isNull || drink.isNull || smoke.isNull ||
|
||||
pet.isNull)
|
||||
return true;
|
||||
|
||||
foreach (immutable i; 0 .. 5) {
|
||||
if (((*color)[i] == Color.Green && (*drink)[i] != Drink.Coffee) ||
|
||||
((*smoke)[i] == Smoke.PallMall && (*pet)[i] != Pet.Bird) ||
|
||||
((*color)[i] == Color.Yellow && (*smoke)[i] != Smoke.Dunhill) ||
|
||||
((*number)[i] == Number.Three && (*drink)[i] != Drink.Milk) ||
|
||||
((*smoke)[i] == Smoke.BlueMaster && (*drink)[i] != Drink.Beer)||
|
||||
((*color)[i] == Color.Blue && (*number)[i] != Number.Two))
|
||||
foreach (immutable i; 0 .. M) {
|
||||
if ((color[i] == Color.Green && drink[i] != Drink.Coffee) ||
|
||||
(smoke[i] == Smoke.PallMall && pet[i] != Pet.Bird) ||
|
||||
(color[i] == Color.Yellow && smoke[i] != Smoke.Dunhill) ||
|
||||
(number[i] == Number.Three && drink[i] != Drink.Milk) ||
|
||||
(smoke[i] == Smoke.BlueMaster && drink[i] != Drink.Beer)||
|
||||
(color[i] == Color.Blue && number[i] != Number.Two))
|
||||
return false;
|
||||
|
||||
foreach (immutable j; 0 .. 5) {
|
||||
if ((*color)[i] == Color.Green && (*color)[j] == Color.White &&
|
||||
(*number)[j] - (*number)[i] != 1)
|
||||
foreach (immutable j; 0 .. M) {
|
||||
if (color[i] == Color.Green && color[j] == Color.White &&
|
||||
number[j] - number[i] != 1)
|
||||
return false;
|
||||
|
||||
immutable int diff = abs((*number)[i] - (*number)[j]);
|
||||
if (((*smoke)[i] == Smoke.Blend &&
|
||||
(*pet)[j] == Pet.Cat && diff != 1) ||
|
||||
((*pet)[i] == Pet.Horse &&
|
||||
(*smoke)[j] == Smoke.Dunhill && diff != 1) ||
|
||||
((*smoke)[i] == Smoke.Blend &&
|
||||
(*drink)[j] == Drink.Water && diff != 1))
|
||||
immutable diff = abs(number[i] - number[j]);
|
||||
if ((smoke[i] == Smoke.Blend && pet[j] == Pet.Cat && diff != 1) ||
|
||||
(pet[i] == Pet.Horse && smoke[j] == Smoke.Dunhill && diff != 1) ||
|
||||
(smoke[i] == Smoke.Blend && drink[j] == Drink.Water && diff != 1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -50,32 +64,36 @@ bool isPossible(immutable Number[5]* number,
|
|||
return true;
|
||||
}
|
||||
|
||||
alias N = nullableRef; // At module level scope to be used with UFCS.
|
||||
|
||||
void main() {
|
||||
static immutable int[5][] perms = [0, 1, 2, 3, 4].permutations;
|
||||
immutable nation = [EnumMembers!Nation];
|
||||
enum size_t FM = M.factorial;
|
||||
|
||||
// Not nice casts:
|
||||
static immutable permsNumber = cast(immutable Number[5][])perms,
|
||||
permsColor = cast(immutable Color[5][])perms,
|
||||
permsDrink = cast(immutable Drink[5][])perms,
|
||||
permsSmoke = cast(immutable Smoke[5][])perms,
|
||||
permsPet = cast(immutable Pet[5][])perms;
|
||||
static immutable Number[M][FM] numberPerms = [EnumMembers!Number].permutations;
|
||||
static immutable Color[M][FM] colorPerms = [EnumMembers!Color].permutations;
|
||||
static immutable Drink[M][FM] drinkPerms = [EnumMembers!Drink].permutations;
|
||||
static immutable Smoke[M][FM] smokePerms = [EnumMembers!Smoke].permutations;
|
||||
static immutable Pet[M][FM] petPerms = [EnumMembers!Pet].permutations;
|
||||
|
||||
foreach (immutable ref number; permsNumber)
|
||||
if (isPossible(&number))
|
||||
foreach (immutable ref color; permsColor)
|
||||
if (isPossible(&number, &color))
|
||||
foreach (immutable ref drink; permsDrink)
|
||||
if (isPossible(&number, &color, &drink))
|
||||
foreach (immutable ref smoke; permsSmoke)
|
||||
if (isPossible(&number, &color, &drink, &smoke))
|
||||
foreach (immutable ref pet; permsPet)
|
||||
if (isPossible(&number,&color,&drink,&smoke,&pet)) {
|
||||
// You can reduce the compile-time computations using four casts like this:
|
||||
// static colorPerms = cast(immutable Color[M][FM])numberPerms;
|
||||
|
||||
static immutable Nation[M] nation = [EnumMembers!Nation];
|
||||
|
||||
foreach (immutable ref number; numberPerms)
|
||||
if (isPossible(number.N))
|
||||
foreach (immutable ref color; colorPerms)
|
||||
if (isPossible(number.N, color.N))
|
||||
foreach (immutable ref drink; drinkPerms)
|
||||
if (isPossible(number.N, color.N, drink.N))
|
||||
foreach (immutable ref smoke; smokePerms)
|
||||
if (isPossible(number.N, color.N, drink.N, smoke.N))
|
||||
foreach (immutable ref pet; petPerms)
|
||||
if (isPossible(number.N, color.N, drink.N, smoke.N, pet.N)) {
|
||||
writeln("Found a solution:");
|
||||
foreach (immutable x; TypeTuple!(nation, number,
|
||||
color, drink, smoke, pet))
|
||||
foreach (x; TypeTuple!(nation, number, color, drink, smoke, pet))
|
||||
writefln("%6s: %12s%12s%12s%12s%12s",
|
||||
Unqual!(typeof(x[0])).stringof,
|
||||
(Unqual!(typeof(x[0]))).stringof,
|
||||
x[0], x[1], x[2], x[3], x[4]);
|
||||
writeln;
|
||||
}
|
||||
|
|
|
|||
33
Task/Zebra-puzzle/D/zebra-puzzle-3.d
Normal file
33
Task/Zebra-puzzle/D/zebra-puzzle-3.d
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
void main() {
|
||||
import std.stdio, std.algorithm, permutations2;
|
||||
|
||||
enum E { Red, Green, Blue, White, Yellow,
|
||||
Milk, Coffee, Water, Beer, Tea,
|
||||
PallMall, Dunhill, Blend, BlueMaster, Prince,
|
||||
Dog, Cat, Zebra, Horse, Birds,
|
||||
British, Swedish, Danish, Norvegian, German }
|
||||
|
||||
enum has = (E[] a, E x, E[] b, E y) => a.countUntil(x) == b.countUntil(y);
|
||||
enum leftOf = (E[] a, E x, E[] b, E y) => a.countUntil(x) == b.countUntil(y) + 1;
|
||||
enum nextTo = (E[] a, E x, E[] b, E y) => leftOf(a, x, b, y) || leftOf(b, y, a, x);
|
||||
|
||||
with (E) foreach (houses; [Red, Blue, Green, Yellow, White].permutations)
|
||||
if (leftOf(houses, White, houses, Green))
|
||||
foreach (persons; [Norvegian, British, Swedish, German, Danish].permutations)
|
||||
if (has(persons, British, houses, Red) && persons[0] == Norvegian &&
|
||||
nextTo(persons, Norvegian, houses, Blue))
|
||||
foreach (drinks; [Tea, Coffee, Milk, Beer, Water].permutations)
|
||||
if (has(drinks, Tea, persons, Danish) &&
|
||||
has(drinks, Coffee, houses, Green) && drinks[$ / 2] == Milk)
|
||||
foreach (pets; [Dog, Birds, Cat, Horse, Zebra].permutations)
|
||||
if (has(pets, Dog, persons, Swedish))
|
||||
foreach (smokes; [PallMall, Dunhill, Blend, BlueMaster, Prince].permutations)
|
||||
if (has(smokes, PallMall, pets, Birds) &&
|
||||
has(smokes, Dunhill, houses, Yellow) &&
|
||||
nextTo(smokes, Blend, pets, Cat) &&
|
||||
nextTo(smokes, Dunhill, pets, Horse) &&
|
||||
has(smokes, BlueMaster, drinks, Beer) &&
|
||||
has(smokes, Prince, persons, German) &&
|
||||
nextTo(drinks, Water, smokes, Blend))
|
||||
writefln("%(%10s\n%)\n", [houses, persons, drinks, pets, smokes]);
|
||||
}
|
||||
294
Task/Zebra-puzzle/Go/zebra-puzzle.go
Normal file
294
Task/Zebra-puzzle/Go/zebra-puzzle.go
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Define some types
|
||||
|
||||
type HouseSet [5]*House
|
||||
type House struct {
|
||||
n Nationality
|
||||
c Colour
|
||||
a Animal
|
||||
d Drink
|
||||
s Smoke
|
||||
}
|
||||
type Nationality int8
|
||||
type Colour int8
|
||||
type Animal int8
|
||||
type Drink int8
|
||||
type Smoke int8
|
||||
|
||||
// Define the possible values
|
||||
|
||||
const (
|
||||
English Nationality = iota
|
||||
Swede
|
||||
Dane
|
||||
Norwegian
|
||||
German
|
||||
)
|
||||
const (
|
||||
Red Colour = iota
|
||||
Green
|
||||
White
|
||||
Yellow
|
||||
Blue
|
||||
)
|
||||
const (
|
||||
Dog Animal = iota
|
||||
Birds
|
||||
Cats
|
||||
Horse
|
||||
Zebra
|
||||
)
|
||||
const (
|
||||
Tea Drink = iota
|
||||
Coffee
|
||||
Milk
|
||||
Beer
|
||||
Water
|
||||
)
|
||||
const (
|
||||
PallMall Smoke = iota
|
||||
Dunhill
|
||||
Blend
|
||||
BlueMaster
|
||||
Prince
|
||||
)
|
||||
|
||||
// And how to print them
|
||||
|
||||
var nationalities = [...]string{"English", "Swede", "Dane", "Norwegian", "German"}
|
||||
var colours = [...]string{"red", "green", "white", "yellow", "blue"}
|
||||
var animals = [...]string{"dog", "birds", "cats", "horse", "zebra"}
|
||||
var drinks = [...]string{"tea", "coffee", "milk", "beer", "water"}
|
||||
var smokes = [...]string{"Pall Mall", "Dunhill", "Blend", "Blue Master", "Prince"}
|
||||
|
||||
func (n Nationality) String() string { return nationalities[n] }
|
||||
func (c Colour) String() string { return colours[c] }
|
||||
func (a Animal) String() string { return animals[a] }
|
||||
func (d Drink) String() string { return drinks[d] }
|
||||
func (s Smoke) String() string { return smokes[s] }
|
||||
func (h House) String() string {
|
||||
return fmt.Sprintf("%-9s %-6s %-5s %-6s %s", h.n, h.c, h.a, h.d, h.s)
|
||||
}
|
||||
func (hs HouseSet) String() string {
|
||||
lines := make([]string, 0, len(hs))
|
||||
for i, h := range hs {
|
||||
s := fmt.Sprintf("%d %s", i, h)
|
||||
lines = append(lines, s)
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
// Simple brute force solution
|
||||
|
||||
func simpleBruteForce() (int, HouseSet) {
|
||||
var v []House
|
||||
for n := range nationalities {
|
||||
for c := range colours {
|
||||
for a := range animals {
|
||||
for d := range drinks {
|
||||
for s := range smokes {
|
||||
h := House{
|
||||
n: Nationality(n),
|
||||
c: Colour(c),
|
||||
a: Animal(a),
|
||||
d: Drink(d),
|
||||
s: Smoke(s),
|
||||
}
|
||||
if !h.Valid() {
|
||||
continue
|
||||
}
|
||||
v = append(v, h)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
n := len(v)
|
||||
log.Println("Generated", n, "valid houses")
|
||||
|
||||
combos := 0
|
||||
first := 0
|
||||
valid := 0
|
||||
var validSet HouseSet
|
||||
for a := 0; a < n; a++ {
|
||||
if v[a].n != Norwegian { // Condition 10:
|
||||
continue
|
||||
}
|
||||
for b := 0; b < n; b++ {
|
||||
if b == a {
|
||||
continue
|
||||
}
|
||||
if v[b].anyDups(&v[a]) {
|
||||
continue
|
||||
}
|
||||
for c := 0; c < n; c++ {
|
||||
if c == b || c == a {
|
||||
continue
|
||||
}
|
||||
if v[c].d != Milk { // Condition 9:
|
||||
continue
|
||||
}
|
||||
if v[c].anyDups(&v[b], &v[a]) {
|
||||
continue
|
||||
}
|
||||
for d := 0; d < n; d++ {
|
||||
if d == c || d == b || d == a {
|
||||
continue
|
||||
}
|
||||
if v[d].anyDups(&v[c], &v[b], &v[a]) {
|
||||
continue
|
||||
}
|
||||
for e := 0; e < n; e++ {
|
||||
if e == d || e == c || e == b || e == a {
|
||||
continue
|
||||
}
|
||||
if v[e].anyDups(&v[d], &v[c], &v[b], &v[a]) {
|
||||
continue
|
||||
}
|
||||
combos++
|
||||
set := HouseSet{&v[a], &v[b], &v[c], &v[d], &v[e]}
|
||||
if set.Valid() {
|
||||
valid++
|
||||
if valid == 1 {
|
||||
first = combos
|
||||
}
|
||||
validSet = set
|
||||
//return set
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Println("Tested", first, "different combinations of valid houses before finding solution")
|
||||
log.Println("Tested", combos, "different combinations of valid houses in total")
|
||||
return valid, validSet
|
||||
}
|
||||
|
||||
// anyDups returns true if h as any duplicate attributes with any of the specified houses
|
||||
func (h *House) anyDups(list ...*House) bool {
|
||||
for _, b := range list {
|
||||
if h.n == b.n || h.c == b.c || h.a == b.a || h.d == b.d || h.s == b.s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *House) Valid() bool {
|
||||
// Condition 2:
|
||||
if h.n == English && h.c != Red || h.n != English && h.c == Red {
|
||||
return false
|
||||
}
|
||||
// Condition 3:
|
||||
if h.n == Swede && h.a != Dog || h.n != Swede && h.a == Dog {
|
||||
return false
|
||||
}
|
||||
// Condition 4:
|
||||
if h.n == Dane && h.d != Tea || h.n != Dane && h.d == Tea {
|
||||
return false
|
||||
}
|
||||
// Condition 6:
|
||||
if h.c == Green && h.d != Coffee || h.c != Green && h.d == Coffee {
|
||||
return false
|
||||
}
|
||||
// Condition 7:
|
||||
if h.a == Birds && h.s != PallMall || h.a != Birds && h.s == PallMall {
|
||||
return false
|
||||
}
|
||||
// Condition 8:
|
||||
if h.c == Yellow && h.s != Dunhill || h.c != Yellow && h.s == Dunhill {
|
||||
return false
|
||||
}
|
||||
// Condition 11:
|
||||
if h.a == Cats && h.s == Blend {
|
||||
return false
|
||||
}
|
||||
// Condition 12:
|
||||
if h.a == Horse && h.s == Dunhill {
|
||||
return false
|
||||
}
|
||||
// Condition 13:
|
||||
if h.d == Beer && h.s != BlueMaster || h.d != Beer && h.s == BlueMaster {
|
||||
return false
|
||||
}
|
||||
// Condition 14:
|
||||
if h.n == German && h.s != Prince || h.n != German && h.s == Prince {
|
||||
return false
|
||||
}
|
||||
// Condition 15:
|
||||
if h.n == Norwegian && h.c == Blue {
|
||||
return false
|
||||
}
|
||||
// Condition 16:
|
||||
if h.d == Water && h.s == Blend {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (hs *HouseSet) Valid() bool {
|
||||
ni := make(map[Nationality]int, 5)
|
||||
ci := make(map[Colour]int, 5)
|
||||
ai := make(map[Animal]int, 5)
|
||||
di := make(map[Drink]int, 5)
|
||||
si := make(map[Smoke]int, 5)
|
||||
for i, h := range hs {
|
||||
ni[h.n] = i
|
||||
ci[h.c] = i
|
||||
ai[h.a] = i
|
||||
di[h.d] = i
|
||||
si[h.s] = i
|
||||
}
|
||||
// Condition 5:
|
||||
if ci[Green]+1 != ci[White] {
|
||||
return false
|
||||
}
|
||||
// Condition 11:
|
||||
if dist(ai[Cats], si[Blend]) != 1 {
|
||||
return false
|
||||
}
|
||||
// Condition 12:
|
||||
if dist(ai[Horse], si[Dunhill]) != 1 {
|
||||
return false
|
||||
}
|
||||
// Condition 15:
|
||||
if dist(ni[Norwegian], ci[Blue]) != 1 {
|
||||
return false
|
||||
}
|
||||
// Condition 16:
|
||||
if dist(di[Water], si[Blend]) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Condition 9: (already tested elsewhere)
|
||||
if hs[2].d != Milk {
|
||||
return false
|
||||
}
|
||||
// Condition 10: (already tested elsewhere)
|
||||
if hs[0].n != Norwegian {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func dist(a, b int) int {
|
||||
if a > b {
|
||||
return a - b
|
||||
}
|
||||
return b - a
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
n, sol := simpleBruteForce()
|
||||
fmt.Println(n, "solution found")
|
||||
fmt.Println(sol)
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import Control.Applicative ((<$>), (<*>))
|
||||
import Control.Monad
|
||||
import Control.Monad (foldM, forM_)
|
||||
import Data.List ((\\), isInfixOf)
|
||||
|
||||
-- types
|
||||
|
|
@ -30,7 +30,8 @@ data Smoke = PallMall | Dunhill | Blend | BlueMaster | Prince
|
|||
|
||||
main :: IO ()
|
||||
main = do
|
||||
mapM_ (\x-> mapM_ print (reverse x) >> putStrLn "----") solutions
|
||||
forM_ solutions $ \x -> mapM_ print (reverse x)
|
||||
>> putStrLn "----"
|
||||
putStrLn "No More Solutions"
|
||||
|
||||
|
||||
60
Task/Zebra-puzzle/Haskell/zebra-puzzle-2.hs
Normal file
60
Task/Zebra-puzzle/Haskell/zebra-puzzle-2.hs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import Control.Monad
|
||||
import Data.List
|
||||
|
||||
values :: (Bounded a, Enum a) => [[a]]
|
||||
values = permutations [minBound..maxBound]
|
||||
|
||||
data Nation = English | Swede | Dane | Norwegian | German
|
||||
deriving (Bounded, Enum, Eq, Show)
|
||||
data Color = Red | Green | White | Yellow | Blue
|
||||
deriving (Bounded, Enum, Eq, Show)
|
||||
data Pet = Dog | Birds | Cats | Horse | Zebra
|
||||
deriving (Bounded, Enum, Eq, Show)
|
||||
data Drink = Tea | Coffee | Milk | Beer | Water
|
||||
deriving (Bounded, Enum, Eq, Show)
|
||||
data Smoke = PallMall | Dunhill | Blend | BlueMaster | Prince
|
||||
deriving (Bounded, Enum, Eq, Show)
|
||||
|
||||
answers = do
|
||||
color <- values
|
||||
leftOf color Green color White -- 5
|
||||
|
||||
nation <- values
|
||||
first nation Norwegian -- 10
|
||||
same nation English color Red -- 2
|
||||
nextTo nation Norwegian color Blue -- 15
|
||||
|
||||
drink <- values
|
||||
middle drink Milk -- 9
|
||||
same nation Dane drink Tea -- 4
|
||||
same drink Coffee color Green -- 6
|
||||
|
||||
pet <- values
|
||||
same nation Swede pet Dog -- 3
|
||||
|
||||
smoke <- values
|
||||
same smoke PallMall pet Birds -- 7
|
||||
same color Yellow smoke Dunhill -- 8
|
||||
nextTo smoke Blend pet Cats -- 11
|
||||
nextTo pet Horse smoke Dunhill -- 12
|
||||
same nation German smoke Prince -- 14
|
||||
same smoke BlueMaster drink Beer -- 13
|
||||
nextTo drink Water smoke Blend -- 16
|
||||
|
||||
return $ zip5 nation color pet drink smoke
|
||||
|
||||
where
|
||||
same xs x ys y = guard $ (x, y) `elem` zip xs ys
|
||||
leftOf xs x ys y = same xs x (tail ys) y
|
||||
nextTo xs x ys y = leftOf xs x ys y `mplus`
|
||||
leftOf ys y xs x
|
||||
middle xs x = guard $ xs !! 2 == x
|
||||
first xs x = guard $ head xs == x
|
||||
|
||||
main = do
|
||||
forM_ answers $ (\answer -> -- for answer in answers:
|
||||
do
|
||||
mapM_ print answer
|
||||
print [nation | (nation, _, Zebra, _, _) <- answer]
|
||||
putStrLn "" )
|
||||
putStrLn "No more solutions!"
|
||||
220
Task/Zebra-puzzle/Java/zebra-puzzle-1.java
Normal file
220
Task/Zebra-puzzle/Java/zebra-puzzle-1.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
98
Task/Zebra-puzzle/Java/zebra-puzzle-2.java
Normal file
98
Task/Zebra-puzzle/Java/zebra-puzzle-2.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
317
Task/Zebra-puzzle/Java/zebra-puzzle-3.java
Normal file
317
Task/Zebra-puzzle/Java/zebra-puzzle-3.java
Normal 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;
|
||||
}
|
||||
}
|
||||
114
Task/Zebra-puzzle/Mathematica/zebra-puzzle.math
Normal file
114
Task/Zebra-puzzle/Mathematica/zebra-puzzle.math
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
ClearAll[EliminatePoss, FilterPuzzle]
|
||||
EliminatePoss[ct_, key1_, key2_] := Module[{t = ct, poss1, poss2, poss, notposs},
|
||||
poss1 = Position[t, key1];
|
||||
poss2 = Position[t, key2];
|
||||
poss = Intersection[Last /@ poss1, Last /@ poss2];
|
||||
notposs = Complement[Range[5], poss];
|
||||
poss1 = Select[poss1, MemberQ[notposs, Last[#]] &];
|
||||
poss2 = Select[poss2, MemberQ[notposs, Last[#]] &];
|
||||
t = ReplacePart[t, poss1 -> Null];
|
||||
t = ReplacePart[t, poss2 -> Null];
|
||||
t
|
||||
]
|
||||
FilterPuzzle[tbl_] := Module[{t = tbl, poss1, poss2, poss, notposs, rows, columns, vals, sets, delpos},
|
||||
t = EliminatePoss[t, "English", "Red"]; (*2. The English man lives in the red house. *)
|
||||
t = EliminatePoss[t, "Swede", "Dog"]; (* 3. The Swede has a dog. *)
|
||||
t = EliminatePoss[t, "Dane", "Tea"]; (* 4. The Dane drinks tea. *)
|
||||
t = EliminatePoss[t, "Green", "Coffee"]; (* 6. They drink coffee in the green house. *)
|
||||
t = EliminatePoss[t, "Pall Mall", "Birds"]; (* 7. The man who smokes Pall Mall has birds.*)
|
||||
t = EliminatePoss[t, "Yellow", "Dunhill"]; (* 8. In the yellow house they smoke Dunhill. *)
|
||||
t = EliminatePoss[t, "Blue Master", "Beer"]; (*13. The man who smokes Blue Master drinks beer. *)
|
||||
t = EliminatePoss[t, "German", "Prince"]; (* 14. The German smokes Prince. *)
|
||||
|
||||
(* 9. In the middle house they drink milk. *)
|
||||
poss = Position[t, "Milk"];
|
||||
delpos = Select[poss, #[[2]] != 3 &];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(* 10. The Norwegian lives in the first house. *)
|
||||
poss = Position[t, "Norwegian"];
|
||||
delpos = Select[poss, #[[2]] != 1 &];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(* 15. The Norwegian lives next to the blue house.*)
|
||||
poss1 = Position[t, "Norwegian"];
|
||||
poss2 = Position[t, "Blue"];
|
||||
poss = Tuples[{poss1, poss2}];
|
||||
poss = Select[poss, #[[1, 2]] + 1 == #[[2, 2]] \[Or] #[[1, 2]] - 1 == #[[2, 2]] &]\[Transpose];
|
||||
delpos = Complement[poss1, poss[[1]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
delpos = Complement[poss2, poss[[2]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(* 5. The green house is immediately to the left of the white house. *)
|
||||
poss1 = Position[t, "Green"];
|
||||
poss2 = Position[t, "White"];
|
||||
poss = Tuples[{poss1, poss2}];
|
||||
poss = Select[poss, #[[1, 2]] + 1 == #[[2, 2]] &]\[Transpose];
|
||||
delpos = Complement[poss1, poss[[1]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
delpos = Complement[poss2, poss[[2]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(*11. The man who smokes Blend lives in the house next to the house with cats.*)
|
||||
poss1 = Position[t, "Blend"];
|
||||
poss2 = Position[t, "Cats"];
|
||||
poss = Tuples[{poss1, poss2}];
|
||||
poss = Select[poss, #[[1, 2]] + 1 == #[[2, 2]] \[Or] #[[1, 2]] - 1 == #[[2, 2]] &]\[Transpose];
|
||||
delpos = Complement[poss1, poss[[1]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
delpos = Complement[poss2, poss[[2]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(* 12. In a house next to the house where they have a horse, they smoke Dunhill. *)
|
||||
poss1 = Position[t, "Horse"];
|
||||
poss2 = Position[t, "Dunhill"];
|
||||
poss = Tuples[{poss1, poss2}];
|
||||
poss = Select[poss, #[[1, 2]] + 1 == #[[2, 2]] \[Or] #[[1, 2]] - 1 == #[[2, 2]] &]\[Transpose];
|
||||
delpos = Complement[poss1, poss[[1]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
delpos = Complement[poss2, poss[[2]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(* 16. They drink water in a house next to the house where they smoke Blend. *)
|
||||
poss1 = Position[t, "Water"];
|
||||
poss2 = Position[t, "Blend"];
|
||||
poss = Tuples[{poss1, poss2}];
|
||||
poss = Select[poss, #[[1, 2]] + 1 == #[[2, 2]] \[Or] #[[1, 2]] - 1 == #[[2, 2]] &]\[Transpose];
|
||||
delpos = Complement[poss1, poss[[1]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
delpos = Complement[poss2, poss[[2]]];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(*General rule 1 in a line => cross out vertical and horizontal lines*)
|
||||
(* 1 in a row*)
|
||||
vals = Select[t, Count[#, Null] == 4 &];
|
||||
vals = DeleteCases[Flatten[vals], Null];
|
||||
poss = Flatten[Position[t, #] & /@ vals, 1];
|
||||
delpos = With[{r = First[#], c = Last[#]}, {#, c} & /@ (Range[-4, 0] + Ceiling[r, 5])] & /@ poss; (*delete in columns*)
|
||||
delpos = Flatten[MapThread[DeleteCases, {delpos, poss}], 1];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
(* 1 in a column*)
|
||||
sets = Flatten[Table[{i + k*5, j}, {k, 0, 4}, {j, 1, 5}, {i, 1, 5}],1];
|
||||
sets = {#, Extract[t, #]} & /@ sets;
|
||||
sets = Select[sets, Count[#[[2]], Null] == 4 &];
|
||||
sets = Flatten[Transpose /@ sets, 1];
|
||||
sets = DeleteCases[sets, {{_, _}, Null}];
|
||||
delpos = sets[[All, 1]];(*delete in rows*)
|
||||
delpos = With[{r = First[#], c = Last[#]}, {r, #} & /@ (DeleteCases[Range[5], c])] & /@ delpos;
|
||||
delpos = Flatten[delpos, 1];
|
||||
t = ReplacePart[t, delpos -> Null];
|
||||
|
||||
t
|
||||
]
|
||||
colors = {"Blue", "Green", "Red", "White", "Yellow"};
|
||||
nationality = {"Dane", "English", "German", "Norwegian", "Swede"};
|
||||
beverage = {"Beer", "Coffee", "Milk", "Tea", "Water"};
|
||||
animal = {"Birds", "Cats", "Dog", "Horse", "Zebra"};
|
||||
smoke = {"Blend", "Blue Master", "Dunhill", "Pall Mall", "Prince"};
|
||||
vals = {colors, nationality, beverage, animal, smoke};
|
||||
bigtable = Join @@ (ConstantArray[#, 5]\[Transpose] & /@ vals);
|
||||
|
||||
bigtable = FixedPoint[FilterPuzzle, bigtable];
|
||||
TableForm[DeleteCases[bigtable\[Transpose], Null, \[Infinity]], TableHeadings -> {Range[5], None}]
|
||||
|
|
@ -5,17 +5,17 @@ next_to(A,B,C):- left_of(A,B,C) ; left_of(B,A,C).
|
|||
left_of(A,B,C):- append(_,[A,B|_],C).
|
||||
|
||||
zebra(Owns, HS):- % color,nation,pet,drink,smokes
|
||||
HS = [h(_,norwegian,_,_,_),_, h(_,_,_,milk,_),_,_],
|
||||
select( [h(red,englishman,_,_,_),h(_,swede,dog,_,_),
|
||||
h(_,dane,_,tea,_), h(_,german,_,_,prince)], HS),
|
||||
select( [h(_,_,birds,_,pallmall),h(yellow,_,_,_,dunhill),
|
||||
h(_,_,_,beer,bluemaster)], HS),
|
||||
left_of( h(green,_,_,coffee,_), h(white,_,_,_,_), HS),
|
||||
next_to( h(_,_,_,_,dunhill), h(_,_,horse,_,_), HS),
|
||||
next_to( h(_,_,_,_,blend), h(_,_,cats, _,_), HS),
|
||||
next_to( h(_,_,_,_,blend), h(_,_,_,water,_), HS),
|
||||
next_to( h(_,norwegian,_,_,_), h(blue,_,_,_,_), HS),
|
||||
member( h(_,Owns,zebra,_,_), HS).
|
||||
HS = [ h(_,norwegian,_,_,_), _, h(_,_,_,milk,_), _, _],
|
||||
select( [ h(red,englishman,_,_,_), h(_,swede,dog,_,_),
|
||||
h(_,dane,_,tea,_), h(_,german,_,_,prince) ], HS),
|
||||
select( [ h(_,_,birds,_,pallmall), h(yellow,_,_,_,dunhill),
|
||||
h(_,_,_,beer,bluemaster) ], HS),
|
||||
left_of( h(green,_,_,coffee,_), h(white,_,_,_,_), HS),
|
||||
next_to( h(_,_,_,_,dunhill), h(_,_,horse,_,_), HS),
|
||||
next_to( h(_,_,_,_,blend), h(_,_,cats, _,_), HS),
|
||||
next_to( h(_,_,_,_,blend), h(_,_,_,water,_), HS),
|
||||
next_to( h(_,norwegian,_,_,_), h(blue,_,_,_,_), HS),
|
||||
member( h(_,Owns,zebra,_,_), HS).
|
||||
|
||||
:- ?- time(( zebra(Who, HS), maplist(writeln,HS), nl, write(Who), nl, nl, fail
|
||||
; write('No more solutions.') )).
|
||||
|
|
|
|||
|
|
@ -1,30 +1,28 @@
|
|||
% populate domain by selecting from it
|
||||
nation(H,V):- memberchk( nation(X), H), X=V. % select the "nation" attribute
|
||||
owns( H,V):- memberchk( owns( X), H), X=V. % ...
|
||||
smoke( H,V):- memberchk( smoke( X), H), X=V.
|
||||
color( H,V):- memberchk( color( X), H), X=V.
|
||||
drink( H,V):- memberchk( drink( X), H), X=V.
|
||||
|
||||
to_the_left(A,B,HS):- append(_,[A,B|_],HS).
|
||||
next_to(A,B,HS):- to_the_left(A,B,HS) ; to_the_left(B,A,HS).
|
||||
middle(A, [_,_,A,_,_]).
|
||||
first(A, [A|_]).
|
||||
attrs(H,[N-V|R]):- memberchk( N-X, H), X=V, % unique attribute names
|
||||
(R=[] -> true ; attrs(H,R)).
|
||||
one_of(HS,AS) :- member(H,HS), attrs(H,AS).
|
||||
two_of(HS,G,AS):- call(G,H1,H2,HS), maplist(attrs,[H1,H2],AS).
|
||||
left_of(A,B,HS):- append(_,[A,B|_],HS).
|
||||
next_to(A,B,HS):- left_of(A,B,HS) ; left_of(B,A,HS).
|
||||
|
||||
zebra(Zebra,Houses):-
|
||||
length(Houses,5),
|
||||
member(H2, Houses), nation(H2, englishman), color( H2, red),
|
||||
member(H3, Houses), nation(H3, swede), owns( H3, dog),
|
||||
member(H4, Houses), nation(H4, dane), drink( H4, tea),
|
||||
to_the_left(H5,H5b,Houses), color(H5, green), color(H5b, white),
|
||||
member(H6, Houses), drink( H6, coffee), color( H6, green),
|
||||
member(H7, Houses), smoke( H7, 'Pall Mall'), owns( H7, birds),
|
||||
member(H8, Houses), color( H8, yellow), smoke( H8, 'Dunhill'),
|
||||
middle(H9, Houses), drink( H9, milk),
|
||||
first(H10, Houses), nation(H10, norwegian),
|
||||
next_to(H11,H11b,Houses), smoke( H11, 'Blend'), owns( H11b, cats),
|
||||
next_to(H12,H12b,Houses), owns( H12, horse), smoke(H12b, 'Dunhill'),
|
||||
member(H13, Houses), drink( H13, beer), smoke( H13, 'Blue Master'),
|
||||
member(H14, Houses), nation(H14, german), smoke( H14, 'Prince'),
|
||||
next_to(H15,H15b,Houses), nation(H15, norwegian), color(H15b, blue),
|
||||
next_to(H16,H16b,Houses), drink( H16, water), smoke(H16b, 'Blend'),
|
||||
member(Zebra,Houses), owns(Zebra, zebra).
|
||||
Houses = [A,_,C,_,_], % 1
|
||||
maplist( one_of(Houses), [ [ nation-englishman, color-red ] % 2
|
||||
, [ nation-swede, owns -dog ] % 3
|
||||
, [ nation-dane, drink-tea ] % 4
|
||||
, [ drink -coffee, color-green ] % 6
|
||||
, [ smoke -'Pall Mall', owns -birds ] % 7
|
||||
, [ color -yellow, smoke-'Dunhill' ] % 8
|
||||
, [ drink -beer, smoke-'Blue Master'] % 13
|
||||
, [ nation-german, smoke-'Prince' ] % 14
|
||||
] ),
|
||||
two_of(Houses, left_of, [[color -green ], [color -white ]]), % 5
|
||||
maplist(attrs, [C,A], [[drink -milk ], [nation-norwegian]]), % 9, 10
|
||||
maplist(two_of(Houses,next_to),
|
||||
[ [[smoke -'Blend' ], [owns -cats ]] % 11
|
||||
, [[owns -horse ], [smoke-'Dunhill' ]] % 12
|
||||
, [[nation-norwegian], [color-blue ]] % 15
|
||||
, [[drink -water ], [smoke-'Blend' ]] % 16
|
||||
] ),
|
||||
one_of(Houses, [ owns-zebra, nation-Zebra]).
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
?- time(( zebra(Z,HS), ( maplist(length,HS,_) -> maplist(sort,HS,S),
|
||||
maplist(writeln,S),nation(Z,R),nl,writeln(R) ), false ; true)).
|
||||
maplist(writeln,S),nl,writeln(Z) ), false ; true)).
|
||||
|
||||
[color(yellow),drink(water), nation(norwegian), owns(cats), smoke(Dunhill) ]
|
||||
[color(blue), drink(tea), nation(dane), owns(horse), smoke(Blend) ]
|
||||
[color(red), drink(milk), nation(englishman),owns(birds), smoke(Pall Mall) ]
|
||||
[color(green), drink(coffee),nation(german), owns(zebra), smoke(Prince) ]
|
||||
[color(white), drink(beer), nation(swede), owns(dog), smoke(Blue Master)]
|
||||
[color-yellow,drink-water, nation-norwegian, owns-cats, smoke-Dunhill ]
|
||||
[color-blue, drink-tea, nation-dane, owns-horse, smoke-Blend ]
|
||||
[color-red, drink-milk, nation-englishman,owns-birds, smoke-Pall Mall ]
|
||||
[color-green, drink-coffee,nation-german, owns-zebra, smoke-Prince ]
|
||||
[color-white, drink-beer, nation-swede, owns-dog, smoke-Blue Master]
|
||||
|
||||
german
|
||||
% 138,899 inferences, 0.060 CPU in 0.110 seconds (55% CPU, 2311655 Lips)
|
||||
% 234,852 inferences, 0.100 CPU in 0.170 seconds (59% CPU, 2345143 Lips)
|
||||
true.
|
||||
|
|
|
|||
45
Task/Zebra-puzzle/Prolog/zebra-puzzle-4.pro
Normal file
45
Task/Zebra-puzzle/Prolog/zebra-puzzle-4.pro
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
:- initialization(main).
|
||||
|
||||
|
||||
zebra(X) :-
|
||||
houses(Hs), member(h(_,X,zebra,_,_), Hs)
|
||||
, findall(_, (member(H,Hs), write(H), nl), _), nl
|
||||
, write('the one who keeps zebra: '), write(X), nl
|
||||
.
|
||||
|
||||
|
||||
houses(Hs) :-
|
||||
Hs = [_,_,_,_,_] % 1
|
||||
, H3 = h(_,_,_,milk,_), Hs = [_,_,H3,_,_] % 9
|
||||
, H1 = h(_,nvg,_,_,_ ), Hs = [H1|_] % 10
|
||||
|
||||
, maplist( flip(member,Hs),
|
||||
[ h(red,eng,_,_,_) % 2
|
||||
, h(_,swe,dog,_,_) % 3
|
||||
, h(_,dan,_,tea,_) % 4
|
||||
, h(green,_,_,coffe,_) % 6
|
||||
, h(_,_,birds,_,pm) % 7
|
||||
, h(yellow,_,_,_,dh) % 8
|
||||
, h(_,_,_,beer,bm) % 13
|
||||
, h(_,ger,_,_,pri) % 14
|
||||
])
|
||||
|
||||
, infix([ h(green,_,_,_,_)
|
||||
, h(white,_,_,_,_) ], Hs) % 5
|
||||
|
||||
, maplist( flip(nextto,Hs),
|
||||
[ [h(_,_,_,_,bl ), h(_,_,cats,_,_)] % 11
|
||||
, [h(_,_,horse,_,_), h(_,_,_,_,dh )] % 12
|
||||
, [h(_,nvg,_,_,_ ), h(blue,_,_,_,_)] % 15
|
||||
, [h(_,_,_,water,_), h(_,_,_,_,bl )] % 16
|
||||
])
|
||||
.
|
||||
|
||||
|
||||
flip(F,X,Y) :- call(F,Y,X).
|
||||
|
||||
infix(Xs,Ys) :- append(Xs,_,Zs) , append(_,Zs,Ys).
|
||||
nextto(P,Xs) :- permutation(P,R), infix(R,Xs).
|
||||
|
||||
|
||||
main :- findall(_, (zebra(_), nl), _), halt.
|
||||
80
Task/Zebra-puzzle/R/zebra-puzzle.r
Normal file
80
Task/Zebra-puzzle/R/zebra-puzzle.r
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
library(combinat)
|
||||
|
||||
col <- factor(c("Red","Green","White","Yellow","Blue"))
|
||||
own <- factor(c("English","Swedish","Danish","German","Norwegian"))
|
||||
pet <- factor(c("Dog","Birds","Cats","Horse","Zebra"))
|
||||
drink <- factor(c("Coffee","Tea","Milk","Beer","Water"))
|
||||
smoke <- factor(c("PallMall", "Blend", "Dunhill", "BlueMaster", "Prince"))
|
||||
|
||||
col_p <- permn(levels(col))
|
||||
own_p <- permn(levels(own))
|
||||
pet_p <- permn(levels(pet))
|
||||
drink_p <- permn(levels(drink))
|
||||
smoke_p <- permn(levels(smoke))
|
||||
|
||||
imright <- function(h1,h2){
|
||||
return(h1-h2==1)
|
||||
}
|
||||
|
||||
nextto <- function(h1,h2){
|
||||
return(abs(h1-h2)==1)
|
||||
}
|
||||
|
||||
house_with <- function(f,val){
|
||||
return(which(levels(f)==val))
|
||||
}
|
||||
|
||||
for (i in seq(length(col_p))){
|
||||
col <- factor(col, levels=col_p[[i]])
|
||||
|
||||
if (imright(house_with(col,"Green"),house_with(col,"White"))) {
|
||||
for (j in seq(length(own_p))){
|
||||
own <- factor(own, levels=own_p[[j]])
|
||||
|
||||
if(house_with(own,"English") == house_with(col,"Red")){
|
||||
if(house_with(own,"Norwegian") == 1){
|
||||
if(nextto(house_with(own,"Norwegian"),house_with(col,"Blue"))){
|
||||
for(k in seq(length(drink_p))){
|
||||
drink <- factor(drink, levels=drink_p[[k]])
|
||||
|
||||
if(house_with(drink,"Coffee") == house_with(col,"Green")){
|
||||
if(house_with(own,"Danish") == house_with(drink,"Tea")){
|
||||
if(house_with(drink,"Milk") == 3){
|
||||
for(l in seq(length(smoke_p))){
|
||||
smoke <- factor(smoke, levels=smoke_p[[l]])
|
||||
|
||||
if(house_with(smoke,"Dunhill") == house_with(col,"Yellow")){
|
||||
if(house_with(smoke,"BlueMaster") == house_with(drink,"Beer")){
|
||||
if(house_with(own,"German") == house_with(smoke,"Prince")){
|
||||
if(nextto(house_with(smoke,"Blend"),house_with(drink,"Water"))){
|
||||
for(m in seq(length(pet_p))){
|
||||
pet <- factor(pet, levels=pet_p[[m]])
|
||||
|
||||
if(house_with(own,"Swedish") == house_with(pet,"Dog")){
|
||||
if(house_with(smoke,"PallMall") == house_with(pet,"Birds")){
|
||||
if(nextto(house_with(smoke,"Blend"),house_with(pet,"Cats"))){
|
||||
if(nextto(house_with(smoke,"Dunhill"),house_with(pet,"Horse"))){
|
||||
res <- sapply(list(own,col,pet,smoke,drink),levels)
|
||||
colnames(res) <- c("Nationality","Colour","Pet","Drink","Smoke")
|
||||
print(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
53
Task/Zebra-puzzle/Ruby/zebra-puzzle.rb
Normal file
53
Task/Zebra-puzzle/Ruby/zebra-puzzle.rb
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Solve Zebra Puzzle.
|
||||
#
|
||||
# Nigel_Galloway
|
||||
# August 31st., 2014.
|
||||
CONTENT = { :House => nil,
|
||||
:Nationality => [:English, :Swedish, :Danish, :Norwegian, :German],
|
||||
:Colour => [:Red, :Green, :White, :Blue, :Yellow],
|
||||
:Pet => [:Dog, :Birds, :Cats, :Horse, :Zebra],
|
||||
:Drink => [:Tea, :Coffee, :Milk, :Beer, :Water],
|
||||
:Smoke => [:PallMall, :Dunhill, :BlueMaster, :Prince, :Blend] }
|
||||
|
||||
def adjacent? (n,i,g,e)
|
||||
(0..3).any?{|x| (n[x]==i and g[x+1]==e) or (n[x+1]==i and g[x]==e)}
|
||||
end
|
||||
|
||||
def leftof? (n,i,g,e)
|
||||
(0..3).any?{|x| n[x]==i and g[x+1]==e}
|
||||
end
|
||||
|
||||
def coincident? (n,i,g,e)
|
||||
n.each_index.any?{|x| n[x]==i and g[x]==e}
|
||||
end
|
||||
|
||||
def solve
|
||||
CONTENT[:Nationality].permutation{|nation|
|
||||
next if nation.first != :Norwegian # 10
|
||||
CONTENT[:Colour].permutation{|colour|
|
||||
next unless leftof?(colour,:Green,colour,:White) # 5
|
||||
next unless coincident?(nation,:English,colour,:Red) # 2
|
||||
next unless adjacent?(nation,:Norwegian,colour,:Blue) # 15
|
||||
CONTENT[:Pet].permutation{|pet|
|
||||
next unless coincident?(nation,:Swedish,pet,:Dog) # 3
|
||||
CONTENT[:Drink].permutation{|drink|
|
||||
next if drink[2] != :Milk # 9
|
||||
next unless coincident?(nation,:Danish,drink,:Tea) # 4
|
||||
next unless coincident?(colour,:Green,drink,:Coffee) # 6
|
||||
CONTENT[:Smoke].permutation{|smoke|
|
||||
next unless coincident?(smoke,:PallMall,pet,:Birds) # 7
|
||||
next unless coincident?(smoke,:Dunhill,colour,:Yellow) # 8
|
||||
next unless coincident?(smoke,:BlueMaster,drink,:Beer) # 13
|
||||
next unless coincident?(smoke,:Prince,nation,:German) # 14
|
||||
next unless adjacent?(smoke,:Blend,pet,:Cats) # 11
|
||||
next unless adjacent?(smoke,:Blend,drink,:Water) # 16
|
||||
next unless adjacent?(smoke,:Dunhill,pet,:Horse) # 12
|
||||
return [nation,colour,pet,drink,smoke]
|
||||
} } } } }
|
||||
end
|
||||
res = solve
|
||||
width = CONTENT.map{|x| x.flatten.map{|y|y.to_s.size}.max}
|
||||
fmt = width.map{|w| "%-#{w}s"}.join(" ")
|
||||
puts "The Zebra is owned by the man who is #{res[0][res[2].find_index(:Zebra)]}",""
|
||||
puts fmt % CONTENT.keys, fmt % width.map{|w| "-"*w}
|
||||
res.transpose.each.with_index(1){|x,n| puts fmt % [n,*x]}
|
||||
76
Task/Zebra-puzzle/Scala/zebra-puzzle.scala
Normal file
76
Task/Zebra-puzzle/Scala/zebra-puzzle.scala
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/* Note to the rules:
|
||||
*
|
||||
* It can further concluded that:
|
||||
* 5a: The green house cannot be at the h1 position
|
||||
* 5b: The white house cannot be at the h5 position
|
||||
*
|
||||
* 16: This rule is redundant.
|
||||
*/
|
||||
|
||||
object Einstein extends App {
|
||||
class House(val nationality: String, val color: String, val beverage: String, val animal: String, val brand: String) {
|
||||
override def toString = { f"$nationality%10s, ${color + ", "}%-8s$beverage,\t$animal,\t$brand." }
|
||||
|
||||
def totalUnEqual(home2: House) =
|
||||
this.animal != home2.animal &&
|
||||
this.beverage != home2.beverage &&
|
||||
this.brand != home2.brand &&
|
||||
this.color != home2.color &&
|
||||
this.nationality != home2.nationality
|
||||
|
||||
//** Checks if the this green house is next to the other white house*/
|
||||
def checkAdjacentWhite(home2: House) = (this.color == "Green") == (home2.color == "White") // #5
|
||||
}
|
||||
|
||||
val possibleMembers = for { // pair clues results in 78 members
|
||||
nationality <- List("Norweigan", "German", "Dane", "Englishman", "Swede")
|
||||
color <- List("Red", "Green", "Yellow", "White", "Blue")
|
||||
beverage <- List("Milk", "Coffee", "Tea", "Beer", "Water")
|
||||
animal <- List("Dog", "Horse", "Birds", "Cats", "Zebra")
|
||||
brand <- List("Blend", "Pall Mall", "Prince", "Blue Master", "Dunhill")
|
||||
if (color == "Red") == (nationality == "Englishman") // #2
|
||||
if (nationality == "Swede") == (animal == "Dog") // #3
|
||||
if (nationality == "Dane") == (beverage == "Tea") // #4
|
||||
if (color == "Green") == (beverage == "Coffee") // #6
|
||||
if (brand == "Pall Mall") == (animal == "Birds") // #7
|
||||
if (brand == "Dunhill") == (color == "Yellow") // #8
|
||||
if (brand == "Blue Master") == (beverage == "Beer") // #13
|
||||
if (brand == "Prince") == (nationality == "German") // #14
|
||||
} yield new House(nationality, color, beverage, animal, brand)
|
||||
|
||||
def matchMiddleBrandAnimal(home1: House, home2: House, home3: House, brand: String, animal: String) =
|
||||
(home1.animal == animal || home2.brand != brand || home3.animal == animal) &&
|
||||
(home1.brand == brand || home2.animal != animal || home3.brand == brand)
|
||||
|
||||
def matchCornerBrandAnimal(corner: House, inner: House, animal: String, brand: String) =
|
||||
(corner.brand != brand || inner.animal == animal) && (corner.animal == animal || inner.brand != brand)
|
||||
|
||||
def housesLeftOver(pickedHouses: House*): List[House] = {
|
||||
possibleMembers.filter(house => pickedHouses.forall(_.totalUnEqual(house)))
|
||||
}
|
||||
|
||||
val members = for { // Neighborhood clues
|
||||
h1 <- housesLeftOver().filter(p => (p.nationality == "Norweigan" /* #10 */ ) && (p.color != "Green") /* #5a */ ) // 28
|
||||
h3 <- housesLeftOver(h1).filter(p => p.beverage == "Milk") // #9 // 24
|
||||
h2 <- housesLeftOver(h1, h3).filter(_.color == "Blue") // #15
|
||||
if matchMiddleBrandAnimal(h1, h2, h3, "Blend", "Cats") // #11
|
||||
if matchCornerBrandAnimal(h1, h2, "Horse", "Dunhill") // #12
|
||||
h4 <- housesLeftOver(h1, h2, h3).filter(_.checkAdjacentWhite(h3) /* #5 */ )
|
||||
h5 <- housesLeftOver(h1, h2, h3, h4)
|
||||
|
||||
// Redundant tests
|
||||
if h2.checkAdjacentWhite(h1)
|
||||
if h3.checkAdjacentWhite(h2)
|
||||
if matchCornerBrandAnimal(h5, h4, "Horse", "Dunhill")
|
||||
if matchMiddleBrandAnimal(h2, h3, h4, "Blend", "Cats")
|
||||
if matchMiddleBrandAnimal(h3, h4, h5, "Blend", "Cats")
|
||||
} yield Seq(h1, h2, h3, h4, h5)
|
||||
|
||||
// Main program
|
||||
val beest = "Zebra"
|
||||
members.flatMap(p => p.filter(p => p.animal == beest)).
|
||||
foreach(s => println(s"The ${s.nationality} is the owner of the ${beest.toLowerCase}."))
|
||||
|
||||
println(s"The ${members.size} solution(s) are:")
|
||||
members.foreach(solution => solution.zipWithIndex.foreach(h => println("House " + (h._2 + 1) + " " + h._1)))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue