Zebra puzzle: Difference between revisions

m
m (→‎{{header|Phix}}: use pygments, and indices to a single permute set)
(3 intermediate revisions by one other user not shown)
Line 4,219:
 
===Constraint Programming Version===
Using the rules from https://github.com/SWI-Prolog/bench/blob/master/programs/zebra.pl
<syntaxhighlight lang="julia"># Julia 1.4
using JuMP
Line 5,311:
<!--(phixonline)-->
<syntaxhighlight lang="phix">
--enum colour, nationality, drink, smoke, pet -- (now implicit)
enum red,white,green,yellow,blue
enum English,Swede,Dane,Norwegian,German
Line 5,327:
constant p5 = permutes(tagset(5)), -- all permutes of {1,2,3,4,5},
lp = length(p5) -- (== factorial(5), ie 120)
sequence perm = repeat(0,5) -- variable indices to above
// 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)
sequenceinteger p1h = find(v1,p5[perm[c1]],)
return h<=4 p2 =and p5[perm[c2][h+1]=v2
for i=1 to 4 do
if p1[i]=v1 and p2[i+1]=v2 then
return true
end if
end for
return false
end function
 
function same_house(integer c1, v1, c2, v2)
sequenceinteger p1h = find(v1,p5[perm[c1]],)
p2 =return p5[perm[c2][h]=v2
for i=1 to 5 do
if p1[i]=v1 and p2[i]=v2 then
return true
end if
end for
return false
end function
function next_to(integer c1, v1, c2, v2)
sequenceinteger p1h1 = find(v1,p5[perm[c1]]),
p2h2 = find(v2,p5[perm[c2]])
forreturn iabs(h1-h2)=1 to 4 do
if (p1[i]=v1 and p2[i+1]=v2) or
(p1[i+1]=v1 and p2[i]=v2) then
return true
end if
end for
return false
end function
procedure print_house(integer n, sequence perm)
sequence args = {n}
for i,p in perm do
Line 5,371 ⟶ 5,358:
end procedure
integer ns = length(solperms)0
sequence solperms = {}
atom t0 = time()
for ccolour=1 to lp do
perm[colour] = c
if left_of(colour,green,colour,white) then
for nnationality=1 to lp do
permif p5[nationality] [1]=Norwegian -- Norwegian lives in 1st nhouse
if p5[n][1]=Norwegian -- Norwegian lives in 1st house
and same_house(nationality,English,colour,red)
and next_to(nationality,Norwegian,colour,blue) then
for ddrink=1 to lp do
perm[drink] = d
if same_house(nationality,Dane,drink,tea)
and same_house(drink,coffee,colour,green)
and p5[ddrink][3]=milk then -- middle house drinks milk
for ssmoke=1 to lp do
perm[smoke] = s
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 ppet=1 to lp do
perm[pet] = p
if same_house(nationality,Swede,pet,dog)
and same_house(smoke,PallMall,pet,birds)
Line 5,399 ⟶ 5,381:
and next_to(pet,horse,smoke,Dunhill) then
for i=1 to 5 do
print_house(i,{colour,nationality,drink,smoke,pet})
end for
solpermsinteger z = appendp5[nationality][find(solpermszebra,deep_copy(perm)p5[pet])]
printf(1,"The %s owns the Zebra\n",{nationalities[nationz]})
perm[smoke] ns += s1
end if
end for
Line 5,412 ⟶ 5,396:
end if
end for
integer ns = length(solperms)
printf(1,"%d solution%s found (%3.3fs).\n",{ns,iff(ns>1,"s",""),time()-t0})
for p in solperms do
integer house = find(zebra,p5[p[pet]]),
nation = p5[p[nationality]][house]
printf(1,"The %s owns the Zebra\n",{nationalities[nation]})
end for
</syntaxhighlight>
{{out}}
Line 5,427 ⟶ 5,405:
House 4: green German coffee Prince zebra
House 5: white Swede beer Blue Master dog
1 solution found (0.000s).
The German owns the Zebra
1 solution found (0.000s).
</pre>
 
1

edit