June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -0,0 +1,140 @@
BEGIN
# attempt to solve Einstein's Riddle - the Zebra puzzle #
INT unknown = 0, same = -1;
INT english = 1, swede = 2, dane = 3, norwegian = 4, german = 5;
INT dog = 1, birds = 2, cats = 3, horse = 4, zebra = 5;
INT red = 1, green = 2, white = 3, yellow = 4, blue = 5;
INT tea = 1, coffee = 2, milk = 3, beer = 4, water = 5;
INT pall mall = 1, dunhill = 2, blend = 3, blue master = 4, prince = 5;
[]STRING nationality = ( "unknown", "english", "swede", "dane", "norwegian", "german" );
[]STRING animal = ( "unknown", "dog", "birds", "cats", "horse", "ZEBRA" );
[]STRING colour = ( "unknown", "red", "green", "white", "yellow", "blue" );
[]STRING drink = ( "unknown", "tea", "coffee", "milk", "beer", "water" );
[]STRING smoke = ( "unknown", "pall mall", "dunhill", "blend", "blue master", "prince" );
MODE HOUSE = STRUCT( INT nationality, animal, colour, drink, smoke );
# returns TRUE if a field in a house could be set to value, FALSE otherwise #
PROC can set = ( INT field, INT value )BOOL: field = unknown OR value = same;
# returns TRUE if the fields of house h could be set to those of #
# suggestion s, FALSE otherwise #
OP XOR = ( HOUSE h, HOUSE s )BOOL:
( can set( nationality OF h, nationality OF s ) AND can set( animal OF h, animal OF s )
AND can set( colour OF h, colour OF s ) AND can set( drink OF h, drink OF s )
AND can set( smoke OF h, smoke OF s )
) # XOR # ;
# sets a field in a house to value if it is unknown #
PROC set = ( REF INT field, INT value )VOID: IF field = unknown AND value /= same THEN field := value FI;
# sets the unknown fields in house h to the non-same fields of suggestion s #
OP +:= = ( REF HOUSE h, HOUSE s )VOID:
( set( nationality OF h, nationality OF s ); set( animal OF h, animal OF s )
; set( colour OF h, colour OF s ); set( drink OF h, drink OF s )
; set( smoke OF h, smoke OF s )
) # +:= # ;
# sets a field in a house to unknown if the value is not same #
PROC reset = ( REF INT field, INT value )VOID: IF value /= same THEN field := unknown FI;
# sets fields in house h to unknown if the suggestion s is not same #
OP -:= = ( REF HOUSE h, HOUSE s )VOID:
( reset( nationality OF h, nationality OF s ); reset( animal OF h, animal OF s )
; reset( colour OF h, colour OF s ); reset( drink OF h, drink OF s )
; reset( smoke OF h, smoke OF s )
) # -:= # ;
# attempts a partial solution for the house at pos #
PROC try = ( INT pos, HOUSE suggestion, PROC VOID continue )VOID:
IF pos >= LWB house AND pos <= UPB house THEN
IF house[ pos ] XOR suggestion THEN
house[ pos ] +:= suggestion; continue; house[ pos ] -:= suggestion
FI
FI # try # ;
# attempts a partial solution for the neighbours of a house #
PROC left or right = ( INT pos, BOOL left, BOOL right, HOUSE neighbour suggestion
, PROC VOID continue )VOID:
( IF left THEN try( pos - 1, neighbour suggestion, continue ) FI
; IF right THEN try( pos + 1, neighbour suggestion, continue ) FI
) # left or right # ;
# attempts a partial solution for all houses and possibly their neighbours #
PROC any2 = ( REF INT number, HOUSE suggestion
, BOOL left, BOOL right, HOUSE neighbour suggestion
, PROC VOID continue )VOID:
FOR pos TO UPB house DO
IF house[ pos ] XOR suggestion THEN
number := pos;
house[ number ] +:= suggestion;
IF NOT left AND NOT right THEN # neighbours not involved #
continue
ELSE # try one or both neighbours #
left or right( pos, left, right, neighbour suggestion, continue )
FI;
house[ number ] -:= suggestion
FI
OD # any2 # ;
# attempts a partial solution for all houses #
PROC any = ( HOUSE suggestion, PROC VOID continue )VOID:
any2( LOC INT, suggestion, FALSE, FALSE, SKIP, continue );
# find solution(s) #
INT blend pos;
INT solutions := 0;
# There are five houses. #
[ 1 : 5 ]HOUSE house;
FOR h TO UPB house DO house[ h ] := ( unknown, unknown, unknown, unknown, unknown ) OD;
# In the middle house they drink milk. #
drink OF house[ 3 ] := milk;
# The Norwegian lives in the first house. #
nationality OF house[ 1 ] := norwegian;
# The Norwegian lives next to the blue house. #
colour OF house[ 2 ] := blue;
# They drink coffee in the green house. #
# The green house is immediately to the left of the white house. #
any2( LOC INT, ( same, same, green, coffee, same )
, FALSE, TRUE, ( same, same, white, same, same ), VOID:
# In a house next to the house where they have a horse, #
# they smoke Dunhill. #
# In the yellow house they smoke Dunhill. #
any2( LOC INT, ( same, horse, same, same, same )
, TRUE, TRUE, ( same, same, yellow, same, dunhill ), VOID:
# The English man lives in the red house. #
any( ( english, same, red, same, same ), VOID:
# The man who smokes Blend lives in the house next to the #
# house with cats. #
any2( blend pos, ( same, same, same, same, blend )
, TRUE, TRUE, ( same, cats, same, same, same ), VOID:
# They drink water in a house next to the house where #
# they smoke Blend. #
left or right( blend pos, TRUE, TRUE, ( same, same, same, water, same ), VOID:
# The Dane drinks tea. #
any( ( dane, same, same, tea, same ), VOID:
# The man who smokes Blue Master drinks beer. #
any( ( same, same, same, beer, blue master ), VOID:
# The Swede has a dog. #
any( ( swede, dog, same, same, same ), VOID:
# The German smokes Prince. #
any( ( german, same, same, same, prince ), VOID:
# The man who smokes Pall Mall has birds. #
any( ( same, birds, same, same, pall mall ), VOID:
# if we can place the zebra, we have a solution #
any( ( same, zebra, same, same, same ), VOID:
( solutions +:= 1;
FOR h TO UPB house DO
print( ( whole( h, 0 )
, " ", nationality[ 1 + nationality OF house[ h ] ]
, ", ", animal [ 1 + animal OF house[ h ] ]
, ", ", colour [ 1 + colour OF house[ h ] ]
, ", ", drink [ 1 + drink OF house[ h ] ]
, ", ", smoke [ 1 + smoke OF house[ h ] ]
, newline
)
)
OD;
print( ( newline ) )
)
) # zebra #
) # pall mall #
) # german #
) # swede #
) # beer #
) # dane #
) # blend L/R #
) # blend #
) # red #
) # horse #
) # green # ;
print( ( "solutions: ", whole( solutions, 0 ), newline ) )
END

