Zebra puzzle: Difference between revisions

m
m (→‎{{header|Phix}}: added syntax colouring the hard way)
(38 intermediate revisions by 17 users not shown)
Line 1:
[[File:zebra.png|525px||right]]
{{task|Puzzles}}
[[Category:CHR]]
Line 15:
:#   The green house is immediately to the left of the white house.
:#   They drink coffee in the green house.
:#   The man who smokes Pall Mall has birdsa bird.
:#   In the yellow house they smoke Dunhill.
:#   In the middle house they drink milk.
:#   The Norwegian lives in the first house.
:#   The man who smokes Blend-smoker lives in the house next to the house with catsa cat.
:#   In a house next to the house where they havewith a horse, they smoke Dunhill.
:#   The man who smokes Blue Master drinks beer.
:#   The German smokes Prince.
Line 26:
:#   They drink water in a house next to the house where they smoke Blend.
 
<br>The question is, who owns the zebra? For clarity, each of the five houses is painted a different color, and their inhabitants are of different nationalities, own different pets, drink different beverages and smoke different brands of cigarettes.
<br>The question is, who owns the zebra?
 
Additionally, list the solution for all the houses.
Line 39:
=={{header|Ada}}==
Not the prettiest Ada, but it's simple and very fast. Similar to my Dinesman's code; uses enums to keep things readable.
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO; use Ada.Text_IO;
procedure Zebra is
type Content is (Beer, Coffee, Milk, Tea, Water,
Line 144:
end loop; end loop;
Solve (myAlley, 0, 5); -- start at test 0 with 5 options
end Zebra;</langsyntaxhighlight>
{{out}}
<pre>ONE: DRINK=WATER PERSON=NORWEGIAN COLOR=YELLOW SMOKE=DUNHILL PET=CAT
Line 154:
=={{header|ALGOL 68}}==
Attempts to find solutions using the rules.
<langsyntaxhighlight lang="algol68">BEGIN
# attempt to solve Einstein's Riddle - the Zebra puzzle #
INT unknown = 0, same = -1;
Line 294:
print( ( "solutions: ", whole( solutions, 0 ), newline ) )
END
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 305:
solutions: 1
</pre>
 
=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">on zebraPuzzle()
-- From statement 10, the Norwegian lives in the first house,
-- so from statement 15, the blue house must be the second one.
-- From these and statements 5, 6, and 9, the green and white houses can only be the 4th & 5th,
-- and the Englishman's red house (statement 2) must be the middle one, where (9) they drink
-- milk. This only leaves the first house to claim the yellow colour and the Dunhill smokers
-- (statement 8), which means the second house must have the the horse (statement 12).
-- Initialise the house data accordingly.
set mv to missing value
set streetTemplate to {¬
{resident:"Norwegian", colour:"yellow", pet:mv, drink:mv, smoke:"Dunhill"}, ¬
{resident:mv, colour:"blue", pet:"horse", drink:mv, smoke:mv}, ¬
{resident:"Englishman", colour:"red", pet:mv, drink:"milk", smoke:mv}, ¬
{resident:mv, colour:"green", pet:mv, drink:"coffee", smoke:mv}, ¬
{resident:mv, colour:"white", pet:mv, drink:mv, smoke:mv} ¬
}
-- Test all permutations of the remaining values.
set solutions to {}
set drinkPermutations to {{"beer", "water"}, {"water", "beer"}}
set residentPermutations to {{"Swede", "Dane", "German"}, {"Swede", "German", "Dane"}, ¬
{"Dane", "German", "Swede"}, {"Dane", "Swede", "German"}, ¬
{"German", "Swede", "Dane"}, {"German", "Dane", "Swede"}}
set petPermutations to {{"birds", "cats", "ZEBRA"}, {"birds", "ZEBRA", "cats"}, ¬
{"cats", "ZEBRA", "birds"}, {"cats", "birds", "ZEBRA"}, ¬
{"ZEBRA", "birds", "cats"}, {"ZEBRA", "cats", "birds"}}
set smokePermutations to {{"Pall Mall", "Blend", "Blue Master"}, {"Pall Mall", "Blue Master", "Blend"}, ¬
{"Blend", "Blue Master", "Pall Mall"}, {"Blend", "Pall Mall", "Blue Master"}, ¬
{"Blue Master", "Pall Mall", "Blend"}, {"Blue Master", "Blend", "Pall Mall"}}
repeat with residentPerm in residentPermutations
-- Properties associated with resident.
copy streetTemplate to sTemplate2
set {r, OK} to {0, true}
repeat with h in {2, 4, 5} -- House numbers with unknown residents.
set thisHouse to sTemplate2's item h
set r to r + 1
set thisResident to residentPerm's item r
if (thisResident is "Swede") then
if (thisHouse's pet is not mv) then
set OK to false
exit repeat
end if
set thisHouse's pet to "dog"
else if (thisResident is "Dane") then
if (thisHouse's drink is not mv) then
set OK to false
exit repeat
end if
set thisHouse's drink to "tea"
else
set thisHouse's smoke to "Prince"
end if
set thisHouse's resident to thisResident
end repeat
-- Properties associated with cigarette brand.
if (OK) then
repeat with smokePerm in smokePermutations
-- Fit in this permutation of smokes.
copy sTemplate2 to sTemplate3
set s to 0
repeat with thisHouse in sTemplate3
if (thisHouse's smoke is mv) then
set s to s + 1
set thisHouse's smoke to smokePerm's item s
end if
end repeat
repeat with drinkPerm in drinkPermutations
-- Try to fit this permutation of drinks.
copy sTemplate3 to sTemplate4
set {d, OK} to {0, true}
repeat with h from 1 to 5
set thisHouse to sTemplate4's item h
if (thisHouse's drink is mv) then
set d to d + 1
set thisDrink to drinkPerm's item d
if (((thisDrink is "beer") and (thisHouse's smoke is not "Blue Master")) or ¬
((thisDrink is "water") and not ¬
(((h > 1) and (sTemplate4's item (h - 1)'s smoke is "Blend")) or ¬
((h < 5) and (sTemplate4's item (h + 1)'s smoke is "Blend"))))) then
set OK to false
exit repeat
end if
set thisHouse's drink to thisDrink
end if
end repeat
if (OK) then
repeat with petPerm in petPermutations
-- Try to fit this permutation of pets.
copy sTemplate4 to sTemplate5
set {p, OK} to {0, true}
repeat with h from 1 to 5
set thisHouse to sTemplate5's item h
if (thisHouse's pet is mv) then
set p to p + 1
set thisPet to petPerm's item p
if ((thisPet is "birds") and (thisHouse's smoke is not "Pall Mall")) or ¬
((thisPet is "cats") and not ¬
(((h > 1) and (sTemplate5's item (h - 1)'s smoke is "Blend")) or ¬
((h < 5) and (sTemplate5's item (h + 1)'s smoke is "Blend")))) then
set OK to false
exit repeat
end if
set thisHouse's pet to thisPet
end if
end repeat
if (OK) then set end of solutions to sTemplate5
end repeat
end if
end repeat
end repeat
end if
end repeat
set solutionCount to (count solutions)
set owners to {}
repeat with thisSolution in solutions
repeat with thisHouse in thisSolution
if (thisHouse's pet is "zebra") then
set owners's end to thisHouse's resident
exit repeat
end if
end repeat
end repeat
return {zebraOwners:owners, numberOfSolutions:solutionCount, solutions:solutions}
end zebraPuzzle
 
zebraPuzzle()</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">{zebraOwners:{"German"}, numberOfSolutions:1, solutions:{{{resident:"Norwegian", colour:"yellow", pet:"cats", drink:"water", smoke:"Dunhill"}, {resident:"Dane", colour:"blue", pet:"horse", drink:"tea", smoke:"Blend"}, {resident:"Englishman", colour:"red", pet:"birds", drink:"milk", smoke:"Pall Mall"}, {resident:"German", colour:"green", pet:"ZEBRA", drink:"coffee", smoke:"Prince"}, {resident:"Swede", colour:"white", pet:"dog", drink:"beer", smoke:"Blue Master"}}}}</syntaxhighlight>
 
=={{header|AutoHotkey}}==
Line 311 ⟶ 443:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> REM The names (only used for printing the results):
DIM Drink$(4), Nation$(4), Colr$(4), Smoke$(4), Animal$(4)
Drink$() = "Beer", "Coffee", "Milk", "Tea", "Water"
Line 411 ⟶ 543:
j% -= 1
ENDWHILE
= TRUE</langsyntaxhighlight>
'''Output:'''
<pre>
Line 426 ⟶ 558:
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">( (English Swede Dane Norwegian German,)
(red green white yellow blue,(red.English.))
(dog birds cats horse zebra,(dog.?.Swede.))
Line 508 ⟶ 640:
& props$(!properties...)
& done
);</langsyntaxhighlight>
Output:
<pre> Solution
Line 519 ⟶ 651:
 
=={{header|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
 
Line 756 ⟶ 888:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>% gcc -Wall -O3 -std=c99 zebra.c -o zebra && time ./zebra
Line 770 ⟶ 902:
 
I'll be the first to admit the following doesn't quite look like a C program. It's in fact in Perl, which outputs a C source, which in turn solves the puzzle. If you think this is long, wait till you see the C it writes.
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
 
use utf8;
Line 945 ⟶ 1,077:
 
# write C code. If it's ugly to you: I didn't write; Perl did.
make_c;</langsyntaxhighlight>
output (ran as <code>perl test.pl | gcc -Wall -x c -; ./a.out</code>):<pre>
0 dunhill cats yellow water Norske
Line 959 ⟶ 1,091:
<!-- By Martin Freedman, 17/01/2018 -->
This is adapted from a solution to a similar problem by Peter Norvig in his [https://www.udacity.com/course/design-of-computer-programs--cs212 Udacity course CS212], originally written in Python. This is translated from [https://github.com/exercism/python/blob/master/exercises/zebra-puzzle/example.py example python solution on exercism]. This is a Generate-and-Prune Constraint Programming algorithm written with Linq. (See Benchmarks below)
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 1,043 ⟶ 1,175:
Read();
}
}</langsyntaxhighlight>
Produces:
<pre>
Line 1,062 ⟶ 1,194:
 
This is a different type of generate-and-prune compared to Norvig. The Norvig solution generates each attribute for 5 houses, then prunes and repeats with the next attribute. Here all houses with possible attributes are first generated and pruned to 78 candidates. The second phase proceeds over the combination of 5 houses from that 78, generating and pruning 1 house at a time. (See Benchmarks below)
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 1,170 ⟶ 1,302:
}
}
}</langsyntaxhighlight>
Produces
<pre>The zebra owner is German
Line 1,186 ⟶ 1,318:
{{works with|C sharp|C#|7.1}}
<!-- By Martin Freedman, 9/02/2018 -->
<langsyntaxhighlight lang="csharp">using Amb;
using System;
using System.Collections.Generic;
Line 1,271 ⟶ 1,403:
Read();
}
}</langsyntaxhighlight>
Produces
<pre>The zebra owner is German
Line 1,287 ⟶ 1,419:
{{libheader|Microsoft Solver Foundation}}
<!-- By Martin Freedman, 19/01/2018 based on MS example code-->
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 1,399 ⟶ 1,531:
Read();
}
}</langsyntaxhighlight>
Produces:
<pre>
Line 1,428 ⟶ 1,560:
This is a modification of the C submission that uses rule classes and reduces the number of permutations evaluated.
 
<langsyntaxhighlight lang="cpp">
#include <stdio.h>
#include <string.h>
Line 1,576 ⟶ 1,708:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,596 ⟶ 1,728:
=={{header|Clojure}}==
This solution uses the contributed package ''clojure.core.logic'' (with ''clojure.tools.macro''), a mini-Kanren based logic solver. The solution is basically the one in [http://github.com/swannodette/logic-tutorial Swannodette's logic tutorial], adapted to the problem statement here.
<langsyntaxhighlight lang="clojure">(ns zebra.core
(:refer-clojure :exclude [==])
(:use [clojure.core.logic]
Line 1,638 ⟶ 1,770:
(println "full solution (in house order):")
(doseq [h soln] (println " " h)))
</syntaxhighlight>
</lang>
{{output}}
<pre>solution count: 1
Line 1,656 ⟶ 1,788:
This is adapted from a solution to a similar problem by Peter Norvig in his [https://www.udacity.com/course/design-of-computer-programs--cs212 Udacity course CS212], originally written in Python but equally applicable in any language with for-comprehensions.
 
<langsyntaxhighlight lang="clojure">(ns zebra
(:require [clojure.math.combinatorics :as c]))
 
Line 1,703 ⟶ 1,835:
(println (apply format "%5s %-11s %-7s %-7s %-12s %-6s"
(map #(% i) (cons inc solution)))))))
</syntaxhighlight>
</lang>
{{output}}
<pre>user=> (time (zebra/-main))
Line 1,721 ⟶ 1,853:
=={{header|Crystal}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="ruby">CONTENT = {House: [""],
Nationality: %i[English Swedish Danish Norwegian German],
Colour: %i[Red Green White Blue Yellow],
Line 1,778 ⟶ 1,910:
end
 
solve_zebra_puzzle</langsyntaxhighlight>
 
=={{header|Curry}}==
{{Works with|PAKCS}}
<langsyntaxhighlight lang="curry">import Constraint (allC, anyC)
import Findall (findall)
 
Line 1,824 ⟶ 1,956:
 
 
main = findall $ \(hs,who) -> houses hs & H _ who Zebra _ _ `member` hs</langsyntaxhighlight>
{{Output}} Using [http://www-ps.informatik.uni-kiel.de/~pakcs/webpakcs/main.cgi web interface].
<pre>Execution time: 180 msec. / elapsed: 180 msec.
Line 1,832 ⟶ 1,964:
{{trans|Ada}}
Most foreach loops in this program are static.
<langsyntaxhighlight lang="d">import std.stdio, std.traits, std.algorithm, std.math;
 
enum Content { Beer, Coffee, Milk, Tea, Water,
Line 1,926 ⟶ 2,058:
 
solve(M, Test.Drink, 5);
}</langsyntaxhighlight>
{{out}}
<pre> One: Water Norwegian Yellow Dunhill Cat
Line 1,938 ⟶ 2,070:
{{trans|Python}}
This requires the module of the first D entry from the Permutations Task.
<langsyntaxhighlight lang="d">import std.stdio, std.math, std.traits, std.typecons, std.typetuple, permutations1;
 
uint factorial(in uint n) pure nothrow @nogc @safe
Line 2,037 ⟶ 2,169:
writeln;
}
}</langsyntaxhighlight>
{{out}}
<pre>Found a solution:
Line 2,052 ⟶ 2,184:
{{trans|PicoLisp}}
This requires the module of the second D entry from the Permutations Task.
<langsyntaxhighlight lang="d">void main() {
import std.stdio, std.algorithm, permutations2;
 
Line 2,084 ⟶ 2,216:
nextTo(drinks, Water, smokes, Blend))
writefln("%(%10s\n%)\n", [houses, persons, drinks, pets, smokes]);
}</langsyntaxhighlight>
{{out}}
<pre>[ Yellow, Blue, Red, Green, White]
Line 2,095 ⟶ 2,227:
=={{header|EchoLisp}}==
We use the '''amb''' library to solve the puzzle. The number of tries - calls to zebra-puzzle - is only 1900, before finding all solutions. Note that there are no declarations for things (cats, tea, ..) or categories (animals, drinks, ..) which are discovered when reading the constraints.
<langsyntaxhighlight lang="scheme">
(lib 'hash)
(lib 'amb)
Line 2,168 ⟶ 2,300:
(amb-fail) ;; will ensure ALL solutions are printed
)
</syntaxhighlight>
</lang>
{{out}}
<langsyntaxhighlight lang="scheme">
(define (task)
(amb-run zebra-puzzle (amb-make-context) (iota 5)))
Line 2,184 ⟶ 2,316:
→ #f
 
</syntaxhighlight>
</lang>
 
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule ZebraPuzzle do
defp adjacent?(n,i,g,e) do
Enum.any?(0..3, fn x ->
Line 2,261 ⟶ 2,393:
Smoke: ~w[PallMall Dunhill BlueMaster Prince Blend]a ]
 
ZebraPuzzle.solve(content)</langsyntaxhighlight>
 
{{out}}
Line 2,278 ⟶ 2,410:
=={{header|Erlang}}==
This solution generates all houses that fits the rules for single houses, then it checks multi-house rules. It would be faster to check multi-house rules while generating the houses. I have not added this complexity since the current program takes just a few seconds.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( zebra_puzzle ).
 
Line 2,396 ⟶ 2,528:
is_rule_16_ok( _House1, _House2, _House3, #house{drink=water}, #house{smoke=blend} ) -> true;
is_rule_16_ok( _House1, _House2, _House3, _House4, _House5 ) -> false.
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,410 ⟶ 2,542:
 
=={{header|ERRE}}==
<syntaxhighlight lang="erre">
<lang ERRE>
PROGRAM ZEBRA_PUZZLE
 
Line 2,516 ⟶ 2,648:
PRINT("Number of solutions=";SOLUTIONS%)
PRINT("Solved in ";TIMER-T1;" seconds")
END PROGRAM</langsyntaxhighlight>
{{out}}
<pre>
Line 2,531 ⟶ 2,663:
=={{header|F_Sharp|F#}}==
This task uses [[Permutations_by_swapping#F.23]]
<langsyntaxhighlight lang="fsharp">
(*Here I solve the Zebra puzzle using Plain Changes, definitely a challenge to some campanoligist to solve it using Grandsire Doubles.
Nigel Galloway: January 27th., 2017 *)
Line 2,573 ⟶ 2,705:
|Some(nn) -> nn.Gz |> Array.iteri(fun n g -> if (g = G.Zebra) then printfn "\nThe man who owns a zebra is %A\n" nn.Nz.[n]); printfn "%A" nn
|None -> printfn "No solution found"
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,586 ⟶ 2,718:
 
=={{header|FormulaOne}}==
<syntaxhighlight lang="formulaone">
<lang FormulaOne>
// First, let's give some type-variables some values:
Nationality = Englishman | Swede | Dane | Norwegian | German
Colour = Red | Green | Yellow | Blue | White
Line 2,593 ⟶ 2,725:
Domestic = Dog | Bird | Cat | Zebra | Horse
Beverage = Tea | Coffee | Milk | Beer | Water
HouseOrderHouseRow = First | Second | Third | Fourth | Fifth
{
We use injections to make the array-elements unique.
Example: 'Pet' is an array of unique elements of type 'Domestic', indexed by 'Nationality'.
In the predicate 'Zebra', we use this injection 'Pet' to define the array-variable 'pet'.
as a parameter of the 'Zebra'-predicate.
The symbol used is the '->>'. 'Nationality->>Domestic' can be read as 'Domestic(Nationality)' in "plain array-speak";
The symbol used is the '->>'. 'Nationality->>Domestic' can be read as 'Domestic(Nationality)'
the difference being that the elements are by definition unique.
in "plain array-speak";
the difference being that the elements are by definition unique (cf. 'injective function').
So, in FormulaOne we use a formula like: 'pet(Swede) = Dog', which simply means that the 'Swede' (type 'Nationality')
(type 'Nationality') has a 'pet' (type 'Pet', which is of type 'Domestic', indexed by 'Nationality'), which appears to be a 'Dog' (type 'Domestic').
which appears to be a 'Dog' (type 'Domestic').
Or, one could say that the 'Swede' has been mapped to the 'Dog' (Oh, well...).
}
Line 2,611 ⟶ 2,746:
HouseColour = Nationality->>Colour
Smoke = Nationality->>Cigarette
Order HouseOrder = HouseOrderHouseRow->>Nationality
pred Zebra(houseColourhouse_olour::HouseColour, pet::Pet, smoke::Smoke, drink::Drink, orderhouse_order::OrderHouseOrder) iff
// For convenience sake, some temporary place_holder variables are used.
// An underscore distinguishes them:
 
houseColourhouse_colour(green_house) = Green &
houseColourhouse_colour(white_house) = White &
houseColourhouse_colour(yellow_house) = Yellow &
smoke(pallmall_smoker) = PallMall &
smoke(blend_smoker) = Blend &
smoke(dunhill_smoker) = Dunhill &
smoke(bluemaster_smoker) = BlueMaster &
pet(cat_keeper) = Cat &
pet(neighbour_dunhill_smoker) = Horse &
 
{ 2. The English man lives in the red house: }
houseColourhouse_colour(Englishman) = Red &
{ 3. The Swede has a dog: }
Line 2,642 ⟶ 2,777:
}
{ 5. The green house is immediately to the left of the white house: }.
{ The local predicate 'LeftOf' (see below) determines the house order: }
LeftOf(green_house, white_house, orderhouse_order) &
{ 6. They drink coffee in the green house: }
Line 2,655 ⟶ 2,790:
smoke(yellow_house) = Dunhill &
{ 9. In the middle house (third in the row) they drink milk: }
drink(orderhouse_order(Third)) = Milk &
{10. The Norwegian lives in the first house: }
orderhouse_order(First) = Norwegian &
{11. The man who smokes Blend lives in the house next to the house with cats: }.
{ Another local predicate 'Neighbour' makes them neighbours: }
Neighbour(blend_smoker, cat_keeper, orderhouse_order) &
{12. In a house next to the house where they have a horse, they smoke Dunhill: }
Neighbour(dunhill_smoker, neighbour_dunhill_smoker, orderhouse_order) &
{13. The man who smokes Blue Master drinks beer: }
Line 2,674 ⟶ 2,809:
smoke(German) = Prince &
{15. The Norwegian lives next to the blue house: }
{Cf. 10. "The Norwegian lives in the first house", so the blue house is the second house: }
house_colour(house_order(Second)) = Blue &
so the blue house is the second house }
houseColour(order(Second)) = Blue &
{16. They drink water in a house next to the house where they smoke Blend: }
drink(neighbour_blend_smoker) = Water &
Neighbour(blend_smoker, neighbour_blend_smoker, orderhouse_order)
{ A simplified solution would number the houses 1, 2, 3, 4, 5
Line 2,689 ⟶ 2,823:
}
local pred Neighbour(neighbour1::Nationality, neighbour2::Nationality, orderhouse_order::OrderHouseOrder)iff
neighbour1 <> neighbour2 &
orderhouse_order(house1) = neighbour1 &
orderhouse_order(house2) = neighbour2 &
( house1 = house2 + 1 |
house1 = house2 - 1 )
local pred LeftOf(neighbour1::Nationality, neighbour2::Nationality, orderhouse_order::OrderHouseOrder) iff
neighbour1 <> neighbour2 &
orderhouse_order(house1) = neighbour1 &
orderhouse_order(house2) = neighbour2 &
house1 = house2 - 1
{
The 'all'-query in FormulaOne:
all Zebra(houseColourhouse_colour, pet, smokes, drinks, orderhouse_order)
gives, of course, only one solution, so it can be replaced by:
one Zebra(houseColourhouse_colour, pet, smokes, drinks, orderhouse_order)
}
Line 2,716 ⟶ 2,850:
Domestic = Dog | Bird | Cat | Zebra | Horse
Beverage = Tea | Coffee | Milk | Beer | Water
HouseOrderHouseRow = First | Second | Third | Fourth | Fifth
Pet = Nationality->>Domestic
Line 2,722 ⟶ 2,856:
HouseColour = Nationality->>Colour
Smoke = Nationality->>Cigarette
Order HouseOrder = HouseOrderHouseRow->>Nationality
 
pred Zebra(houseColourhouse_colour::HouseColour, pet::Pet, smoke::Smoke, drink::Drink, orderhouse_order::OrderHouseOrder) iff
 
houseColourhouse-colour(green_house) = Green &
houseColourhouse-colour(white_house) = White &
houseColourhouse-colour(yellow_house) = Yellow &
smoke(pallmall_smoker) = PallMall &
smoke(blend_smoker) = Blend &
Line 2,735 ⟶ 2,869:
pet(cat_keeper) = Cat &
pet(neighbour_dunhill_smoker) = Horse &
house_colour(Englishman) = Red &
 
houseColour(Englishman) = Red &
pet(Swede) = Dog &
drink(Dane) = Tea &
LeftOf(green_house, white_house, orderhouse_order) &
drink(green_house) = Coffee &
pet(pallmall_smoker) = Bird &
smoke(yellow_house) = Dunhill &
drink(orderhouse_order(Third)) = Milk &
orderhouse_order(First) = Norwegian &
Neighbour(blend_smoker, cat_keeper, orderhouse_order) &
Neighbour(dunhill_smoker, neighbour_dunhill_smoker, orderhouse_order) &
drink(bluemaster_smoker) = Beer &
smoke(German) = Prince &
houseColourhouse_colour(orderhouse_order(Second)) = Blue &
drink(neighbour_blend_smoker) = Water &
Neighbour(blend_smoker, neighbour_blend_smoker, orderhouse_order)
local pred Neighbour(neighbour1::Nationality, neighbour2::Nationality, orderhouse_order::OrderHouseOrder)iff
neighbour1 <> neighbour2 &
orderhouse_order(house1) = neighbour1 & orderhouse_order(house2) = neighbour2 &
( house1 = house2 + 1 | house1 = house2 - 1 )
local pred LeftOf(neighbour1::Nationality, neighbour2::Nationality, orderhouse_::OrderHouseOrder) iff
neighbour1 <> neighbour2 &
orderhouse_order(house1) = neighbour1 & orderhouse_order(house2) = neighbour2 &
house1 = house2 - 1
</syntaxhighlight>
</lang>
{{out}}
<pre>
houseColour house_colour = [ {Englishman} Red, {Swede} White, {Dane} Blue, {Norwegian} Yellow, {German} Green ]
pet = [ {Englishman} Birds, {Swede} Dog, {Dane} Horse, {Norwegian} Cats, {German} Zebra ]
smokes = [ {Englishman} PallMall, {Swede} BlueMaster, {Dane} Blend, {Norwegian} Dunhill, {German} Prince ]
drinks = [ {Englishman} Milk, {Swede} Beer, {Dane} Tea, {Norwegian} Water, {German} Coffee ]
orderhouse_order = [ {First} Norwegian, {Second} Dane, {Third} Englishman, {Fourth} German, {Fifth}, Swede ]
</pre>
 
=={{header|GAP}}==
<langsyntaxhighlight lang="gap">leftOf :=function(setA, vA, setB, vB)
local i;
for i in [1..4] do
Line 2,833 ⟶ 2,966:
Print(cigars,"\n");
od;od;od;od;od;
</syntaxhighlight>
</lang>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 3,129 ⟶ 3,262:
fmt.Println(n, "solution found")
fmt.Println(sol)
}</langsyntaxhighlight>
{{out}}
<pre>Generated 51 valid houses
Line 3,147 ⟶ 3,280:
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">module Main where
 
import Control.Applicative ((<$>), (<*>))
Line 3,237 ⟶ 3,370:
leftOf p q
| (_:h:_) <- dropWhile (not . p) solution = q h
| otherwise = False</langsyntaxhighlight>
{{out}}
<pre>House {color = Yellow, man = Nor, pet = Cats, drink = Water, smoke = Dunhill}
Line 3,252 ⟶ 3,385:
(a little faster version)
 
<langsyntaxhighlight lang="haskell">import Control.Monad
import Data.List
 
Line 3,311 ⟶ 3,444:
print [nation | (nation, _, Zebra, _, _) <- answer]
putStrLn "" )
putStrLn "No more solutions!"</langsyntaxhighlight>
 
Output:
Line 3,326 ⟶ 3,459:
 
Propositions 1 .. 16 without 9,10 and15
<langsyntaxhighlight lang="j">ehs=: 5$a:
 
cr=: (('English';'red') 0 3} ehs);<('Dane';'tea') 0 2}ehs
Line 3,338 ⟶ 3,471:
next=: <((<'Blend') 4 }ehs);<(<'water')2}ehs
next=: next,<((<'Blend') 4 }ehs);<(<'cats')1}ehs
next=: next,<((<'Dunhill') 4}ehs);<(<'horse')1}ehs</langsyntaxhighlight>
'''Example'''
<langsyntaxhighlight lang="j"> lof
┌─────────────────┬───────────┐
│┌┬┬──────┬─────┬┐│┌┬┬┬─────┬┐│
││││coffee│green│││││││white│││
│└┴┴──────┴─────┴┘│└┴┴┴─────┴┘│
└─────────────────┴───────────┘</langsyntaxhighlight>
 
Collections of all variants of the propositions:
<langsyntaxhighlight lang="j">hcr=: (<ehs),. (A.~i.@!@#)cr
hcs=:~. (A.~i.@!@#)cs,2$<ehs
hlof=:(-i.4) |."0 1 lof,3$<ehs
hnext=: ,/((i.4) |."0 1 (3$<ehs)&,)"1 ;(,,:|.)&.> next</langsyntaxhighlight>
 
We start the row of houses with fixed properties 9, 10 and 15.
<langsyntaxhighlight lang="j">houses=: ((<'Norwegian') 0}ehs);((<'blue') 3 }ehs);((<'milk') 2}ehs);ehs;<ehs</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="j"> houses
┌───────────────┬──────────┬──────────┬──────┬──────┐
│┌─────────┬┬┬┬┐│┌┬┬┬────┬┐│┌┬┬────┬┬┐│┌┬┬┬┬┐│┌┬┬┬┬┐│
││Norwegian││││││││││blue││││││milk││││││││││││││││││
│└─────────┴┴┴┴┘│└┴┴┴────┴┘│└┴┴────┴┴┘│└┴┴┴┴┘│└┴┴┴┴┘│
└───────────────┴──────────┴──────────┴──────┴──────┘</langsyntaxhighlight>
Set of proposition variants:
<langsyntaxhighlight lang="j">constraints=: hcr;hcs;hlof;<hnext</langsyntaxhighlight>
The worker and its helper verbs
<langsyntaxhighlight lang="j">select=: ~.@(,: #~ ,&(0~:#))
filter=: #~*./@:(2>#S:0)"1
compose=: [: filter f. [: ,/ select f. L:0"1"1 _
Line 3,375 ⟶ 3,508:
z=.(#~1=[:+/"1 (0=#)S:0"1) h=.~. h
end.
)</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="j"> >"0 houses solve constraints
┌─────────┬─────┬──────┬──────┬──────────┐
│Norwegian│cats │water │yellow│Dunhill │
Line 3,388 ⟶ 3,521:
├─────────┼─────┼──────┼──────┼──────────┤
│Swede │dog │beer │white │BlueMaster│
└─────────┴─────┴──────┴──────┴──────────┘</langsyntaxhighlight>
So, the German owns the zebra.
 
'''Alternative'''
<br>A longer running solver by adding the zebra variants.
<langsyntaxhighlight lang="j">zebra=: (-i.5)|."0 1 (<(<'zebra') 1}ehs),4$<ehs
 
solve3=: 4 :0
Line 3,400 ⟶ 3,533:
z=. f^:(3>[:#(#~p"1)&>)^:_ <,:x
>"0 (#~([:*./[:;[:<@({.~:}.)\.;)"1)(#~p"1); z
)</langsyntaxhighlight>
{{out}}
<langsyntaxhighlight lang="j"> houses solve3 constraints,<zebra
┌─────────┬─────┬──────┬──────┬──────────┐
│Norwegian│cats │water │yellow│Dunhill │
Line 3,413 ⟶ 3,546:
├─────────┼─────┼──────┼──────┼──────────┤
│Swede │dog │beer │white │BlueMaster│
└─────────┴─────┴──────┴──────┴──────────┘</langsyntaxhighlight>
 
=={{header|Java}}==
This Java solution includes 34 classes. I developed and tested on a Win7 machine with JDK 1.8 platform, but it should work with earlier version 1.7 also.:
* The outer class <tt>Zebra</tt>
* A PossibleLine
* A set of PossibleLines
* The Solver
 
<syntaxhighlight lang="java">package org.rosettacode.zebra;
First, create a class which express the puzzle line.
 
import java.util.Arrays;
<lang Java>
import java.util.Iterator;
package zebra;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
 
public class LineOfPuzzleZebra implements Cloneable{
private Integer order;
private String nation;
private String color;
private String animal;
private String drink;
private String cigarette;
private LineOfPuzzle rightNeighbor;
private LineOfPuzzle leftNeighbor;
private PuzzleSet<LineOfPuzzle> undefNeighbors;
public LineOfPuzzle (Integer order, String nation, String color,
String animal, String drink, String cigarette){
this.animal=animal;
this.cigarette=cigarette;
this.color=color;
this.drink=drink;
this.nation=nation;
this.order=order;
}
 
private static final int[] orders = {1, 2, 3, 4, 5};
public Integer getOrder() {
private static final String[] nations = {"English", "Danish", "German", "Swedish", "Norwegian"};
return order;
private static final String[] animals = {"Zebra", "Horse", "Birds", "Dog", "Cats"};
}
private static final String[] drinks = {"Coffee", "Tea", "Beer", "Water", "Milk"};
private static final String[] cigarettes = {"Pall Mall", "Blend", "Blue Master", "Prince", "Dunhill"};
private static final String[] colors = {"Red", "Green", "White", "Blue", "Yellow"};
 
static class Solver {
public void setOrder(Integer order) {
private final PossibleLines puzzleTable = new PossibleLines();
this.order = order;
}
 
public String getNation void solve() {
PossibleLines constraints = new PossibleLines();
return nation;
constraints.add(new PossibleLine(null, "English", "Red", null, null, null));
}
constraints.add(new PossibleLine(null, "Swedish", null, "Dog", null, null));
constraints.add(new PossibleLine(null, "Danish", null, null, "Tea", null));
constraints.add(new PossibleLine(null, null, "Green", null, "Coffee", null));
constraints.add(new PossibleLine(null, null, null, "Birds", null, "Pall Mall"));
constraints.add(new PossibleLine(null, null, "Yellow", null, null, "Dunhill"));
constraints.add(new PossibleLine(3, null, null, null, "Milk", null));
constraints.add(new PossibleLine(1, "Norwegian", null, null, null, null));
constraints.add(new PossibleLine(null, null, null, null, "Beer", "Blue Master"));
constraints.add(new PossibleLine(null, "German", null, null, null, "Prince"));
constraints.add(new PossibleLine(2, null, "Blue", null, null, null));
 
//Creating all possible combination of a puzzle line.
public void setNation(String nation) {
//The maximum number of lines is 5^^6 (15625).
this.nation = nation;
//Each combination line is checked against a set of knowing facts, thus
}
//only a small number of line result at the end.
for (Integer orderId : Zebra.orders) {
for (String nation : Zebra.nations) {
for (String color : Zebra.colors) {
for (String animal : Zebra.animals) {
for (String drink : Zebra.drinks) {
for (String cigarette : Zebra.cigarettes) {
addPossibleNeighbors(constraints, orderId, nation, color, animal, drink, cigarette);
}
}
}
}
}
}
 
System.out.println("After general rule set validation, remains " +
public String getColor() {
puzzleTable.size() + " lines.");
return color;
}
 
for (Iterator<PossibleLine> it = puzzleTable.iterator(); it.hasNext(); ) {
public void setColor(String color) {
this.color boolean validLine = colortrue;
}
 
PossibleLine possibleLine = it.next();
public String getAnimal() {
return animal;
}
 
if (possibleLine.leftNeighbor != null) {
public void setAnimal(String animal) {
PossibleLine neighbor = possibleLine.leftNeighbor;
this.animal = animal;
if (neighbor.order < 1 || neighbor.order > 5) {
}
validLine = false;
it.remove();
}
}
if (validLine && possibleLine.rightNeighbor != null) {
PossibleLine neighbor = possibleLine.rightNeighbor;
if (neighbor.order < 1 || neighbor.order > 5) {
it.remove();
}
}
}
 
System.out.println("After removing out of bound neighbors, remains " +
public String getDrink() {
puzzleTable.size() + " lines.");
return drink;
}
 
//Setting left and right neighbors
public void setDrink(String drink) {
for (PossibleLine puzzleLine : puzzleTable) {
this.drink = drink;
for (PossibleLine leftNeighbor : puzzleLine.neighbors) {
}
PossibleLine rightNeighbor = leftNeighbor.copy();
 
//make it left neighbor
public String getCigarette() {
leftNeighbor.order = puzzleLine.order - 1;
return cigarette;
if (puzzleTable.contains(leftNeighbor)) {
}
if (puzzleLine.leftNeighbor != null)
puzzleLine.leftNeighbor.merge(leftNeighbor);
else
puzzleLine.setLeftNeighbor(leftNeighbor);
}
rightNeighbor.order = puzzleLine.order + 1;
if (puzzleTable.contains(rightNeighbor)) {
if (puzzleLine.rightNeighbor != null)
puzzleLine.rightNeighbor.merge(rightNeighbor);
else
puzzleLine.setRightNeighbor(rightNeighbor);
}
}
}
 
int iteration = 1;
public void setCigarette(String cigarette) {
this.cigarette int lastSize = cigarette0;
}
 
//Recursively validate against neighbor rules
/**
while (puzzleTable.size() > 5 && lastSize != puzzleTable.size()) {
* Overrides object equal method
lastSize = puzzleTable.size();
* @param obj
puzzleTable.clearLineCountFlags();
* @return
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof LineOfPuzzle){
LineOfPuzzle searchLine = (LineOfPuzzle)obj;
return this.getWholeLine().equalsIgnoreCase(searchLine.getWholeLine());
}
else
return false;
}
public int getFactsCount(){
int facts = 0;
facts+=this.getOrder()!=null?1:0;
facts+=this.getNation()!=null?1:0;
facts+=this.getColor()!=null?1:0;
facts+=this.getAnimal()!=null?1:0;
facts+=this.getCigarette()!=null?1:0;
facts+=this.getDrink()!=null?1:0;
return facts;
}
public int getCommonFactsCount(LineOfPuzzle lineOfFacts){
int ordrCmp = (this.order!=null && lineOfFacts.getOrder()!= null &&
this.order.intValue()== lineOfFacts.getOrder().intValue())?1:0;
int natnCmp = (this.nation!=null && lineOfFacts.getNation()!= null &&
this.nation.equalsIgnoreCase(lineOfFacts.getNation()))?1:0;
int colrCmp = (this.color!=null && lineOfFacts.getColor()!= null &&
this.color.equalsIgnoreCase(lineOfFacts.getColor()))?1:0;
 
recursiveSearch(null, puzzleTable, -1);
int petsCmp = (this.animal!=null && (lineOfFacts.getAnimal()!= null &&
this.animal.equalsIgnoreCase(lineOfFacts.getAnimal())))?1:0;
 
constraints.clear();
int cigrCmp = (this.cigarette!=null && lineOfFacts.getCigarette()!= null &&
// Assuming we'll get at leas one valid line each iteration, we create
this.cigarette.equalsIgnoreCase(lineOfFacts.getCigarette()))?1:0;
// a set of new rules with lines which have no more then one instance of same OrderId.
for (int i = 1; i < 6; i++) {
if (puzzleTable.getLineCountByOrderId(i) == 1)
constraints.addAll(puzzleTable.getSimilarLines(new PossibleLine(i, null, null, null, null,
null)));
}
 
puzzleTable.removeIf(puzzleLine -> !constraints.accepts(puzzleLine));
int drnkCmp = (this.drink!=null && lineOfFacts.getDrink()!= null &&
this.drink.equalsIgnoreCase(lineOfFacts.getDrink()))?1:0;
int result = (ordrCmp + natnCmp + colrCmp + petsCmp + cigrCmp + drnkCmp);
return result;
}
public void addUndefindedNeighbor(LineOfPuzzle newNeighbor){
if (this.undefNeighbors==null)
this.undefNeighbors = new PuzzleSet<>();
this.undefNeighbors.add(newNeighbor);
}
public boolean hasUndefNeighbors(){
return (this.undefNeighbors!=null);
}
 
System.out.println("After " + iteration + " recursive iteration, remains "
public PuzzleSet<LineOfPuzzle> getUndefNeighbors(){
+ puzzleTable.size() + " lines");
return this.undefNeighbors;
iteration++;
}
}
 
// Print the results
public void setLeftNeighbor(LineOfPuzzle leftNeighbor){
System.out.println("-------------------------------------------");
this.leftNeighbor = leftNeighbor;
if (puzzleTable.size() == 5) {
this.leftNeighbor.setOrder(this.order - 1);
for (PossibleLine puzzleLine : puzzleTable) {
}
System.out.println(puzzleLine.getWholeLine());
}
public void setRightNeighbor(LineOfPuzzle rightNeighbor){
} else
this.rightNeighbor=rightNeighbor;
System.out.println("Sorry, solution not found!");
this.rightNeighbor.setOrder(this.order + 1);
}
public boolean hasLeftNeighbor(){
return (leftNeighbor!=null);
}
public LineOfPuzzle getLeftNeighbor(){
return this.leftNeighbor;
}
public boolean hasNeighbor(int direction){
if (direction < 0)
return (leftNeighbor!=null);
else
return (rightNeighbor!=null);
}
 
private void addPossibleNeighbors(
public boolean hasRightNeighbor(){
PossibleLines constraints, Integer orderId, String nation,
return (rightNeighbor!=null);
String color, String animal, String drink, String cigarette) {
}
boolean validLine = true;
PossibleLine pzlLine = new PossibleLine(orderId,
public LineOfPuzzle getRightNeighbor(){
return this.rightNeighbor; nation,
color,
}
animal,
drink,
cigarette);
// Checking against a set of knowing facts
if (constraints.accepts(pzlLine)) {
// Adding rules of neighbors
if (cigarette.equals("Blend")
&& (animal.equals("Cats") || drink.equals("Water")))
validLine = false;
 
if (cigarette.equals("Dunhill")
public LineOfPuzzle getNeighbor(int direction){
&& animal.equals("Horse"))
if (direction < 0)
return this.leftNeighbor validLine = false;
else
return this.rightNeighbor;
}
public String getWholeLine() {
String sLine = this.order + " - " +
this.nation + " - " +
this.color + " - " +
this.animal + " - " +
this.drink + " - " +
this.cigarette;
return sLine;
}
@Override
public int hashCode() {
int sLine = (this.order + " - " +
this.nation + " - " +
this.color + " - " +
this.animal + " - " +
this.drink + " - " +
this.cigarette
).hashCode();
return sLine;
}
 
public void merge(LineOfPuzzle mergedLine){ if (validLine) {
puzzleTable.add(pzlLine);
if (this.order == null) this.order = mergedLine.order;
 
if (this.nation == null) this.nation = mergedLine.nation;
//set neighbors constraints
if (this.color == null) this.color = mergedLine.color;
if (color.equals("Green")) {
if (this.animal == null) this.animal = mergedLine.animal;
pzlLine.setRightNeighbor(
if (this.drink == null) this.drink = mergedLine.drink;
new PossibleLine(null, null, "White", null, null, null));
if (this.cigarette == null) this.cigarette = mergedLine.cigarette;
}
if (color.equals("White")) {
pzlLine.setLeftNeighbor(
new PossibleLine(null, null, "Green", null, null, null));
public LineOfPuzzle clone() {
try { }
return (LineOfPuzzle) super.clone(); //
if (animal.equals("Cats") && !cigarette.equals("Blend")) {
} catch (CloneNotSupportedException e) {
pzlLine.neighbors.add(new PossibleLine(null, null, null, null, null,
e.printStackTrace();
throw new RuntimeException( "Blend"));
}
if (cigarette.equals("Blend") && !animal.equals("Cats")) {
pzlLine.neighbors.add(new PossibleLine(null, null, null, "Cats", null
, null));
}
//
if (drink.equals("Water")
&& !animal.equals("Cats")
&& !cigarette.equals("Blend")) {
pzlLine.neighbors.add(new PossibleLine(null, null, null, null, null,
"Blend"));
}
 
if (cigarette.equals("Blend") && !drink.equals("Water")) {
pzlLine.neighbors.add(new PossibleLine(null, null, null, null, "Water"
, null));
}
//
if (animal.equals("Horse") && !cigarette.equals("Dunhill")) {
pzlLine.neighbors.add(new PossibleLine(null, null, null, null, null,
"Dunhill"));
}
if (cigarette.equals("Dunhill") && !animal.equals("Horse")) {
pzlLine.neighbors.add(new PossibleLine(null, null, null, "Horse",
null, null));
}
}
}
}
}
}
</lang>
 
// Recursively checks the input set to ensure each line has right neighbor.
Second, create a class which express a set of puzzle lines.
// Neighbors can be of three type, left, right or undefined.
// Direction: -1 left, 0 undefined, 1 right
private boolean recursiveSearch(PossibleLine pzzlNodeLine,
PossibleLines possibleLines, int direction) {
boolean validLeaf = false;
boolean hasNeighbor;
PossibleLines puzzleSubSet;
 
for (Iterator<PossibleLine> it = possibleLines.iterator(); it.hasNext(); ) {
<lang Java>
PossibleLine pzzlLeafLine = it.next();
package zebra;
validLeaf = false;
 
hasNeighbor = pzzlLeafLine.hasNeighbor(direction);
import java.util.Iterator;
 
import java.util.LinkedHashSet;
if (hasNeighbor) {
puzzleSubSet = puzzleTable.getSimilarLines(pzzlLeafLine.getNeighbor(direction));
if (puzzleSubSet != null) {
if (pzzlNodeLine != null)
validLeaf = puzzleSubSet.contains(pzzlNodeLine);
else
validLeaf = recursiveSearch(pzzlLeafLine, puzzleSubSet, -1 * direction);
}
}
 
if (!validLeaf && pzzlLeafLine.hasNeighbor(-1 * direction)) {
hasNeighbor = true;
puzzleSubSet = puzzleTable.getSimilarLines(pzzlLeafLine.getNeighbor(-1 * direction));
if (puzzleSubSet != null) {
if (pzzlNodeLine != null)
validLeaf = puzzleSubSet.contains(pzzlNodeLine);
else
validLeaf = recursiveSearch(pzzlLeafLine, puzzleSubSet, direction);
}
}
 
if (pzzlNodeLine != null && validLeaf)
public class PuzzleSet<T extends LineOfPuzzle> extends LinkedHashSet{
return true;
private T t;
 
if (pzzlNodeLine == null && hasNeighbor && !validLeaf) {
private int countOfOne=0;
it.remove();
private int countOfTwo=0;
}
private int countOfThree=0;
 
private int countOfFour=0;
if (pzzlNodeLine == null) {
private int countOfFive=0;
if (hasNeighbor && validLeaf) {
possibleLines.riseLineCountFlags(pzzlLeafLine.order);
PuzzleSet() {
super(); }
if (!hasNeighbor) {
}
possibleLines.riseLineCountFlags(pzzlLeafLine.order);
public void set(T t) { this.t = t; } }
}
public T get(int index) {
return ((T)this.toArray()[index]);
}
public PuzzleSet<T> getSimilarLines(T searchLine) {
PuzzleSet<T> puzzleSubSet = new PuzzleSet<>();
for (Iterator<T> it = this.iterator(); it.hasNext();) {
T lineOfPuzzle = it.next();
if(lineOfPuzzle.getCommonFactsCount(searchLine) == searchLine.getFactsCount())
puzzleSubSet.add(lineOfPuzzle);
}
if (puzzleSubSet.isEmpty())
return null;
return puzzleSubSet;
}
public boolean contains(T searchLine) {
for (Iterator<T> it = this.iterator(); it.hasNext();) {
T puzzleLine = it.next();
if(puzzleLine.getCommonFactsCount(searchLine) == searchLine.getFactsCount())
return true;
}
return false;
}
public boolean accepts(T searchLine) {
int passed=0;
int notpassed=0;
for (Iterator<T> it = this.iterator(); it.hasNext();) {
T puzzleSetLine = it.next();
int lineFactsCnt = puzzleSetLine.getFactsCount();
int comnFactsCnt = puzzleSetLine.getCommonFactsCount(searchLine);
if( lineFactsCnt != comnFactsCnt && lineFactsCnt !=0 && comnFactsCnt !=0){
notpassed++;
}
return validLeaf;
if( lineFactsCnt == comnFactsCnt)
passed++;
}
return (passed >= 0 && notpassed == 0);
}
 
public static void riseLineCountFlagsmain(intString[] lineOrderIdargs) {
switch (lineOrderId){
case 1: countOfOne++; break;
case 2: countOfTwo++; break;
case 3: countOfThree++; break;
case 4: countOfFour++; break;
case 5: countOfFive++; break;
default:;
}
}
 
public void clearLineCountFlags(){
countOfOne=0;
countOfTwo=0;
countOfThree=0;
countOfFour=0;
countOfFive=0;
}
 
Solver solver = new Solver();
public int getLineCountByOrderId(int lineOrderId){
switch solver.solve(lineOrderId){;
case 1: return countOfOne;
case 2: return countOfTwo;
case 3: return countOfThree;
case 4: return countOfFour;
case 5: return countOfFive;
default:return -1;
}
}
}
</lang>
 
static class PossibleLines extends LinkedHashSet<PossibleLine> {
Third, create the main run class where there is a recursive call to check for rule sets.
<lang Java>
package zebra;
 
private final int[] count = new int[5];
import java.util.ArrayList;
import java.util.Iterator;
 
public classPossibleLine get(int Puzzleindex) {
return ((PossibleLine) toArray()[index]);
private static final ArrayList<Integer> orders = new ArrayList<>(5);
}
private static final ArrayList<String> nations = new ArrayList<>(5);
private static final ArrayList<String> animals = new ArrayList<>(5);
private static final ArrayList<String> drinks = new ArrayList<>(5);
private static final ArrayList<String> cigarettes = new ArrayList<>(5);
private static final ArrayList<String> colors = new ArrayList<>(5);
private static PuzzleSet<LineOfPuzzle> puzzleTable;
static
{
// House orders
orders.add(1);
orders.add(2);
orders.add(3);
orders.add(4);
orders.add(5);
// Man nations
nations.add("English");
nations.add("Danish");
nations.add("German");
nations.add("Swedesh");
nations.add("Norwegian");
//Animals
animals.add("Zebra");
animals.add("Horse");
animals.add("Birds");
animals.add("Dog");
animals.add("Cats");
//Drinks
drinks.add("Coffee");
drinks.add("Tea");
drinks.add("Beer");
drinks.add("Water");
drinks.add("Milk");
//Smokes
cigarettes.add("Pall Mall");
cigarettes.add("Blend");
cigarettes.add("Blue Master");
cigarettes.add("Prince");
cigarettes.add("Dunhill");
//Colors
colors.add("Red");
colors.add("Green");
colors.add("White");
colors.add("Blue");
colors.add("Yellow");
}
public static void main (String[] args){
boolean validLine=true;
puzzleTable = new PuzzleSet<>();
//Rules
LineOfPuzzle rule2 = new LineOfPuzzle(null, "English", "Red", null, null, null);
LineOfPuzzle rule3 = new LineOfPuzzle(null, "Swedesh", null, "Dog", null, null);
LineOfPuzzle rule4 = new LineOfPuzzle(null, "Danish", null, null, "Tea", null);
LineOfPuzzle rule6 = new LineOfPuzzle(null, null, "Green", null, "Coffee", null);
LineOfPuzzle rule7 = new LineOfPuzzle(null, null, null, "Birds", null, "Pall Mall");
LineOfPuzzle rule8 = new LineOfPuzzle(null, null, "Yellow", null, null, "Dunhill");
LineOfPuzzle rule9 = new LineOfPuzzle(3, null, null, null, "Milk", null);
LineOfPuzzle rule10 = new LineOfPuzzle(1, "Norwegian", null, null, null, null);
LineOfPuzzle rule13 = new LineOfPuzzle(null, null, null, null, "Beer", "Blue Master");
LineOfPuzzle rule14 = new LineOfPuzzle(null, "German", null, null, null, "Prince");
LineOfPuzzle rule15 = new LineOfPuzzle(2, null, "Blue", null, null, null);
PuzzleSet<LineOfPuzzle> ruleSet = new PuzzleSet<>();
ruleSet.add(rule2);
ruleSet.add(rule3);
ruleSet.add(rule4);
ruleSet.add(rule6);
ruleSet.add(rule7);
ruleSet.add(rule8);
ruleSet.add(rule9);
ruleSet.add(rule10);
ruleSet.add(rule13);
ruleSet.add(rule14);
ruleSet.add(rule15);
 
public PossibleLines getSimilarLines(PossibleLine searchLine) {
//Creating all possible combination of a puzzle line.
PossibleLines puzzleSubSet = new PossibleLines();
//The maximum number of lines is 5^^6 (15625).
for (PossibleLine possibleLine : this) {
//Each combination line is checked against a set of knowing facts, thus
if (possibleLine.getCommonFactsCount(searchLine) == searchLine.getFactsCount())
//only a small number of line result at the end.
for (Integer orderId : Puzzle.orders) { puzzleSubSet.add(possibleLine);
}
for (String nation : Puzzle.nations) {
forif (String color : PuzzlepuzzleSubSet.colorsisEmpty()) {
return null;
for (String animal : Puzzle.animals) {
for (String drink : Puzzle.drinks) {
for (String cigarette : Puzzle.cigarettes) {
LineOfPuzzle pzlLine = new LineOfPuzzle(orderId,
nation,
color,
animal,
drink,
cigarette);
// Checking against a set of knowing facts
if (ruleSet.accepts(pzlLine)){
// Adding rules of neighbors
if (cigarette.equalsIgnoreCase("Blend")
&& (animal.equalsIgnoreCase("Cats")
|| drink.equalsIgnoreCase("Water")))
validLine = false;
if (cigarette.equalsIgnoreCase("Dunhill")
&& animal.equalsIgnoreCase("Horse"))
validLine = false;
if (validLine){
puzzleTable.add(pzlLine);
//set neighbors constraints
if (color.equalsIgnoreCase("Green")){
pzlLine.setRightNeighbor(new LineOfPuzzle(null, null, "White", null, null, null));
}
if (color.equalsIgnoreCase("White")){
pzlLine.setLeftNeighbor(new LineOfPuzzle(null, null, "Green", null, null, null));
}
//
if (animal.equalsIgnoreCase("Cats")
&& !cigarette.equalsIgnoreCase("Blend") ){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, null, "Blend"));
}
if (cigarette.equalsIgnoreCase("Blend")
&& !animal.equalsIgnoreCase("Cats")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, "Cats", null, null));
}
//
if (drink.equalsIgnoreCase("Water")
&& !animal.equalsIgnoreCase("Cats")
&& !cigarette.equalsIgnoreCase("Blend")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, null, "Blend"));
}
 
return puzzleSubSet;
if (cigarette.equalsIgnoreCase("Blend")
}
&& !drink.equalsIgnoreCase("Water")){
 
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, "Water", null));
public boolean contains(PossibleLine searchLine) {
}
for (PossibleLine puzzleLine : this) //{
if (puzzleLine.getCommonFactsCount(searchLine) == searchLine.getFactsCount())
if (animal.equalsIgnoreCase("Horse")
return && !cigarette.equalsIgnoreCase("Dunhill")){true;
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, null, null, "Dunhill"));
}
if (cigarette.equalsIgnoreCase("Dunhill")
&& !animal.equalsIgnoreCase("Horse")){
pzlLine.addUndefindedNeighbor(new LineOfPuzzle(null, null, null, "Horse", null, null));
}
}
validLine = true;
}
} //cigarette end
} //drinks end
} //animal end
} //color end
} //nations end
} //order end
System.out.println("After general rule set validation, remains "+
puzzleTable.size() + " lines.");
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();){
validLine=true;
LineOfPuzzle lineOfPuzzle = it.next();
if (lineOfPuzzle.hasLeftNeighbor()){
LineOfPuzzle neighbor = lineOfPuzzle.getLeftNeighbor();
if (neighbor.getOrder()<1 || neighbor.getOrder()>5){
validLine=false;
it.remove();
}
}
return false;
if (validLine && lineOfPuzzle.hasRightNeighbor()){
LineOfPuzzle neighbor = lineOfPuzzle.getRightNeighbor();
if (neighbor.getOrder()<1 || neighbor.getOrder()>5){
it.remove();
}
}
}
System.out.println("After removing out of bound neighbors, remains " +
puzzleTable.size() + " lines.");
//Setting left and right neighbors
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();) {
LineOfPuzzle puzzleLine = it.next();
 
public boolean accepts(PossibleLine searchLine) {
if (puzzleLine.hasUndefNeighbors()){
int passed = 0;
for (Iterator<LineOfPuzzle> it1 = puzzleLine.getUndefNeighbors().iterator(); it1.hasNext();) {
int LineOfPuzzle leftNeighbornotpassed = it1.next()0;
LineOfPuzzle rightNeighbor = leftNeighbor.clone();
 
for (PossibleLine puzzleSetLine : this) //make it left neighbor{
int lineFactsCnt = leftNeighbor.setOrder(puzzleLinepuzzleSetLine.getOrdergetFactsCount()-1);
int comnFactsCnt = if (puzzleTablepuzzleSetLine.containsgetCommonFactsCount(leftNeighbor)searchLine){;
 
if (puzzleLine.hasLeftNeighbor())
if (lineFactsCnt != comnFactsCnt && lineFactsCnt != 0 && comnFactsCnt != 0) {
puzzleLine.getLeftNeighbor().merge(leftNeighbor);
elsenotpassed++;
puzzleLine.setLeftNeighbor(leftNeighbor);
}
rightNeighbor.setOrder(puzzleLine.getOrder()+1);
if (puzzleTable.contains(rightNeighbor)){
if (puzzleLine.hasRightNeighbor())
puzzleLine.getRightNeighbor().merge(rightNeighbor);
else
puzzleLine.setRightNeighbor(rightNeighbor);
}
}
 
if (lineFactsCnt == comnFactsCnt)
passed++;
}
return passed >= 0 && notpassed == 0;
}
int iteration=1;
int lastSize=0;
//Recursively validate against neighbor rules
while (puzzleTable.size()>5 && lastSize != puzzleTable.size()) {
lastSize = puzzleTable.size();
puzzleTable.clearLineCountFlags();
recursiveSearch(null, puzzleTable, -1);
ruleSet.clear();
// Assuming we'll get at leas one valid line each iteration, we create
// a set of new rules with lines which have no more then one instance of same OrderId.
for (int i = 1; i < 6; i++) {
if (puzzleTable.getLineCountByOrderId(i)==1)
ruleSet.addAll(puzzleTable.getSimilarLines(new LineOfPuzzle(i, null, null, null, null, null)));
}
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();) {
LineOfPuzzle puzzleLine = it.next();
 
public void riseLineCountFlags(int lineOrderId) {
if (!ruleSet.accepts(puzzleLine))
count[lineOrderId - it.remove()1]++;
}
//
System.out.println("After " + iteration + " recursive iteration, remains "
+ puzzleTable.size() + " lines");
iteration+=1;
}
 
//public Printvoid theclearLineCountFlags() results{
Arrays.fill(count, 0);
System.out.println("-------------------------------------------");
if (puzzleTable.size()==5){}
 
for (Iterator<LineOfPuzzle> it = puzzleTable.iterator(); it.hasNext();) {
public int getLineCountByOrderId(int lineOrderId) {
LineOfPuzzle puzzleLine = it.next();
return count[lineOrderId - 1];
System.out.println(puzzleLine.getWholeLine());
}
}else
System.out.println("Sorry, solution not found!");
}
// Recursively checks the input set to ensure each line has right neighbor.
// Neighbors can be of three type, left, right or undefined.
// Direction: -1 left, 0 undefined, 1 right
private static boolean recursiveSearch(LineOfPuzzle pzzlNodeLine,
PuzzleSet puzzleSet, int direction){
boolean validLeaf = false;
boolean hasNeighbor = false;
PuzzleSet<LineOfPuzzle> puzzleSubSet = null;
for (Iterator<LineOfPuzzle> it = puzzleSet.iterator(); it.hasNext();) {
LineOfPuzzle pzzlLeafLine = it.next();
validLeaf = false;
hasNeighbor = pzzlLeafLine.hasNeighbor(direction);
if (hasNeighbor){
puzzleSubSet = puzzleTable.getSimilarLines(pzzlLeafLine.getNeighbor(direction));
if (puzzleSubSet != null){
if (pzzlNodeLine !=null)
validLeaf = puzzleSubSet.contains(pzzlNodeLine);
else
validLeaf = recursiveSearch(pzzlLeafLine, puzzleSubSet, -1*direction);
}
else
validLeaf = false;
}
if (!validLeaf && pzzlLeafLine.hasNeighbor(-1*direction)){
hasNeighbor = true;
if (hasNeighbor){
puzzleSubSet = puzzleTable.getSimilarLines(pzzlLeafLine.getNeighbor(-1*direction));
if (puzzleSubSet != null){
if (pzzlNodeLine !=null)
validLeaf = puzzleSubSet.contains(pzzlNodeLine);
else
validLeaf = recursiveSearch(pzzlLeafLine, puzzleSubSet, direction);
}
else
validLeaf = false;
}
}
if (pzzlNodeLine != null && validLeaf)
return validLeaf;
if (pzzlNodeLine == null && hasNeighbor && !validLeaf){
it.remove();
}
 
static class PossibleLine {
if (pzzlNodeLine == null){
 
if (hasNeighbor && validLeaf){
Integer order;
puzzleSet.riseLineCountFlags(pzzlLeafLine.getOrder());
String }nation;
String if (!hasNeighbor){color;
String animal;
puzzleSet.riseLineCountFlags(pzzlLeafLine.getOrder());
String }drink;
String } cigarette;
 
}
returnPossibleLine validLeafrightNeighbor;
PossibleLine leftNeighbor;
Set<PossibleLine> neighbors = new LinkedHashSet<>();
 
public PossibleLine(Integer order, String nation, String color,
String animal, String drink, String cigarette) {
this.animal = animal;
this.cigarette = cigarette;
this.color = color;
this.drink = drink;
this.nation = nation;
this.order = order;
}
 
@Override
public boolean equals(Object obj) {
return obj instanceof PossibleLine
&& getWholeLine().equals(((PossibleLine) obj).getWholeLine());
}
 
public int getFactsCount() {
int facts = 0;
facts += order != null ? 1 : 0;
facts += nation != null ? 1 : 0;
facts += color != null ? 1 : 0;
facts += animal != null ? 1 : 0;
facts += cigarette != null ? 1 : 0;
facts += drink != null ? 1 : 0;
return facts;
}
 
private static int common(Object a, Object b) {
return a != null && Objects.equals(a, b) ? 1 : 0;
}
 
public int getCommonFactsCount(PossibleLine facts) {
return common(order, facts.order)
+ common(nation, facts.nation)
+ common(color, facts.color)
+ common(animal, facts.animal)
+ common(cigarette, facts.cigarette)
+ common(drink, facts.drink);
}
 
public void setLeftNeighbor(PossibleLine leftNeighbor) {
this.leftNeighbor = leftNeighbor;
this.leftNeighbor.order = order - 1;
}
 
public void setRightNeighbor(PossibleLine rightNeighbor) {
this.rightNeighbor = rightNeighbor;
this.rightNeighbor.order = order + 1;
}
 
public boolean hasNeighbor(int direction) {
return getNeighbor(direction) != null;
}
 
public PossibleLine getNeighbor(int direction) {
if (direction < 0)
return leftNeighbor;
else
return rightNeighbor;
}
 
public String getWholeLine() {
return order + " - " +
nation + " - " +
color + " - " +
animal + " - " +
drink + " - " +
cigarette;
}
 
@Override
public int hashCode() {
return Objects.hash(order, nation, color, animal, drink, cigarette);
}
 
public void merge(PossibleLine mergedLine) {
if (order == null) order = mergedLine.order;
if (nation == null) nation = mergedLine.nation;
if (color == null) color = mergedLine.color;
if (animal == null) animal = mergedLine.animal;
if (drink == null) drink = mergedLine.drink;
if (cigarette == null) cigarette = mergedLine.cigarette;
}
 
public PossibleLine copy() {
PossibleLine clone = new PossibleLine(order, nation, color, animal, drink, cigarette);
clone.leftNeighbor = leftNeighbor;
clone.rightNeighbor = rightNeighbor;
clone.neighbors = neighbors; // shallow copy
return clone;
}
}
}</syntaxhighlight>
}
</lang>
{{out}}
<pre>
Line 4,089 ⟶ 4,009:
 
'''Part 1''': Generic filters for unification and matching
<syntaxhighlight lang="jq">
<lang jq>
# Attempt to unify the input object with the specified object
def unify( object ):
Line 4,111 ⟶ 4,031:
| if $ans then .[i] = $ans else empty end
else empty
end ;</langsyntaxhighlight>
'''Part 2''': Zebra Puzzle
<langsyntaxhighlight lang="jq"># Each house is a JSON object of the form:
# { "number": _, "nation": _, "owns": _, "color": _, "drinks": _, "smokes": _}
 
Line 4,172 ⟶ 4,092:
;
zebra</langsyntaxhighlight>
{{Out}}
<div style="overflow:scroll; height:400px;">
<langsyntaxhighlight lang="sh">$ time jq -n -f zebra.jq
[
{
Line 4,222 ⟶ 4,142:
real 0m0.284s
user 0m0.260s
sys 0m0.005s</langsyntaxhighlight></div>
 
=={{header|Julia}}==
 
<syntaxhighlight lang="julia">
<lang Julia>
# Julia 1.0
using Combinatorics
Line 4,285 ⟶ 4,205:
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,300 ⟶ 4,220:
===Constraint Programming Version===
Using the rules from https://github.com/SWI-Prolog/bench/blob/master/zebra.pl
<langsyntaxhighlight Julialang="julia"># Julia 1.4
using JuMP
using GLPK
Line 4,375 ⟶ 4,295:
drinks=getindex.(m, 4),
smokes=getindex.(m, 5))
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,390 ⟶ 4,310:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.3
 
fun nextPerm(perm: IntArray): Boolean {
Line 4,503 ⟶ 4,423:
val plural = if (solutions == 1) "" else "s"
println("$solutions solution$plural found")
}</langsyntaxhighlight>
 
{{out}}
Line 4,523 ⟶ 4,443:
The Logtalk distribution includes a solution for a variant of this puzzle (here reproduced with permission):
 
<langsyntaxhighlight lang="logtalk">
/* Houses logical puzzle: who owns the zebra and who drinks water?
 
Line 4,600 ⟶ 4,520:
 
:- end_object.
</syntaxhighlight>
</lang>
 
Sample query:
<langsyntaxhighlight lang="text">
| ?- houses::(houses(S), print(S)).
h(norwegian,fox,kool,water,yellow)
Line 4,612 ⟶ 4,532:
 
S = [h(norwegian,fox,kool,water,yellow),h(ukrainian,horse,chesterfield,tea,blue),h(english,snake,winston,milk,red),h(japonese,zebra,kent,coffee,green),h(spanish,dog,lucky,juice,white)]
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
This creates a table that has 5 columns, and 25 rows. We fill the table; each column is the same and equal to all the options joined together in blocks of 5:
<pre> 1 2 3 4 5
Line 4,644 ⟶ 4,564:
This should be read as follows: Each column shows (in blocks of 5) the possible candidates of each kind (beverage, animal, smoke...)
We solve it now in a 'sudoku' way: We remove candidates iteratively until we are left with 1 candidate of each kind for each house.
<langsyntaxhighlight Mathematicalang="mathematica">ClearAll[EliminatePoss, FilterPuzzle]
EliminatePoss[ct_, key1_, key2_] := Module[{t = ct, poss1, poss2, poss, notposs},
poss1 = Position[t, key1];
Line 4,757 ⟶ 4,677:
 
bigtable = FixedPoint[FilterPuzzle, bigtable];
TableForm[DeleteCases[bigtable\[Transpose], Null, \[Infinity]], TableHeadings -> {Range[5], None}]</langsyntaxhighlight>
Using the command FixedPoint, we iteratively filter out these candidates, until we are (hopefully) left with 1 candidate per kind per house.
{{out}}
Line 4,766 ⟶ 4,686:
5 White Swede Beer Dog Blue Master</pre>
 
=={{header|Mercury}}==
<syntaxhighlight lang="mercury">:- module zebra.
:- interface.
 
:- import_module io.
 
:- pred main(io, io).
:- mode main(di, uo) is cc_multi. % or det for all-solutions
 
:- implementation.
 
:- import_module list.
:- import_module solutions.
 
% perm
 
:- pred my_perm(list(T), list(T)).
:- mode my_perm(in, out) is multi.
 
my_perm([], []).
my_perm([X | Xs], Perm) :-
my_perm(Xs, PermXs),
my_insert(X, PermXs, Perm).
 
:- pred my_insert(T, list(T), list(T)).
:- mode my_insert(in, in, out) is multi.
 
my_insert(X, [], [X]).
my_insert(X, [Y | Ys], Zs) :-
(
Zs = [X, Y | Ys]
;
my_insert(X, Ys, Zs0),
Zs = [Y | Zs0]
).
 
% The puzzle
 
:- type person
---> english
; spanish
; ukrainian
; norwegian
; japanese.
 
:- pred left_of(list(T), T, T).
:- mode left_of(in, in, in) is semidet.
 
left_of([A, B | _], A, B).
left_of([_ | List], A, B) :- left_of(List, A, B).
 
:- pred next_to(list(T), T, T).
:- mode next_to(in, in, in) is semidet.
 
next_to(List, A, B) :-
( left_of(List, A, B)
; left_of(List, B, A)
).
 
:- pred puzzle({list(person), list(person), list(person), list(person),
list(person)}).
:- mode puzzle(out) is nondet.
 
puzzle({Houses, Colours, Pets, Drinks, Smokes}) :-
% 10. The Norwegian lives in the first house.
First = norwegian,
perm([english, spanish, ukrainian, japanese],
[Second, Third, Fourth, Fifth]),
 
% 2. The Englishman lives in the red house.
Red = english,
perm([spanish, ukrainian, norwegian, japanese],
[Green, Ivory, Yellow, Blue]),
 
% 10. The Norwegian lives in the first house.
% 15. The Norwegian lives next to the blue house.
Second = Blue,
 
% 6. The green house is immediately to the right of the ivory house.
left_of(Houses, Ivory, Green),
 
% 3. The Spaniard owns the dog.
Dog = spanish,
perm([english, ukrainian, norwegian, japanese],
[Snails, Fox, Horse, Zebra]),
 
% 4. Coffee is drunk in the green house.
Green = Coffee,
 
% 5. The Ukrainian drinks tea.
Tea = ukrainian,
 
% 9. Milk is drunk in the middle house.
Milk = Third,
 
perm([english, spanish, norwegian, japanese],
[Coffee, Milk, Juice, Water]),
 
% 7. The Old Gold smoker owns snails.
Snails = OldGold,
 
% 8. Kools are smoked in the yellow house.
Kools = Yellow,
 
% 13. The Lucky Strike smoker drinks orange juice.
LuckyStrike = Juice,
 
% 14. The Japanese smokes Parliaments.
Parliament = japanese,
 
perm([english, spanish, ukrainian, norwegian],
[OldGold, Kools, Chesterfield, LuckyStrike]),
 
% 11. The man who smokes Chesterfields lives in the house
% next to the man with the fox.
next_to(Houses, Chesterfield, Fox),
 
% 12. Kools are smoked in the house next to the house
% where the horse is kept.
next_to(Houses, Kools, Horse),
 
Houses = [First, Second, Third, Fourth, Fifth],
Colours = [Red, Green, Ivory, Yellow, Blue],
Pets = [Dog, Snails, Fox, Horse, Zebra],
Drinks = [Coffee, Tea, Milk, Juice, Water],
Smokes = [OldGold, Kools, Chesterfield, LuckyStrike, Parliament].
 
% Printing a solution
 
:- pred write_solution({list(person), list(person), list(person),
list(person), list(person)}::in, io::di, io::uo) is det.
 
write_solution({Houses, Colours, Pets, Drinks, Smokes}, !IO) :-
write_string("--------\n", !IO),
write_assignments(["1st", "2nd", "3rd", "4th", "5th"],
Houses, !IO),
write_assignments(["red", "green", "ivory", "yellow", "blue"],
Colours, !IO),
write_assignments(["dog", "snails", "fox", "horse", "zebra"],
Pets, !IO),
write_assignments(["coffee", "tea", "milk", "juice", "water"],
Drinks, !IO),
write_assignments(["oldgold", "kools", "chesterfield",
"luckystrike", "parliament"], Smokes, !IO).
 
:- pred write_assignments(list(string)::in, list(person)::in,
io::di, io::uo) is det.
 
write_assignments(Labels, Persons, !IO) :-
foldl_corresponding(write_assignment, Labels, Persons, !IO),
nl(!IO).
 
:- pred write_assignment(string::in, person::in, io::di, io::uo) is det.
 
write_assignment(Label, Person, !IO) :-
write_string(Label, !IO),
write_string(" - ", !IO),
write(Person, !IO),
write_string("\n", !IO).
 
% main
 
main(!IO) :-
% Print all solutions.
/*
solutions(puzzle, Solutions),
foldl(write_solution, Solutions, !IO).
*/
 
% Print solutions as they are found.
/*
unsorted_aggregate(puzzle, write_solution, !IO).
*/
 
% Print one solution.
( if puzzle(Solution) then
write_solution(Solution, !IO)
else
write_string("No solution found.\n", !IO)
).
</syntaxhighlight>
{{out}}
<pre>--------
1st - norwegian
2nd - ukrainian
3rd - english
4th - spanish
5th - japanese
 
red - english
green - japanese
ivory - spanish
yellow - norwegian
blue - ukrainian
 
dog - spanish
snails - english
fox - norwegian
horse - ukrainian
zebra - japanese
 
coffee - japanese
tea - ukrainian
milk - english
juice - spanish
water - norwegian
 
oldgold - english
kools - norwegian
chesterfield - ukrainian
luckystrike - spanish
parliament - japanese</pre>
=={{header|MiniZinc}}==
<syntaxhighlight lang="minizinc">
<lang MiniZinc>
%Solve Zebra Puzzle. Nigel Galloway, August 27th., 2019
include "alldifferent.mzn";
Line 4,797 ⟶ 4,929:
solve satisfy;
output ["The "++show(Nz[n])++" owns the zebra"++"\n\n"++show(Nz)++"\n"++show(Iz)++"\n"++show(Gz)++"\n"++show(Ez)++"\n"++show(Lz)++"\n"];
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 4,817 ⟶ 4,949:
be pasted into the REPL.
 
<syntaxhighlight lang="nial">
<lang Nial>
remove is op x xs {filter (not (x =)) xs}
 
Line 4,873 ⟶ 5,005:
 
abs(time - (run; time))
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,891 ⟶ 5,023:
</pre>
 
=={{header|Pari/GpNim}}==
 
<lang pari/gp>
Using the same order for test of criteria as in Kotlin solution.
 
<syntaxhighlight lang="nim">import algorithm, strformat, sequtils
 
type
 
Color {.pure.} = enum Blue, Green, Red, White, Yellow
Person {.pure.} = enum Dane, English, German, Norwegian, Swede
Pet {.pure.} = enum Birds, Cats, Dog, Horse, Zebra
Drink {.pure.} = enum Beer, Coffee, Milk, Tea, Water
Cigarettes {.pure.} = enum Blend, BlueMaster = "Blue Master",
Dunhill, PallMall = "Pall Mall", Prince
 
House = tuple
color: Color
person: Person
pet: Pet
drink: Drink
cigarettes: Cigarettes
 
Houses = array[5, House]
 
 
iterator permutations[T](): array[5, T] =
## Yield the successive permutations of values of type T.
var term = [T(0), T(1), T(2), T(3), T(4)]
yield term
while term.nextPermutation():
yield term
 
 
proc findSolutions(): seq[Houses] =
## Return all the solutions.
 
for colors in permutations[Color]():
if colors.find(White) != colors.find(Green) + 1: continue # 5
for persons in permutations[Person]():
if persons[0] != Norwegian: continue # 10
if colors.find(Red) != persons.find(English): continue # 2
if abs(persons.find(Norwegian) - colors.find(Blue)) != 1: continue # 15
for pets in permutations[Pet]():
if persons.find(Swede) != pets.find(Dog): continue # 3
for drinks in permutations[Drink]():
if drinks[2] != Milk: continue # 9
if persons.find(Dane) != drinks.find(Tea): continue # 4
if colors.find(Green) != drinks.find(Coffee): continue # 6
for cigarettes in permutations[Cigarettes]():
if cigarettes.find(PallMall) != pets.find(Birds): continue # 7
if cigarettes.find(Dunhill) != colors.find(Yellow): continue # 8
if cigarettes.find(BlueMaster) != drinks.find(Beer): continue # 13
if cigarettes.find(Prince) != persons.find(German): continue # 14
if abs(cigarettes.find(Blend) - pets.find(Cats)) != 1: continue # 11
if abs(cigarettes.find(Dunhill) - pets.find(Horse)) != 1: continue # 12
if abs(cigarettes.find(Blend) - drinks.find(Water)) != 1: continue # 16
var houses: Houses
for i in 0..4:
houses[i] = (colors[i], persons[i], pets[i], drinks[i], cigarettes[i])
result.add houses
 
let solutions = findSolutions()
echo "Number of solutions: ", solutions.len
let sol = solutions[0]
echo()
 
echo "Number Color Person Pet Drink Cigarettes"
echo "—————— —————— ————————— ————— —————— ———————————"
for i in 0..4:
echo &"{i + 1:3} {sol[i].color:6} {sol[i].person:9} ",
&"{sol[i].pet:5} {sol[i].drink:6} {sol[i].cigarettes: 11}"
 
let owner = sol.filterIt(it.pet == Zebra)[0].person
echo &"\nThe {owner} owns the zebra."</syntaxhighlight>
 
{{out}}
<pre>Number of solutions: 1
 
Number Color Person Pet Drink Cigarettes
—————— —————— ————————— ————— —————— ———————————
1 Yellow Norwegian Cats Water Dunhill
2 Blue Dane Horse Tea Blend
3 Red English Birds Milk Pall Mall
4 Green German Zebra Coffee Prince
5 White Swede Dog Beer Blue Master
 
The German owns the zebra.</pre>
 
=={{header|PARI/GP}}==
<syntaxhighlight lang="none">
perm(arr) = {
n=#arr;i=n-1;
Line 4,944 ⟶ 5,164:
for(i=1,5,printf("House:%s %6s %10s %10s %10s %10s\n",i,colors[c][i],nations[n][i],pets[p][i],drinks[d][i],smokes[s][i]));\
)))))))));
</syntaxhighlight>
</lang>
 
{{out}}
Line 4,960 ⟶ 5,180:
=={{header|Perl}}==
Basically the same idea as C, though of course it's much easier to have Perl generate Perl code.
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
 
use utf8;
Line 5,063 ⟶ 5,283:
pair qw( water blend -1 1 );
 
$solve->();</langsyntaxhighlight>
 
Incidentally, the same logic can be used to solve the dwelling problem, if somewhat awkwardly:
<langsyntaxhighlight lang="perl">...
# property names and values
setprops
Line 5,086 ⟶ 5,306:
pair qw(cooper fletcher 4 3 2 -2 -3 -4);
 
$solve->();</langsyntaxhighlight>
 
=={{header|Phix}}==
<!--<lang Phix>(phixonline)-->
<syntaxhighlight lang="phix">
<span style="color: #008080;">enum</span> <span style="color: #000000;">Colour</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Nationality</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Drink</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">Pet</span>
--enum colour, nationality, drink, smoke, pet -- (now implicit)
<span style="color: #008080;">constant</span> <span style="color: #000000;">Colours</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"red"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"white"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"green"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"yellow"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"blue"</span><span style="color: #0000FF;">},</span>
enum red,white,green,yellow,blue
<span style="color: #000000;">Nationalities</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"English"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Swede"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Dane"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Norwegian"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"German"</span><span style="color: #0000FF;">},</span>
enum English,Swede,Dane,Norwegian,German
<span style="color: #000000;">Drinks</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"tea"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"coffee"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"milk"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"beer"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"water"</span><span style="color: #0000FF;">},</span>
enum tea,coffee,milk,beer,water
<span style="color: #000000;">Smokes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"Pall Mall"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Dunhill"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Blend"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Blue Master"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Prince"</span><span style="color: #0000FF;">},</span>
enum PallMall,Dunhill,Blend,BlueMaster,Prince
<span style="color: #000000;">Pets</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"dog"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"birds"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cats"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"horse"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"zebra"</span><span style="color: #0000FF;">},</span>
enum dog,birds,cats,horse,zebra
<span style="color: #000000;">Sets</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">Colours</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Nationalities</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Drinks</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Smokes</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Pets</span><span style="color: #0000FF;">}</span>
 
constant colours = {"red","white","green","yellow","blue"},
<span style="color: #008080;">constant</span> <span style="color: #000000;">tagset5</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- {1,2,3,4,5}, oft-permuted</span>
nationalities = {"English","Swede","Dane","Norwegian","German"},
<span style="color: #004080;">sequence</span> <span style="color: #000000;">perm</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tagset5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- perm[1] is Colour of each house, etc</span>
drinks = {"tea","coffee","milk","beer","water"},
smokes = {"Pall Mall","Dunhill","Blend","Blue Master","Prince"},
<span style="color: #008080;">function</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">)</span>
pets = {"dog","birds","cats","horse","zebra"},
<span style="color: #008080;">return</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">Sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
sets = {colours,nationalities,drinks,smokes,pets}
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant p5 = permutes(tagset(5)), -- all permutes of {1,2,3,4,5},
<span style="color: #008080;">function</span> <span style="color: #000000;">left_of</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">h1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">h2</span><span style="color: #0000FF;">)</span>
lp = length(p5) -- (== factorial(5), ie 120)
<span style="color: #008080;">return</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">h1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">h2</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
// In the following, c1,c2 are indexes to p5, for colour..pet,
// and v1,v2 are from their corresponding enums, so eg p5[c1]
<span style="color: #008080;">function</span> <span style="color: #000000;">next_to</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">h1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">h2</span><span style="color: #0000FF;">)</span>
// might be {1,4,3,2,5} for the colours of 1..5 and finding
<span style="color: #008080;">return</span> <span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h1</span><span style="color: #0000FF;">-</span><span style="color: #000000;">h2</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">1</span>
// v1 in that gives us a house number. Checking the specified
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
// condition, eg [h] == green && [h+1] == white is then easy.
 
