RosettaCodeData/Task/Zebra-puzzle/FutureBasic/zebra-puzzle.basic
2025-08-11 18:05:26 -07:00

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
//