View file

@ -0,0 +1,51 @@
function make(str, test = (_) -> true)
collect( filter(test, permutations(split(str))) )
end
men = make("danish english german norwegian swedish",
x -> "norwegian" == x[1])
drinks = make("beer coffee milk tea water", x -> "milk" == x[3])
colors = make("blue green red white yellow",
x -> 1 == findfirst(x, "white") - findfirst(x, "green"))
pets = make("birds cats dog horse zebra")
smokes = make("blend blue-master dunhill pall-mall prince")
function eq(x, xs, y, ys)
findfirst(xs, x) == findfirst(ys, y)
end
function adj(x, xs, y, ys)
1 == abs(findfirst(xs, x) - findfirst(ys, y))
end
for m = men, c = colors
if eq("red",c, "english",m) && adj("norwegian",m, "blue",c)
for d = drinks
if eq("danish",m, "tea",d) && eq("coffee",d,"green",c)
for s = smokes
if eq("yellow",c,"dunhill",s) &&
eq("blue-master",s,"beer",d) &&
eq("german",m,"prince",s)
for p = pets
if eq("birds",p,"pall-mall",s) &&
eq("swedish",m,"dog",p) &&
adj("blend",s,"cats",p) &&
adj("horse",p,"dunhill",s)
println("Zebra is owned by ", m[findfirst(p,"zebra")])
println("Houses:")
for line = mapslices(xs -> join( map(s->rpad(s,12), xs)),
[p m c d s], 2)
println(line)
end
end
end
end
end
end
end
end
end

View file

@ -0,0 +1,55 @@
remove is op x xs {filter (not (x =)) xs}
append_map is transformer func op seq { \
reduce (op x xs { (func x) link xs}) (seq append []) }
permutations is op seq { \
if empty seq then [[]] else \
(append_map \
(op head {each (op tail {head hitch tail}) \
(permutations (remove head seq))}) \
seq) \
endif}
f is find
tokenize is op str{string_split ' ' str}
mk is tr pred op str {filter pred permutations tokenize str}
eq is op x xs y ys{f x xs = f y ys}
adj is op x xs y ys{1 = abs(f x xs - f y ys)}
run is { \
men := mk (op xs {0 = f 'norwegian' xs}) \
'danish english german norwegian swedish'; \
colors := mk (op xs {1 = ((f 'white' xs) - (f 'green' xs))}) \
'blue green red white yellow'; \
drinks := mk (op xs {2 = f 'milk' xs}) 'beer coffee milk tea water'; \
pets := mk (op xs {l}) 'birds cats dog horse zebra'; \
smokes := mk (op xs {l}) 'blend blue-master dunhill pall-mall prince'; \
for m with men do \
for c with colors do \
if (eq 'english' m 'red' c) and \
(adj 'norwegian' m 'blue' c) then \
for d with drinks do \
if (eq 'danish' m 'tea' d) and \
(eq 'coffee' d 'green' c) then \
for s with smokes do \
if (eq 'yellow' c 'dunhill' s) and \
(eq 'blue-master' s 'beer' d) and \
(eq 'german' m 'prince' s) then \
for p with pets do \
if (eq 'birds' p 'pall-mall' s) and \
(eq 'swedish' m 'dog' p) and \
(adj 'blend' s 'cats' p) and \
(adj 'horse' p 'dunhill' s) then \
write (0 blend (p m c d s)) \
endif \
endfor \
endif \
endfor \
endif \
endfor \
endif \
endfor \
endfor }
abs(time - (run; time))

