|
| 1 | +module ZebraPuzzle |
| 2 | + |
| 3 | +open System |
| 4 | + |
| 5 | +type Color = |
| 6 | + | Red |
| 7 | + | Green |
| 8 | + | Ivory |
| 9 | + | Yellow |
| 10 | + | Blue |
| 11 | + |
| 12 | +type Resident = |
| 13 | + | Englishman |
| 14 | + | Spaniard |
| 15 | + | Ukranian |
| 16 | + | Norwegian |
| 17 | + | Japanese |
| 18 | + |
| 19 | +type Pet = |
| 20 | + | Dog |
| 21 | + | Snails |
| 22 | + | Fox |
| 23 | + | Horse |
| 24 | + | Zebra |
| 25 | + |
| 26 | +type Beverage = |
| 27 | + | Coffee |
| 28 | + | Tea |
| 29 | + | Milk |
| 30 | + | OrangeJuice |
| 31 | + | Water |
| 32 | + |
| 33 | +type Smokes = |
| 34 | + | OldGold |
| 35 | + | Kools |
| 36 | + | Chesterfields |
| 37 | + | LuckyStrike |
| 38 | + | Parliaments |
| 39 | + |
| 40 | +let rec permutations = |
| 41 | + function |
| 42 | + | [] -> seq [ List.empty ] |
| 43 | + | x :: xs -> Seq.collect (insertions x) (permutations xs) |
| 44 | + |
| 45 | +and insertions x = |
| 46 | + function |
| 47 | + | [] -> [ [ x ] ] |
| 48 | + | (y :: ys) as xs -> (x :: xs) :: (List.map (fun x -> y :: x) (insertions x ys)) |
| 49 | + |
| 50 | +let private house item = List.findIndex ((=) item) |
| 51 | + |
| 52 | +let private filterColors = |
| 53 | + permutations [ Red; Green; Ivory; Yellow; Blue ] |
| 54 | + |> Seq.filter (fun colors -> |
| 55 | + // The green house is immediately to the right of the ivory house. |
| 56 | + (house Green colors) + 1 = (house Ivory colors)) |
| 57 | + |
| 58 | +let private filterResidents colors = |
| 59 | + permutations [ Englishman; Spaniard; Ukranian; Norwegian; Japanese ] |
| 60 | + |> Seq.filter (fun residents -> |
| 61 | + // The Norwegian lives in the first house. |
| 62 | + (house Norwegian residents) = 0 |
| 63 | + // The Norwegian lives next to the blue house. |
| 64 | + && Math.Abs((house Norwegian residents) - (house Blue colors)) = 1 |
| 65 | + // The Englishman lives in the red house. |
| 66 | + && (house Englishman residents) = (house Red colors)) |
| 67 | + |
| 68 | +let private filterBeverages colors residents = |
| 69 | + permutations [ Coffee; Tea; Milk; OrangeJuice; Water ] |
| 70 | + |> Seq.filter (fun beverages -> |
| 71 | + // Coffee is drunk in the green house. |
| 72 | + (house Coffee beverages) = (house Green colors) |
| 73 | + // The Ukranian drinks tea. |
| 74 | + && (house Ukranian residents) = (house Tea beverages) |
| 75 | + // Milk is drunk in the middle house. |
| 76 | + && (house Milk beverages) = 2) |
| 77 | + |
| 78 | +let private filterSmokes colors residents beverages = |
| 79 | + permutations [ OldGold; Kools; Chesterfields; LuckyStrike; Parliaments ] |
| 80 | + |> Seq.filter (fun smokes -> |
| 81 | + // Kools are smoked in the second house. |
| 82 | + (house Kools smokes) = (house Yellow colors) |
| 83 | + // The Lucky Strike smoker drinks orange juice. |
| 84 | + && (house LuckyStrike smokes) = (house OrangeJuice beverages) |
| 85 | + // The Japanese smokes Parliaments. |
| 86 | + && (house Japanese residents) = (house Parliaments smokes)) |
| 87 | + |
| 88 | +let private filterPets residents smokes = |
| 89 | + permutations [ Dog; Snails; Fox; Horse; Zebra ] |
| 90 | + |> Seq.filter (fun pets -> |
| 91 | + // The Spaniard owns the dog. |
| 92 | + (house Dog pets) = (house Spaniard residents) |
| 93 | + // The Old Gold smoker owns snails. |
| 94 | + && (house OldGold smokes) = (house Snails pets) |
| 95 | + // The man who smokes Chesterfields lives in the house next to the man with the fox. |
| 96 | + && Math.Abs((house Chesterfields smokes) - (house Fox pets)) = 1 |
| 97 | + // Kools are smoked in the house next to the house where the horse is kept. |
| 98 | + && Math.Abs((house Kools smokes) - (house Horse pets)) = 1) |
| 99 | + |
| 100 | +let private combinations = |
| 101 | + seq { |
| 102 | + for colors in filterColors do |
| 103 | + for residents in filterResidents colors do |
| 104 | + for beverages in filterBeverages colors residents do |
| 105 | + for smokes in filterSmokes colors residents beverages do |
| 106 | + for pets in filterPets residents smokes do |
| 107 | + yield (colors, residents, beverages, smokes, pets) |
| 108 | + } |
| 109 | + |
| 110 | +let (colors, residents, beverages, smokes, pets) = Seq.head combinations |
| 111 | + |
| 112 | +let drinksWater = List.item (house Water beverages) residents |
| 113 | + |
| 114 | +let ownsZebra = List.item (house Zebra pets) residents |
0 commit comments