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

@ -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;
}
}

View file

@ -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;
}

View 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]);
}