86 lines
3.6 KiB
Text
86 lines
3.6 KiB
Text
--enum colour, nationality, drink, smoke, pet -- (now implicit)
|
|
enum red,white,green,yellow,blue
|
|
enum English,Swede,Dane,Norwegian,German
|
|
enum tea,coffee,milk,beer,water
|
|
enum PallMall,Dunhill,Blend,BlueMaster,Prince
|
|
enum dog,birds,cats,horse,zebra
|
|
|
|
constant colours = {"red","white","green","yellow","blue"},
|
|
nationalities = {"English","Swede","Dane","Norwegian","German"},
|
|
drinks = {"tea","coffee","milk","beer","water"},
|
|
smokes = {"Pall Mall","Dunhill","Blend","Blue Master","Prince"},
|
|
pets = {"dog","birds","cats","horse","zebra"},
|
|
sets = {colours,nationalities,drinks,smokes,pets}
|
|
|
|
constant p5 = permutes(tagset(5)), -- all permutes of {1,2,3,4,5},
|
|
lp = length(p5) -- (== factorial(5), ie 120)
|
|
|
|
// In the following, c1,c2 are indexes to p5, for colour..pet,
|
|
// and v1,v2 are from their corresponding enums, so eg p5[c1]
|
|
// might be {1,4,3,2,5} for the colours of 1..5 and finding
|
|
// v1 in that gives us a house number. Checking the specified
|
|
// condition, eg [h] == green && [h+1] == white is then easy.
|
|
|
|
function left_of(integer c1, v1, c2, v2)
|
|
integer h = find(v1,p5[c1])
|
|
return h<=4 and p5[c2][h+1]=v2
|
|
end function
|
|
|
|
function same_house(integer c1, v1, c2, v2)
|
|
integer h = find(v1,p5[c1])
|
|
return p5[c2][h]=v2
|
|
end function
|
|
|
|
function next_to(integer c1, v1, c2, v2)
|
|
integer h1 = find(v1,p5[c1]),
|
|
h2 = find(v2,p5[c2])
|
|
return abs(h1-h2)=1
|
|
end function
|
|
|
|
procedure print_house(integer n, sequence perm)
|
|
sequence args = {n}
|
|
for i,p in perm do
|
|
args = append(args,sets[i][p5[p][n]])
|
|
end for
|
|
printf(1,"House %d: %|7s %|10s %|6s %|12s %=6s\n",args)
|
|
end procedure
|
|
|
|
integer ns = 0
|
|
atom t0 = time()
|
|
for colour=1 to lp do
|
|
if left_of(colour,green,colour,white) then
|
|
for nationality=1 to lp do
|
|
if p5[nationality][1]=Norwegian -- Norwegian lives in 1st house
|
|
and same_house(nationality,English,colour,red)
|
|
and next_to(nationality,Norwegian,colour,blue) then
|
|
for drink=1 to lp do
|
|
if same_house(nationality,Dane,drink,tea)
|
|
and same_house(drink,coffee,colour,green)
|
|
and p5[drink][3]=milk then -- middle house drinks milk
|
|
for smoke=1 to lp do
|
|
if same_house(colour,yellow,smoke,Dunhill)
|
|
and same_house(nationality,German,smoke,Prince)
|
|
and same_house(smoke,BlueMaster,drink,beer)
|
|
and next_to(drink,water,smoke,Blend) then
|
|
for pet=1 to lp do
|
|
if same_house(nationality,Swede,pet,dog)
|
|
and same_house(smoke,PallMall,pet,birds)
|
|
and next_to(smoke,Blend,pet,cats)
|
|
and next_to(pet,horse,smoke,Dunhill) then
|
|
for i=1 to 5 do
|
|
print_house(i,{colour,nationality,drink,smoke,pet})
|
|
end for
|
|
integer z = p5[nationality][find(zebra,p5[pet])]
|
|
printf(1,"The %s owns the Zebra\n",{nationalities[z]})
|
|
ns += 1
|
|
end if
|
|
end for
|
|
end if
|
|
end for
|
|
end if
|
|
end for
|
|
end if
|
|
end for
|
|
end if
|
|
end for
|
|
printf(1,"%d solution%s found (%3.3fs).\n",{ns,iff(ns>1,"s",""),time()-t0})
|