<span style="color: #008080;">procedure</span> <span style="color: #000000;">print_house</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
function left_of(integer c1, v1, c2, v2)
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d:%s,%s,%s,%s,%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span>
integer h = find(v1,p5[c1])
<span style="color: #000000;">Colours</span><span style="color: #0000FF;">[</span><span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]],</span>
return h<=4 and p5[c2][h+1]=v2
<span style="color: #000000;">Nationalities</span><span style="color: #0000FF;">[</span><span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]],</span>
end function
<span style="color: #000000;">Drinks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Drink</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]],</span>
 
<span style="color: #000000;">Smokes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]],</span>
function same_house(integer c1, v1, c2, v2)
<span style="color: #000000;">Pets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Pet</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]})</span>
integer h = find(v1,p5[c1])
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
return p5[c2][h]=v2
end function
<span style="color: #004080;">integer</span> <span style="color: #000000;">solutions</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">solperms</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
function next_to(integer c1, v1, c2, v2)
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
integer h1 = find(v1,p5[c1]),
<span style="color: #008080;">constant</span> <span style="color: #000000;">factorial5</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
h2 = find(v2,p5[c2])
<span style="color: #008080;">for</span> <span style="color: #000000;">C</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">factorial5</span> <span style="color: #008080;">do</span>
return abs(h1-h2)=1
<span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tagset5</span><span style="color: #0000FF;">)</span>
end function
<span style="color: #008080;">if</span> <span style="color: #000000;">left_of</span><span style="color: #0000FF;">(</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"green"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"white"</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">N</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">factorial5</span> <span style="color: #008080;">do</span>
procedure print_house(integer n, sequence perm)
<span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">N</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tagset5</span><span style="color: #0000FF;">)</span>
sequence args = {n}
<span style="color: #008080;">if</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Norwegian"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">1</span>
for i,p in perm do
<span style="color: #008080;">and</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"English"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"red"</span><span style="color: #0000FF;">)</span>
args = append(args,sets[i][p5[p][n]])
<span style="color: #008080;">and</span> <span style="color: #000000;">next_to</span><span style="color: #0000FF;">(</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Norwegian"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"blue"</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">D</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">factorial5</span> <span style="color: #008080;">do</span>
printf(1,"House %d: %|7s %|10s %|6s %|12s %=6s\n",args)
<span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Drink</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">D</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tagset5</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #008080;">if</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Dane"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Drink</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tea"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Drink</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"coffee"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"green"</span><span style="color: #0000FF;">)</span>
integer ns = 0
<span style="color: #008080;">and</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Drink</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"milk"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span>
atom t0 = time()
<span style="color: #008080;">for</span> <span style="color: #000000;">S</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">factorial5</span> <span style="color: #008080;">do</span>
for colour=1 to lp do
<span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">S</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tagset5</span><span style="color: #0000FF;">)</span>
if left_of(colour,green,colour,white) then
<span style="color: #008080;">if</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Colour</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"yellow"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Dunhill"</span><span style="color: #0000FF;">)</span>
for nationality=1 to lp do
<span style="color: #008080;">and</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"German"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Prince"</span><span style="color: #0000FF;">)</span>
if p5[nationality][1]=Norwegian -- Norwegian lives in 1st house
<span style="color: #008080;">and</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Blue Master"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Drink</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"beer"</span><span style="color: #0000FF;">)</span>
and same_house(nationality,English,colour,red)
<span style="color: #008080;">and</span> <span style="color: #000000;">next_to</span><span style="color: #0000FF;">(</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Drink</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"water"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Blend"</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
and next_to(nationality,Norwegian,colour,blue) then
<span style="color: #008080;">for</span> <span style="color: #000000;">P</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">factorial5</span> <span style="color: #008080;">do</span>
for drink=1 to lp do
<span style="color: #000000;">perm</span><span style="color: #0000FF;">[</span><span style="color: #000000;">Pet</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">permute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">P</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tagset5</span><span style="color: #0000FF;">)</span>
if same_house(nationality,Dane,drink,tea)
<span style="color: #008080;">if</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Nationality</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Swede"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Pet</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dog"</span><span style="color: #0000FF;">)</span>
and same_house(drink,coffee,colour,green)
<span style="color: #008080;">and</span> <span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Pall Mall"</span><span style="color: #0000FF;">)==</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Pet</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"birds"</span><span style="color: #0000FF;">)</span>
and p5[drink][3]=milk then -- middle house drinks milk
<span style="color: #008080;">and</span> <span style="color: #000000;">next_to</span><span style="color: #0000FF;">(</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Blend"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Pet</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"cats"</span><span style="color: #0000FF;">))</span>
for smoke=1 to lp do
<span style="color: #008080;">and</span> <span style="color: #000000;">next_to</span><span style="color: #0000FF;">(</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Pet</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"horse"</span><span style="color: #0000FF;">),</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Smoke</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Dunhill"</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">then</span>
if same_house(colour,yellow,smoke,Dunhill)
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">5</span> <span style="color: #008080;">do</span>
and same_house(nationality,German,smoke,Prince)
<span style="color: #000000;">print_house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
and <span style="color: #008080;">end</span> <span style="color: #008080;">for</span>same_house(smoke,BlueMaster,drink,beer)
and next_to(drink,water,smoke,Blend) then
<span style="color: #000000;">solutions</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
for pet=1 to lp do
<span style="color: #000000;">solperms</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solperms</span><span style="color: #0000FF;">,</span><span style="color: #000000;">perm</span><span style="color: #0000FF;">)</span>
if <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>same_house(nationality,Swede,pet,dog)
<span style="color: #008080;">end</span> <spanand style="color: #008080;">for</span>same_house(smoke,PallMall,pet,birds)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> and next_to(smoke,Blend,pet,cats)
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> and next_to(pet,horse,smoke,Dunhill) then
<span style="color: #008080;">end</span> <span style for i="color:1 to 5 #008080;">if</span>do
print_house(i,{colour,nationality,drink,smoke,pet})
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
integer z = p5[nationality][find(zebra,p5[pet])]
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
printf(1,"The %s owns the Zebra\n",{nationalities[z]})
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
ns += 1
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end if
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d solution%s found (%3.3fs).\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
end for
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solperms</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
end if
<span style="color: #000000;">perm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">solperms</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
end for
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The %s owns the Zebra\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">Nationalities</span><span style="color: #0000FF;">[</span><span style="color: #000000;">house</span><span style="color: #0000FF;">(</span><span style="color: #000000;">Pet</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"zebra"</span><span style="color: #0000FF;">)]})</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<!--</lang>-->
end if
end for
end if
end for
printf(1,"%d solution%s found (%3.3fs).\n",{ns,iff(ns>1,"s",""),time()-t0})
</syntaxhighlight>
{{out}}
<pre>
House 1: yellow, Norwegian, water, Dunhill, cats
House 2: blue, Dane, tea, Blend, horse
House 3: red, English, milk, Pall Mall, birds
House 4: green, German, coffee, Prince, zebra
House 5: white, Swede, beer, Blue Master, dog
1 solution found (0.016s).
The German owns the Zebra
1 solution found (0.000s).
</pre>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">import cp.
 