View file

@ -1,9 +1,8 @@
/* REXX ---------------------------------------------------------------
* Solve the Zebra Puzzle
*--------------------------------------------------------------------*/
oid='zebra.txt'; 'erase' oid
Call mk_perm /* compute all permutations */
Call encode /* encode the elements of the specifucations */
Call encode /* encode the elements of the specifications */
/* ex2 .. eg16 the formalized specifications */
solutions=0
Call time 'R'
@ -42,7 +41,7 @@
||left(animal.ai,11)
Call out ol.i
End
solutions+=1
solutions=solutions+1
End
End /* animal_i */
End
@ -50,7 +49,7 @@
End
End /* drink_i */
End
End /* colr_i */
End /* color_i */
End
End /* nation_i */
Say 'Number of solutions =' solutions
@ -167,4 +166,4 @@ encode:
out:
Say arg(1)
Return lineout(oid,arg(1))
Return

View file

@ -0,0 +1,24 @@
class String; def brk; split(/(?=[A-Z])/); end; end
men,drinks,colors,pets,smokes = "NorwegianGermanDaneSwedeEnglish
MilkTeaBeerWaterCoffeeGreenWhiteRedYellowBlueZebraDogCatsHorseBirds
PallmallDunhillBlendBluemasterPrince".delete(" \n").
brk.each_slice(5).map{|e| e.permutation.to_a};
men.select!{|x| "Norwegian"==x[0]};
drinks.select!{|x| "Milk"==x[2]};
colors.select!{|x| x.join[/GreenWhite/]};
dis = proc{|s,*a| s.brk.map{|w| a.map{|p| p.index(w)}.
compact[0]}.each_slice(2).map{|a,b| (a-b).abs}}
men.each{|m| colors.each{|c|
next unless dis["RedEnglishBlueNorwegian",c,m]==[0,1]
drinks.each{|d| next unless dis["DaneTeaCoffeeGreen",m,d,c]==[0,0]
smokes.each{|s|
next unless dis["YellowDunhillBluemasterBeerGermanPrince",
c,s,d,m]==[0,0,0]
pets.each{|p|
next unless dis["SwedeDogBirdsPallmallCatsBlendHorseDunhill",
m,p,s]==[0,0,1,1]
x = [p,m,c,d,s].transpose
puts "The #{x.find{|y|y[0]=="Zebra"}[1]} owns the zebra.",
x.map{|y| y.map{|z| z.ljust(11)}.join}}}}}}

View file

@ -8,22 +8,8 @@
*/
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")
nationality <- List("Norwegian", "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")
@ -37,6 +23,22 @@ object Einstein extends App {
if (brand == "Blue Master") == (beverage == "Beer") // #13
if (brand == "Prince") == (nationality == "German") // #14
} yield new House(nationality, color, beverage, animal, brand)
val members = for { // Neighborhood clues
h1 <- housesLeftOver().filter(p => (p.nationality == "Norwegia" /* #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)
def matchMiddleBrandAnimal(home1: House, home2: House, home3: House, brand: String, animal: String) =
(home1.animal == animal || home2.brand != brand || home3.animal == animal) &&
@ -49,28 +51,28 @@ object Einstein extends App {
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)
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."
}
// 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)
def totalUnEqual(home2: House) =
this.animal != home2.animal &&
this.beverage != home2.beverage &&
this.brand != home2.brand &&
this.color != home2.color &&
this.nationality != home2.nationality
// 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}."))
//** Checks if the this green house is next to the other white house*/
def checkAdjacentWhite(home2: House) = (this.color == "Green") == (home2.color == "White") // #5
}
println(s"The ${members.size} solution(s) are:")
members.foreach(solution => solution.zipWithIndex.foreach(h => println("House " + (h._2 + 1) + " " + h._1)))
}
{ // 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(s"House ${h._2 + 1} ${h._1}")))
}
} // loc 58

View file

@ -78,8 +78,7 @@ object Einstein extends App {
// print each row including a column header
((1 to 5).map(n => s"House $n") +: solution).map(_.map(pretty)).map(x => (pretty(labels.next) +: x).mkString(" ")).foreach(println)
println()
println(s"The ${solution(1)(solution(3).indexOf("Fish"))} owns the Fish")
println(s"\nThe ${solution(1)(solution(3).indexOf("Fish"))} owns the Fish")
}
}
}// loc 38