266 lines
7.9 KiB
Text
266 lines
7.9 KiB
Text
/*
|
|
|
|
Z E B R A P U Z Z L E
|
|
Based on Phix logic
|
|
FutureBasic 7.0.34, August 2025 R.W.
|
|
|
|
*/
|
|
|
|
/*--------------------------------------------------------------------
|
|
There are five houses...
|
|
----------------------------------------------------------------------
|
|
// The green house is immediately to the left of the white house
|
|
// The Norwegian lives in the first house
|
|
// The English man lives in the red house
|
|
// The Norwegian lives next to the blue house
|
|
// The Dane drinks tea
|
|
// They drink coffee in the green house
|
|
// In the middle house they drink milk
|
|
// In the yellow house they smoke Dunhill
|
|
// The German smokes Prince
|
|
// The man who smokes Blue Master drinks beer
|
|
// They drink water in a house next to the house where they smoke Blend
|
|
// The Swede has a dog
|
|
// The man who smokes Pall Mall has birds
|
|
// The man who smokes Blend lives in the house next to the house with cats
|
|
// In a house next to the house where they have a horse,
|
|
// they smoke Dunhill
|
|
//
|
|
// Task: Who owns the zebra?
|
|
*/
|
|
// Enumerate based on the data given
|
|
// in the puzzle (5 variables for each group)
|
|
|
|
Begin Enum 1 // drinks
|
|
_tea
|
|
_coffee
|
|
_milk
|
|
_beer
|
|
_water
|
|
End Enum
|
|
|
|
Begin Enum 1 // nationalities
|
|
_English
|
|
_Swede
|
|
_Dane
|
|
_Norwegian
|
|
_German
|
|
End Enum
|
|
|
|
Begin Enum 1 // house colors
|
|
_red
|
|
_white
|
|
_green
|
|
_yellow
|
|
_blue
|
|
End Enum
|
|
|
|
Begin Enum 1 // smokes
|
|
_PallMall
|
|
_Dunhill
|
|
_Blend
|
|
_BlueMaster
|
|
_Prince
|
|
End Enum
|
|
|
|
Begin Enum 1 // animals
|
|
_dog
|
|
_birds
|
|
_cats
|
|
_horse
|
|
_zebra
|
|
End Enum
|
|
|
|
// Since we have 5 variables, the total permutation/combo
|
|
// would be 5! (5 factorial) which is 120
|
|
|
|
Int gPermutation(120, 5) // 120 combinations
|
|
Int gNumbers(5) // of 1 to 5
|
|
Int gPermCount
|
|
Int factorial5 = 120 // value of 5!
|
|
Int entry, ns, ic
|
|
Int color, nationality, drink, smoke, pet // 5 groups
|
|
|
|
// Since we used assigned numbers, we need this to
|
|
// show the equivalent description
|
|
|
|
CFStringRef Colors(5) = {@"Houses",@"red",@"white",¬
|
|
@"green",@"yellow",@"blue"}
|
|
CFStringRef Nationalities(5) = {@"Nationalities",@"English",@"Swede",¬
|
|
@"Dane",@"Norwegian",@"German"}
|
|
CFStringRef Smokes(5) = {@"Smokes",@"Pall Mall",@"Dunhill",¬
|
|
@"Blend",@"Blue Master",@"Prince"}
|
|
CFStringRef Drinks(5) = {@"Drinks",@"tea",@"coffee",¬
|
|
@"milk",@"beer",@"water"}
|
|
CFStringRef Pets(5) = {@"Animals",@"dog",@"birds",¬
|
|
@"cats",@"horse",@"zebra"}
|
|
|
|
// Recursive permutation generator
|
|
local fn Permute( l as int, r as int )
|
|
dim i as int
|
|
if l = r
|
|
for i = 1 to 5
|
|
gPermutation(gPermCount, i) = gNumbers(i)
|
|
next
|
|
gPermCount++
|
|
else
|
|
for i = l to r
|
|
swap gNumbers(l), gNumbers(i)
|
|
fn Permute( l + 1, r )
|
|
swap gNumbers(l), gNumbers(i)
|
|
next
|
|
end if
|
|
end fn
|
|
|
|
//
|
|
// Fill arrays of 5! permutations of 1 to 5
|
|
local fn generatePermutations
|
|
int i
|
|
for i = 1 to 5: gNumbers(i) = i: next i
|
|
gPermCount = 1
|
|
fn Permute( 1, 5 ) // Use 1-based index range
|
|
end fn
|
|
|
|
//
|
|
// Pad spaces to width of "padTo" for output formatting
|
|
Local fn Pad(theString as CFStringRef, padTo as Int) as CFStringRef
|
|
theString = fn StringByReplacingOccurrencesOfString (theString, @"\"", @"" )
|
|
if len(theString) < padTo then theString ¬
|
|
= left( concat( theString, @" "), padTo )
|
|
print theString;
|
|
end fn = theString
|
|
|
|
// Find an entry in the permutation table
|
|
// c1 = index into gPermutation array
|
|
// v1 = the seek value
|
|
local fn find(c1 as Int, v1 as Int) as Int
|
|
Int h, i
|
|
h = 0
|
|
for i = 1 to 5
|
|
if gPermutation(c1,i) == v1 then h = i: i = 6:
|
|
next i
|
|
end fn = h
|
|
|
|
//
|
|
// Left (as seen from the front) to location logic
|
|
local fn left_of(c1 as Int, v1 as Int, c2 as Int, v2 as Int) as Int
|
|
Int h, result
|
|
h = fn find(c1,v1)
|
|
result = (h <=4) && (gPermutation(c2,h + 1) == v2)
|
|
end fn = result
|
|
|
|
//
|
|
// Is in the same house logic
|
|
local fn same_house(c1 as Int, v1 as Int, c2 as Int, v2 as Int) as Int
|
|
Int h, result
|
|
h = fn find(c1, v1)
|
|
result = (gPermutation(c2,h) == v2)
|
|
end fn = result
|
|
|
|
//
|
|
// located next to logic
|
|
local fn next_to(c1 as Int, v1 as Int, c2 as Int, v2 as Int) as Int
|
|
Int h1, h2, result
|
|
h1 = fn find(c1, v1): h2 = fn find(c2, v2)
|
|
result = abs(h1-h2) == 1
|
|
end fn = result
|
|
|
|
//================================================================
|
|
// Main
|
|
|
|
window 1,@"Zebra puzzle"
|
|
|
|
Int i, j
|
|
fn generatePermutations
|
|
// start the clock
|
|
CFTimeInterval t
|
|
t = fn CACurrentMediaTime
|
|
print
|
|
|
|
for Color = 1 to factorial5
|
|
ic++
|
|
// The green house is immediately to the left of the white house
|
|
if fn left_of (Color, _green, Color, _white)
|
|
|
|
for Nationality = 1 to factorial5
|
|
ic++
|
|
// The Norwegian lives in the first house and
|
|
// The English man lives in the red house and
|
|
// The Norwegian lives next to the blue house.
|
|
if gPermutation (Nationality,1) == _Norwegian && ¬
|
|
fn same_house (Nationality, _English, Color, _red) && ¬
|
|
fn next_to (Nationality, _Norwegian,Color, _blue)
|
|
|
|
for drink = 1 to factorial5
|
|
ic++
|
|
// The Dane drinks tea and
|
|
// They drink coffee in the green house and
|
|
// In the middle house they drink milk
|
|
if fn same_house (Nationality, _Dane,drink, _tea) && ¬
|
|
fn same_house (drink, _coffee, Color, _green) && ¬
|
|
gPermutation (drink, 3) == _milk
|
|
|
|
for smoke = 1 to factorial5
|
|
ic++
|
|
// In the yellow house they smoke Dunhill and
|
|
// The German smokes Prince and
|
|
// The man who smokes Blue Master drinks beer and
|
|
// They drink water in a house next to the house
|
|
// where they smoke Blend
|
|
if fn same_house (Color, _yellow, smoke, _Dunhill) && ¬
|
|
fn same_house (Nationality, _German, smoke, _Prince) && ¬
|
|
fn same_house (smoke, _BlueMaster, drink, _beer) && ¬
|
|
fn next_to (drink, _water, smoke, _Blend)
|
|
|
|
for pet = 1 to factorial5
|
|
ic++
|
|
// The Swede has a dog and
|
|
// The man who smokes Pall Mall has birds and
|
|
// The man who smokes Blend lives in the house next
|
|
// to the house with cats and
|
|
// In a house next to the house where they have a horse,
|
|
// they smoke Dunhill
|
|
if fn same_house (Nationality, _Swede, pet, _dog) && ¬
|
|
fn same_house (smoke,_PallMall, pet, _birds) && ¬
|
|
fn next_to (smoke,_Blend, pet, _cats) && ¬
|
|
fn next_to (pet,_horse,smoke,_Dunhill)
|
|
|
|
// stop the clock
|
|
printf @" Solved in = %.4f seconds", ¬
|
|
(fn CACurrentMediaTime-t)
|
|
print
|
|
// Show the results
|
|
fn pad (@" HOUSE",11): fn pad (@"PERSON",11)
|
|
fn pad (@"DRINKS",8): fn pad (@"SMOKES",13)
|
|
fn pad (@"HAS",6)
|
|
print
|
|
print " ==============================================="
|
|
for i=1 to 5
|
|
print " ";i;" ";
|
|
fn pad (Colors(gPermutation(color,i)),8)
|
|
fn pad (Nationalities(gPermutation(Nationality,i)),11)
|
|
fn pad (Drinks(gPermutation(drink,i)),8)
|
|
fn pad (Smokes(gPermutation(smoke,i)),13)
|
|
fn pad (Pets(gPermutation(pet,i)),8): print
|
|
if i == 5 then entry = i
|
|
next i
|
|
print
|
|
print " The ";Nationalities(entry);" owns the zebra."
|
|
ns += 1: print
|
|
print " ";ic;" combinations tested before finding a solution"
|
|
print " Solution found = ";ns;
|
|
if ns < 2 then print " (unique)"
|
|
end if //5
|
|
next pet
|
|
end if //4
|
|
next smoke
|
|
end if //3
|
|
next drink
|
|
end if //2
|
|
next nationality
|
|
end if //1
|
|
next color
|
|
//
|
|
handleEvents
|
|
|
|
//
|