main =>
Nat = [English, Swede, Dane, German, Norwegian],
Color = [Red, Green, White, Yellow, Blue],
Smoke = [PallMall, Dunhill, Blend, SBlue, Prince],
Pet = [Dog, Bird, Cat, Horse, Zebra],
Drink = [Tea, Coffee, Milk, Beer, Water],
 
Nat :: 1..5,
Color :: 1..5,
Smoke :: 1..5,
Pet :: 1..5,
Drink :: 1..5,
 
all_different(Nat),
all_different(Color),
all_different(Smoke),
all_different(Pet),
all_different(Drink),
 
English = Red,
Swede = Dog,
Dane = Tea,
Green #= White-1,
Coffee = Green,
Bird = PallMall,
Yellow = Dunhill,
Milk = 3,
Norwegian = 1,
abs(Blend-Cat) #= 1,
abs(Dunhill-Horse) #= 1,
SBlue = Beer,
German = Prince,
abs(Norwegian-Blue) #= 1,
abs(Blend-Water) #= 1,
 
solve(Nat ++ Color ++ Smoke ++ Pet ++ Drink),
 
L = [English=english,
Swede=swede,
Dane=dane,
German=german,
Norwegian=norwegian].sort(),
member(Zebra=ZebraOwner, L),
writef("The %w owns the zebra\n", ZebraOwner),
writeln(L).
</syntaxhighlight>
{{out}}
<pre>
The german owns the zebra
[1 = norwegian,2 = dane,3 = english,4 = german,5 = swede]
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(be match (@House @Person @Drink @Pet @Cigarettes)
(permute (red blue green yellow white) @House)
(left-of @House white @House green)
Line 5,224 ⟶ 5,505:
 
(be next-to (@X @A @Y @B) (right-of @X @A @Y @B))
(be next-to (@X @A @Y @B) (left-of @X @A @Y @B))</langsyntaxhighlight>
Test:
<langsyntaxhighlight PicoLisplang="picolisp">(pilog '((match @House @Person @Drink @Pet @Cigarettes))
(let Fmt (-8 -11 -8 -7 -11)
(tab Fmt "HOUSE" "PERSON" "DRINKS" "HAS" "SMOKES")
(mapc '(@ (pass tab Fmt))
@House @Person @Drink @Pet @Cigarettes ) ) )</langsyntaxhighlight>
Output:
<pre>HOUSE PERSON DRINKS HAS SMOKES
Line 5,243 ⟶ 5,524:
In Prolog we can specify the domain by selecting elements from it, making mutually exclusive choices for efficiency:
 
<langsyntaxhighlight Prologlang="prolog">select([A|As],S):- select(A,S,S1),select(As,S1).
select([],_).
Line 5,263 ⟶ 5,544:
 
:- ?- time(( zebra(Who, HS), maplist(writeln,HS), nl, write(Who), nl, nl, fail
; write('No more solutions.') )).</langsyntaxhighlight>
 
Output:
Line 5,286 ⟶ 5,567:
Using extensible records, letting the houses' attributes be discovered from rules, ''not'' predetermined by a programmer (as any ''"a house has five attributes"'' solution is doing).
 
<langsyntaxhighlight Prologlang="prolog">% attribute store is 'Name - Value' pairs with unique names
attrs( H, [N-V | R]) :- !, memberchk( N-X, H), X = V, (R = [], ! ; attrs( H, R)).
attrs( HS, AttrsL) :- maplist( attrs, HS, AttrsL).
Line 5,315 ⟶ 5,596:
, [[drink -water ], [smoke-'Blend' ]] % 16
] ),
in( Houses, [owns-zebra, nation-Owner]).</langsyntaxhighlight>
[http://ideone.com/wcwXfZ Output]:
<langsyntaxhighlight Prologlang="prolog">?- time(( zebra(Z,HS), (maplist(length,HS,_) -> maplist(sort,HS,S),
maplist(writeln,S),nl,writeln(Z)), false ; writeln('No More Solutions'))).
Line 5,329 ⟶ 5,610:
german
No More Solutions
% 263,486 inferences, 0.047 CPU in 0.063 seconds (74% CPU, 5630007 Lips)</langsyntaxhighlight>
 
===Alternative version===
{{Works with|GNU Prolog}}
{{Works with|SWI Prolog}}
<langsyntaxhighlight lang="prolog">:- initialization(main).
 
 
Line 5,379 ⟶ 5,660:
 
main :- findall(_, (zebra(_), nl), _), halt.
</syntaxhighlight>
</lang>
{{Output}}
<pre>h(yellow,nvg,cats,water,dh)
Line 5,393 ⟶ 5,674:
{{Works with|SWI Prolog}}
Original source code is 'ECLiPSe ( http://eclipseclp.org/ )' example: http://eclipseclp.org/examples/zebra.ecl.txt
<langsyntaxhighlight lang="prolog">:- use_module(library(clpfd)).
 
zebra :-
Line 5,447 ⟶ 5,728:
format(Fmt, PetNames),
format(Fmt, DrinkNames).
</syntaxhighlight>
</lang>
{{Output}}
<pre>
Line 5,460 ⟶ 5,741:
{{trans|Clojure}}
Using 'logpy': https://github.com/logpy/logpy
<langsyntaxhighlight lang="python">
from logpy import *
from logpy.core import lall
Line 5,534 ⟶ 5,815:
for line in solutions[0]:
print str(line)
</syntaxhighlight>
</lang>
 
===Alternative Version===
{{trans|D}}
<langsyntaxhighlight lang="python">import psyco; psyco.full()
 
class Content: elems= """Beer Coffee Milk Tea Water
Line 5,638 ⟶ 5,919:
solve(M, Test.Drink, 5)
 
main()</langsyntaxhighlight>
{{out}}
<pre> One: Water Norwegian Yellow Dunhill Cat
Line 5,647 ⟶ 5,928:
Runtime about 0.18 seconds.
===Alternative Version===
<langsyntaxhighlight lang="python">from itertools import permutations
 
class Number:elems= "One Two Three Four Five".split()
Line 5,697 ⟶ 5,978:
print
 
main()</langsyntaxhighlight>
Output:
<pre>Found a solution:
Line 5,710 ⟶ 5,991:
Using 'python-constraint': http://labix.org/python-constraint,
Original source code is 'ECLiPSe ( http://eclipseclp.org/ )' example: http://eclipseclp.org/examples/zebra.ecl.txt
<syntaxhighlight lang ="python">from constraint import *'''
Improved version: Instead of simple variables (a, b),
more intelligible and readable (?) variables are employed.
'''
def doc1():
'''
There are five houses.
The English man lives in the red house.
The Swede has a dog.
The Dane drinks tea.
The green house is immediately to the left of the white house.
They drink coffee in the green house.
The man who smokes Pall Mall has a bird.
In the yellow house they smoke Dunhill.
In the middle house they drink milk.
The Norwegian lives in the first house.
The man who smokes Blend lives in the house next to the house with a cat.
In a house next to the house where they have a horse, they smoke Dunhill.
The man who smokes Blue Master drinks beer.
The German smokes Prince.
The Norwegian lives next to the blue house.
They drink water in a house next to the house where they smoke Blend.
 
The solution:
problem = Problem()
 
Nation: Norwegian Dane = ["Englishman", "Spaniard", "Japanese", German "Ukrainian", "Norwegian" ]Swede
Color: = ["Red", Yellow "Green", Blue "White", "Yellow",Red "Blue" Green ] White
Smoke: Dunhill Blend PallMall Prince BlueMaster
Smoke = ["Oldgold", "Kools", "Chesterfield", "Luckystrike", "Parliament"]
Pet = ["Dog", Pet: "Snails", "Fox", Cat "Horse", " Bird Zebra" ] Dog
Drink: = ["Tea", Water "Coffee", "Milk", Tea "Orangejuice", "Water"Milk Coffee ]Beer
'''
 
import os
print(os.system('cls') if os.name == 'nt' else os.system('clear'))
 
print(doc1.__doc__)
input('<key>')
 
from constraint import *
 
p = Problem()
 
Nation = ['Englishman', 'Dane', 'German', 'Norwegian', 'Swede']
Color = [ 'Blue', 'Green', 'Red', 'White', 'Yellow']
Smoke = [ 'Blend', 'BlueMaster', 'Dunhill', 'PallMall', 'Prince']
Pet = [ 'Bird', 'Cat', 'Dog', 'Horse', 'Zebra']
Drink = [ 'Beer', 'Coffee', 'Milk', 'Tea', 'Water']
 
# add variables: house numbers 1 to 5
problemp.addVariables(Nation, range(1,5+16))
problemp.addVariables(Color, range(1,5+16))
problemp.addVariables(Smoke, range(1,5+16))
problemp.addVariables(Pet, range(1,5+16))
problemp.addVariables(Drink, range(1,5+16))
 
# add constraint: the values in each list are exclusive
problemp.addConstraint(AllDifferentConstraint(), Nation)
problemp.addConstraint(AllDifferentConstraint(), Color)
problemp.addConstraint(AllDifferentConstraint(), Smoke)
problemp.addConstraint(AllDifferentConstraint(), Pet)
problemp.addConstraint(AllDifferentConstraint(), Drink)
 
# add constraint: actual constraints
# The English man lives in the red house.
problem.addConstraint(lambda a, b: a == b, ["Englishman", "Red" ])
p.addConstraint(
problem.addConstraint(lambda a, b: a == b, ["Spaniard", "Dog" ])
lambda house_englishman, red:
problem.addConstraint(lambda a, b: a == b, ["Green", "Coffee" ])
house_englishman is red,
problem.addConstraint(lambda a, b: a == b, ["Ukrainian", "Tea" ])
['Englishman', 'Red'])
problem.addConstraint(lambda a, b: a == b + 1, ["Green", "White" ])
 
problem.addConstraint(lambda a, b: a == b, ["Oldgold", "Snails" ])
# The Swede has a dog.
problem.addConstraint(lambda a, b: a == b, ["Yellow", "Kools" ])
p.addConstraint(
problem.addConstraint(lambda a: a == 3, ["Milk" ])
lambda pet_swede, dog:
problem.addConstraint(lambda a: a == 1, ["Norwegian" ])
problem.addConstraint(lambda a, b: a ==pet_swede is dog, b - 1 or a == b + 1, ["Chesterfield", "Fox" ])
['Swede', 'Dog'])
problem.addConstraint(lambda a, b: a == b - 1 or a == b + 1, ["Kools", "Horse" ])
 
problem.addConstraint(lambda a, b: a == b, ["Luckystrike", "Orangejuice"])
# The Dane drinks tea.
problem.addConstraint(lambda a, b: a == b, ["Japanese", "Parliament" ])
p.addConstraint(
problem.addConstraint(lambda a, b: a == b - 1 or a == b + 1, ["Norwegian", "Blue" ])
lambda drink_dane, tea:
drink_dane is tea,
['Dane', 'Tea'])
 
# The green house is immediately to the left of the white house.
p.addConstraint(
lambda green_house, white_house:
# Houses 1 .. 5 -> green house is 1 lower than white house
green_house is white_house - 1,
['Green', 'White'])
 
# They drink coffee in the green house.
p.addConstraint(
lambda drink_green_house, coffee:
drink_green_house is coffee,
['Green', 'Coffee'])
 
# The man who smokes Pall Mall has a bird.
p.addConstraint(
lambda pet_of_pallmall_smoker, a_bird:
pet_of_pallmall_smoker is a_bird,
['PallMall', 'Bird'])
 
# In the yellow house they smoke Dunhill.
p.addConstraint(
lambda owner_yellow_house, dunhill_smoker:
owner_yellow_house is dunhill_smoker,
['Yellow', 'Dunhill'])
 
# In the middle house they drink milk.
p.addConstraint(
lambda house_number_milk_drinker:
house_number_milk_drinker is 3,
['Milk'])
 
# The Norwegian lives in the first house.
p.addConstraint(
lambda house_number_norwegian:
house_number_norwegian is 1,
['Norwegian'])
 
# The man who smokes Blend lives in the house next to the house with a cat.
p.addConstraint(
lambda house_number_blend_smoker, number_of_house_with_cat:
# next -> housenumber +/- 1
house_number_blend_smoker is number_of_house_with_cat + 1 or
house_number_blend_smoker is number_of_house_with_cat - 1,
['Blend', 'Cat'])
 
# In a house next to the house where they have a horse, they smoke Dunhill.
p.addConstraint(
lambda house_number_dunhill_smoker, number_of_house_with_horse:
# next -> housenumber +/- 1
house_number_dunhill_smoker is number_of_house_with_horse + 1 or
house_number_dunhill_smoker is number_of_house_with_horse - 1,
['Dunhill', 'Horse'])
 
# The man who smokes Blue Master drinks beer.
p.addConstraint(
lambda drink_bluemaster_smoker, beer:
drink_bluemaster_smoker is beer,
['BlueMaster', 'Beer'])
 
# The German smokes Prince.
p.addConstraint(
lambda prince_smoker, german:
prince_smoker is german,
['Prince', 'German'])
 
# The Norwegian lives next to the blue house.
p.addConstraint(
lambda house_number_norwegian, house_number_blue_house:
house_number_norwegian is house_number_blue_house + 1 or
house_number_norwegian is house_number_blue_house - 1,
['Norwegian', 'Blue'])
 
# They drink water in a house next to the house where they smoke Blend.
p.addConstraint(
lambda house_number_water_drinker, house_number_blend_smoker:
house_number_water_drinker is house_number_blend_smoker + 1 or
house_number_water_drinker is house_number_blend_smoker - 1,
['Water', 'Blend'])
 
# get solution
sol = problemp.getSolution()
 
# print the answers
nation = ["'Nation"' if i == 0 else ""'' for i in range(6)]
color = ["'Color"' if i == 0 else ""'' for i in range(6)]
smoke = ["'Smoke"' if i == 0 else ""'' for i in range(6)]
pet = ["'Pet"' if i == 0 else ""'' for i in range(6)]
drink = ["'Drink"' if i == 0 else ""'' for i in range(6)]
 
for n in Nation:
for n in Nation: nation[sol[n]] = n
for n in Color: color[sol[n]] = n
for n in colorSmoke: smoke[sol[n]] = n
for n in Smoke Pet: pet[sol[n]] = n
for n in smokeDrink: drink[sol[n]] = n
 
for n in Pet:
# put the answers in the correct order of solution
pet[sol[n]] = n
print('\n\n', 'The calculated solution:', '\n')
for n in Drink:
 
drink[sol[n]] = n
for dr in [nation, color, smoke, pet, drink]:
print(f'{r[0]:>13s}: ', end='')
print("%6s: %14s%14s%14s%14s%14s" % (d[0], d[1], d[2], d[3], d[4], d[5]))
for i in range(1, 6):
</lang>
print(f'{r[i]:>14s}',end='')
print()
print()
</syntaxhighlight>
Output:
<pre>Nation: Nation: Norwegian Ukrainian Dane Englishman SpaniardGerman JapaneseSwede
Color: Color: Yellow Yellow Blue Blue Red Green White GreenWhite
Smoke: Smoke: Dunhill Kools Chesterfield Blend PallMall Oldgold Luckystrike Prince ParliamentBlueMaster
Pet: Pet: Fox Cat Horse Horse Snails Bird Zebra Dog ZebraDog
Drink: Drink: Water Water Tea Tea Milk Orangejuice Coffee Coffee</pre> Beer
</pre>
 
=={{header|R}}==
{{libheader|combinat}}<langsyntaxhighlight Rlang="r">
 
library(combinat)
Line 5,861 ⟶ 6,267:
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 5,876 ⟶ 6,282:
{{trans|Prolog}}
 
<langsyntaxhighlight lang="racket">#lang racket
 
(require racklog)
Line 5,932 ⟶ 6,338:
(%member (list (_) Owns 'zebra (_) (_)) HS)]))
 
(%which (Who HS) (%zebra Who HS))</langsyntaxhighlight>
 
Output:
Line 5,948 ⟶ 6,354:
(formerly Perl 6)
A rule driven approach:
<syntaxhighlight lang="raku" perl6line>my Hash @houses = (1 .. 5).map: { %(:num($_)) }; # 1 there are five houses
 
my @facts = (
Line 5,972 ⟶ 6,378:
for gather solve(@houses, @facts) {
#-- output
say .[0].pairshead.sort.map(*.key.uc.fmt("%-9s")).join(' | ');
say .pairs.sort.map(*.value.fmt("%-9s")).join(' | ')
for .list;
last; # stop after first solution
Line 5,979 ⟶ 6,385:
}
 
#| found a solution has been found that fits all the facts
multi sub solve(@solution, @facts [ ]) {
take @solution;
}
 
#| extend athis scenario to coverfit the next fact
multi sub solve(@scenario, [ $fact, *@facts ] is copy) {
for gather choicesmatch(@scenario, |$fact) -> @houses {
solve(@$_houses, @facts)
}
}
 
#| find all possible solutions for pairs of houses with
#| %aproperties attributes%b, left of a house with %bproperties attributes%a
multi sub choicesmatch(@houses, :Left-Of(%ba)!, *%ab) {
myfor 1 ..^ @scenarios;houses {
for my %left-house := @houses {[$_-1];
my $idx%right-house := .<num> - 1@houses[$_];
if $idx > 0 && plausible(@houses[$idx-1], %a) && plausible(@houses[$idx], %b) {
if plausible(%left-house, %a) && plausible(%right-house, %b) {
my @scenario = @houses.clone;
@scenario[$idxtemp %left-1]house = %( %(@houses[$idx-1]),= %a );
@scenario[$idx] =temp %(right-house %(@houses[$idx]),= %b );
take @scenariohouses;
}
}
}
 
#| match these houses are next to each other (left or right)
#| find all possible pairs of houses with %a attributes, either side
multi sub match(@houses, :Next-To(%b)!, *%a ) {
#! of a house with %b attributes
multi sub choices match(@houses, |%a, :NextLeft-ToOf(%b)!, *%a ) {;
choicesmatch(@houses, |%ab, :Left-Of(%ba) );
choices(@houses, |%b, :Left-Of(%a) );
}
 
#| find all possible houses that match the given attributesproperties
multi sub choicesmatch(@houses, *%factprops) {
for @houses.grep({plausible($_, %factprops)}) -> $%house {
mytemp @scenario%house ,= @houses.clone%props;
mytake $idx = $house<num> - 1@houses;
@scenario[$idx] = %( %$house, %fact );
take @scenario;
}
}
 
#| plausible if doesn't conflict with anything
sub plausible(%house, %attsprops) {
all! %attsprops.keys.mapfirst: { (%house{$_.key}:!exists) ||&& %house{$_.key} eqne %atts{$_}.value };
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 6,043 ⟶ 6,446:
{{trans|BBC BASIC}}
Permutations algorithm taken from REXX
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* Solve the Zebra Puzzle
*--------------------------------------------------------------------*/
Line 6,211 ⟶ 6,614:
out:
Say arg(1)
Return</langsyntaxhighlight>
{{out}}
<pre>House Drink Nation Colour Smoke Animal
Line 6,223 ⟶ 6,626:
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">CONTENT = { House: '',
Nationality: %i[English Swedish Danish Norwegian German],
Colour: %i[Red Green White Blue Yellow],
Line 6,276 ⟶ 6,679:
end
 
solve_zebra_puzzle</langsyntaxhighlight>
 
{{out}}
Line 6,292 ⟶ 6,695:
 
===Another approach===
<langsyntaxhighlight lang="ruby">
class String; def brk; split(/(?=[A-Z])/); end; end
men,drinks,colors,pets,smokes = "NorwegianGermanDaneSwedeEnglish
Line 6,317 ⟶ 6,720:
puts "The #{x.find{|y|y[0]=="Zebra"}[1]} owns the zebra.",
x.map{|y| y.map{|z| z.ljust(11)}.join}}}}}}
</syntaxhighlight>
</lang>
Output:
<pre>
Line 6,330 ⟶ 6,733:
=={{header|Scala}}==
===Idiomatic (for comprehension)===
<langsyntaxhighlight Scalalang="scala">/* Note to the rules:
*
* It can further concluded that:
Line 6,407 ⟶ 6,810:
members.foreach(solution => solution.zipWithIndex.foreach(h => println(s"House ${h._2 + 1} ${h._1}")))
}
} // loc 58</langsyntaxhighlight>
{{Out}}See it in running in your browser by [https://scalafiddle.io/sf/h5Y98te/0 ScalaFiddle (JavaScript executed in browser)] or by [https://scastie.scala-lang.org/fJZRog4xQ9aAV4D3crM1gQ Scastie (remote JVM)].{{out}}
<pre> The German is the owner of the zebra.
Line 6,419 ⟶ 6,822:
 
===Scala Alternate Version (Over-engineered)===
<langsyntaxhighlight lang="scala">import scala.util.Try
 
object Einstein extends App {
Line 6,502 ⟶ 6,905:
}
 
}// loc 38</langsyntaxhighlight>
{{Out}}Experience running it in your browser by [https://scalafiddle.io/sf/hJgtjYG/1 ScalaFiddle (JavaScript executed in browser)] or by [https://scastie.scala-lang.org/ajeuRgDSQKyVv4Jd6SPfVQ Scastie (remote JVM)].
{{out}}
Line 6,517 ⟶ 6,920:
=={{header|Sidef}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="ruby">var CONTENT = Hash(
:House => nil,
:Nationality => [:English, :Swedish, :Danish, :Norwegian, :German],
Line 6,568 ⟶ 6,971:
say "The Zebra is owned by the man who is #{res[0][res[2].first_index(:Zebra)]}\n"
say (fmt % keys..., "\n", fmt % width.map{|w| "-"*w }...)
res[0].indices.map{|i| res.map{|a| a[i] }}.each_kv {|k,v| say fmt%(k,v...) }</langsyntaxhighlight>
{{out}}
<pre>
Line 6,585 ⟶ 6,988:
{{works with|SML/NJ}}
{{trans|C++}}(This implementation uses the search algorithm of the C++ implementation, but the rules check algorithm is different.)
<langsyntaxhighlight lang="sml">
(* Attributes and values *)
val str_attributes = Vector.fromList ["Color", "Nation", "Drink", "Pet", "Smoke"]
Line 6,835 ⟶ 7,238:
else print "No solution found!\n"
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 6,852 ⟶ 7,255:
===General solver with relational algebra===
A general solver for this type of puzzle, using relational algebra. This solver can also be used for "Dinesman's multiple-dwelling problem"
<langsyntaxhighlight lang="tailspin">
processor EinsteinSolver
@: [{|{}|}]; // A list of possible relations, start with one relation with an empty tuple
$ -> \(
Line 6,874 ⟶ 7,277:
 
operator (a nextTo&{byField:, bMinusA:} b)
data ES_temp__ <"1"> local
@EinsteinSolver: [$@EinsteinSolver... -> \(
def in: $;
def temp: {| $... -> {$, ES_temp__: ($(byField)::raw)"1"} |};
def numbers: [$temp({ES_temp__:})... -> $.ES_temp__];
$numbers... -> \(
def aNumber: $;
def bNumbers: [$bMinusA... -> ($ + $aNumber)"1"];
def new: ($temp matching {| {$a, ES_temp__: $aNumber} |});
@: ($new union (($temp notMatching {| $a |}) notMatching {| {ES_temp__: $aNumber} |}));
Line 6,947 ⟶ 7,351:
'No more solutions
' -> !OUT::write
</syntaxhighlight>
</lang>
 
{{out}}
Line 6,966 ⟶ 7,370:
{{trans|C#}}
The streaming syntax of Tailspin lends itself naturally to this solution
<langsyntaxhighlight lang="tailspin">
templates permutations
when <=1> do [1] !
Line 7,019 ⟶ 7,423:
-> \[i]('$i;: $;'! \) -> '$... -> '$;$#10;';$#10;'
-> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 7,032 ⟶ 7,436:
=={{header|Tcl}}==
{{trans|Python}}
{{tcllib|struct::list}}<langsyntaxhighlight lang="tcl">package require struct::list
 
# Implements the constants by binding them directly into the named procedures.
Line 7,147 ⟶ 7,551:
 
initConstants isPossible
main</langsyntaxhighlight>
{{out}}
<pre>
Line 7,161 ⟶ 7,565:
=={{header|VBA}}==
{{trans|Phix}}
<langsyntaxhighlight lang="vb">Option Base 1
Public Enum attr
Colour = 1
Line 7,325 ⟶ 7,729:
Debug.Print "The " & Nationalities(perm(Nationality)(house(Pet, Zebra))) & " owns the Zebra"
Next i
End Sub</langsyntaxhighlight>{{out}}
<pre>1: yellow Norwegian water Dunhill cats
2: blue Dane tea Blend horse
Line 7,334 ⟶ 7,738:
1 solution found
The German owns the Zebra</pre>
 
=={{header|V (Vlang)}}==
{{trans|Go}}
<syntaxhighlight lang="v (vlang)">type HouseSet = []House
struct House {
n Nationality
c Colour
a Animal
d Drink
s Smoke
}
// Define the possible values
enum Nationality {
english = 0
swede
dane
norwegian
german
}
enum Colour {
red = 0
green
white
yellow
blue
}
enum Animal {
dog = 0
birds
cats
horse
zebra
}
enum Drink {
tea = 0
coffee
milk
beer
water
}
enum Smoke {
pall_mall = 0
dunhill
blend
blue_master
prince
}
// And how to print them
const nationalities = [Nationality.english, Nationality.swede, Nationality.dane, Nationality.norwegian, Nationality.german]
const colours = [Colour.red, Colour.green, Colour.white, Colour.yellow, Colour.blue]
const animals = [Animal.dog, Animal.birds, Animal.cats, Animal.horse, Animal.zebra]
const drinks = [Drink.tea, Drink.coffee, Drink.milk, Drink.beer, Drink.water]
const smokes = [Smoke.pall_mall, Smoke.dunhill, Smoke.blend, Smoke.blue_master, Smoke.prince]
 
fn (h House) str() string {
return "${h.n:-9} ${h.c:-6} ${h.a:-5} ${h.d:-6} $h.s"
}
fn (hs HouseSet) str() string {
mut lines := []string{len: 0, cap: 5}
for i, h in hs {
s := "$i $h"
lines << s
}
return lines.join("\n")
}
// Simple brute force solution
fn simple_brute_force() (int, HouseSet) {
mut v := []House{}
for n in nationalities {
for c in colours {
for a in animals {
for d in drinks {
for s in smokes {
h := House{
n: n,
c: c,
a: a,
d: d,
s: s,
}
if !h.valid() {
continue
}
v << h
}
}
}
}
}
n := v.len
println("Generated $n valid houses")
mut combos := 0
mut first := 0
mut valid := 0
mut valid_set := []House{}
for a := 0; a < n; a++ {
if v[a].n != Nationality.norwegian { // Condition 10:
continue
}
for b := 0; b < n; b++ {
if b == a {
continue
}
if v[b].any_dups(v[a]) {
continue
}
for c := 0; c < n; c++ {
if c == b || c == a {
continue
}
if v[c].d != Drink.milk { // Condition 9:
continue
}
if v[c].any_dups(v[b], v[a]) {
continue
}
for d := 0; d < n; d++ {
if d == c || d == b || d == a {
continue
}
if v[d].any_dups(v[c], v[b], v[a]) {
continue
}
for e := 0; e < n; e++ {
if e == d || e == c || e == b || e == a {
continue
}
if v[e].any_dups(v[d], v[c], v[b], v[a]) {
continue
}
combos++
set := HouseSet([v[a], v[b], v[c], v[d], v[e]])
if set.valid() {
valid++
if valid == 1 {
first = combos
}
valid_set = set
//return set
}
}
}
}
}
}
println("Tested $first different combinations of valid houses before finding solution")
println("Tested $combos different combinations of valid houses in total")
return valid, valid_set
}
// any_dups returns true if h as any duplicate attributes with any of the specified houses
fn (h House) any_dups(list ...House) bool {
for b in list {
if h.n == b.n || h.c == b.c || h.a == b.a || h.d == b.d || h.s == b.s {
return true
}
}
return false
}
fn (h House) valid() bool {
// Condition 2:
if (h.n == Nationality.english && h.c != Colour.red) || (h.n != Nationality.english && h.c == Colour.red) {
return false
}
// Condition 3:
if (h.n == Nationality.swede && h.a != Animal.dog) || (h.n != Nationality.swede && h.a == Animal.dog) {
return false
}
// Condition 4:
if (h.n == Nationality.dane && h.d != Drink.tea) || (h.n != Nationality.dane && h.d == Drink.tea ){
return false
}
// Condition 6:
if (h.c == Colour.green && h.d != Drink.coffee) || (h.c != Colour.green && h.d == Drink.coffee) {
return false
}
// Condition 7:
if (h.a == Animal.birds && h.s != Smoke.pall_mall) || (h.a != Animal.birds && h.s == Smoke.pall_mall) {
return false
}
// Condition 8:
if (h.c == Colour.yellow && h.s != Smoke.dunhill) || (h.c != Colour.yellow && h.s == Smoke.dunhill) {
return false
}
// Condition 11:
if h.a == Animal.cats && h.s == Smoke.blend {
return false
}
// Condition 12:
if h.a == Animal.horse && h.s == Smoke.dunhill {
return false
}
// Condition 13:
if (h.d == Drink.beer && h.s != Smoke.blue_master) || (h.d != Drink.beer && h.s == Smoke.blue_master) {
return false
}
// Condition 14:
if (h.n == Nationality.german && h.s != Smoke.prince) || (h.n != Nationality.german && h.s == Smoke.prince) {
return false
}
// Condition 15:
if h.n == Nationality.norwegian && h.c == Colour.blue {
return false
}
// Condition 16:
if h.d == Drink.water && h.s == Smoke.blend {
return false
}
return true
}
fn (hs HouseSet) valid() bool {
mut ni := map[Nationality]int{}
mut ci := map[Colour]int{}
mut ai := map[Animal]int{}
mut di := map[Drink]int{}
mut si := map[Smoke]int{}
for i, h in hs {
ni[h.n] = i
ci[h.c] = i
ai[h.a] = i
di[h.d] = i
si[h.s] = i
}
// Condition 5:
if ci[Colour.green]+1 != ci[Colour.white] {
return false
}
// Condition 11:
if dist(ai[Animal.cats], si[Smoke.blend]) != 1 {
return false
}
// Condition 12:
if dist(ai[Animal.horse], si[Smoke.dunhill]) != 1 {
return false
}
// Condition 15:
if dist(ni[Nationality.norwegian], ci[Colour.blue]) != 1 {
return false
}
// Condition 16:
if dist(di[Drink.water], si[Smoke.blend]) != 1 {
return false
}
 
// Condition 9: (already tested elsewhere)
if hs[2].d != Drink.milk {
return false
}
// Condition 10: (already tested elsewhere)
if hs[0].n != Nationality.norwegian {
return false
}
return true
}
fn dist(a int, b int) int {
if a > b {
return a - b
}
return b - a
}
fn main() {
n, sol := simple_brute_force()
println("$n solution found")
println(sol)
}</syntaxhighlight>
 
{{out}}
<pre>
Generated 51 valid houses
Tested 652 different combinations of valid houses before finding solution
Tested 750 different combinations of valid houses in total
1 solution found
0 norwegian yellow cats water dunhill
1 dane blue horse tea blend
2 english red birds milk pall_mall
3 german green zebra coffee prince
4 swede white dog beer blue_master
</pre>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
var colors = ["Red", "Green", "White", "Yellow", "Blue"]
var nations = ["English", "Swede", "Danish", "Norwegian", "German"]
var animals = ["Dog", "Birds", "Cats", "Horse", "Zebra"]
var drinks = ["Tea", "Coffee", "Milk", "Beer", "Water"]
var smokes = ["Pall Mall", "Dunhill", "Blend", "Blue Master", "Prince"]
 
var p = List.filled(120, null) // stores all permutations of numbers 0..4
for (i in 0..119) p[i] = List.filled(5, -1)
 
var nextPerm = Fn.new { |perm|
var size = perm.count
var k = -1
for (i in size-2..0) {
if (perm[i] < perm[i + 1]) {
k = i
break
}
}
if (k == -1) return false // last permutation
for (l in size-1..k) {
if (perm[k] < perm[l]) {
perm.swap(k, l)
var m = k + 1
var n = size - 1
while (m < n) {
perm.swap(m, n)
m = m + 1
n = n - 1
}
break
}
}
return true
}
 
var check = Fn.new { |a1, a2, v1, v2|
for (i in 0..4) {
if (p[a1][i] == v1) return p[a2][i] == v2
}
return false
}
 
var checkLeft = Fn.new { |a1, a2, v1, v2|
for (i in 0..3) {
if (p[a1][i] == v1) return p[a2][i + 1] == v2
}
return false
}
 
var checkRight = Fn.new { |a1, a2, v1, v2|
for (i in 1..4) {
if (p[a1][i] == v1) return p[a2][i - 1] == v2
}
return false
}
 
var checkAdjacent = Fn.new { |a1, a2, v1, v2|
return checkLeft.call(a1, a2, v1, v2) || checkRight.call(a1, a2, v1, v2)
}
 
var printHouses = Fn.new { |c, n, a, d, s|
var owner = ""
System.print("House Color Nation Animal Drink Smokes")
System.print("===== ====== ========= ====== ====== ===========")
for (i in 0..4) {
var f = "$3d $-6s $-9s $-6s $-6s $-11s"
var l = [i + 1, colors[p[c][i]], nations[p[n][i]], animals[p[a][i]], drinks[p[d][i]], smokes[p[s][i]]]
Fmt.lprint(f, l)
if (animals[p[a][i]] == "Zebra") owner = nations[p[n][i]]
}
System.print("\nThe %(owner) owns the Zebra\n")
}
 
var fillHouses = Fn.new {
var solutions = 0
for (c in 0..119) {
if (!checkLeft.call(c, c, 1, 2)) continue // C5 : Green left of white
for (n in 0..119) {
if (p[n][0] != 3) continue // C10: Norwegian in First
if (!check.call(n, c, 0, 0)) continue // C2 : English in Red
if (!checkAdjacent.call(n, c, 3, 4)) continue // C15: Norwegian next to Blue
for (a in 0..119) {
if (!check.call(a, n, 0, 1)) continue // C3 : Swede has Dog
for (d in 0..119) {
if (p[d][2] != 2) continue // C9 : Middle drinks Milk
if (!check.call(d, n, 0, 2)) continue // C4 : Dane drinks Tea
if (!check.call(d, c, 1, 1)) continue // C6 : Green drinks Coffee
for (s in 0..119) {
if (!check.call(s, a, 0, 1)) continue // C7 : Pall Mall has Birds
if (!check.call(s, c, 1, 3)) continue // C8 : Yellow smokes Dunhill
if (!check.call(s, d, 3, 3)) continue // C13: Blue Master drinks Beer
if (!check.call(s, n, 4, 4)) continue // C14: German smokes Prince
if (!checkAdjacent.call(s, a, 2, 2)) continue // C11: Blend next to Cats
if (!checkAdjacent.call(s, a, 1, 3)) continue // C12: Dunhill next to Horse
if (!checkAdjacent.call(s, d, 2, 4)) continue // C16: Blend next to Water
solutions = solutions + 1
printHouses.call(c, n, a, d, s)
}
}
}
}
}
return solutions
}
 
var perm = [0, 1, 2, 3, 4]
for (i in 0..119) {
for (j in 0..4) p[i][j] = perm[j]
nextPerm.call(perm)
}
var solutions = fillHouses.call()
var plural = (solutions == 1) ? "" : "s"
System.print("%(solutions) solution%(plural) found")</syntaxhighlight>
 
{{out}}
<pre>
House Color Nation Animal Drink Smokes
===== ====== ========= ====== ====== ===========
1 Yellow Norwegian Cats Water Dunhill
2 Blue Danish Horse Tea Blend
3 Red English Birds Milk Pall Mall
4 Green German Zebra Coffee Prince
5 White Swede Dog Beer Blue Master
 
The German owns the Zebra
 
1 solution found
</pre>
 
=={{header|zkl}}==
Line 7,339 ⟶ 8,165:
 
Lists are used as associated arrays rather than hash tables. With only five entries, it doesn't really matter.
<langsyntaxhighlight lang="zkl">var people,drinks,houses,smokes,pets; // lists treated as associated arrays
fcn c2 { people.find(English)==houses.find(Red) }
fcn c3 { people.find(Swede)==pets.find(Dog) }
Line 7,399 ⟶ 8,225:
.zip(titles,names))
{ println(list.apply(names.get):fmt(title,_.xplode())) }
}</langsyntaxhighlight>
{{out}}
<pre>
7,794

edits