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