If you read the previous two blog posts we started to solve a riddle Einstein created, using the F# language. In this last post, we’ll finish the solution by defining the set of rules for the remaining set of houses, and hopefully find the answer to the riddle.
let livesNextTo(house1:House, house2:House) =
house1.Number = house2.Number - 1 || house1.Number = house2.Number + 1
let multiRule1(houses:List<House>) =
let greenHouse = houses |> List.find (fun h -> h.Color = ColorHouse.Green)
let whiteHouse = houses |> List.find (fun h -> h.Color = ColorHouse.White)
greenHouse.Number = whiteHouse.Number - 1
let multiRule2(houses:List<House>) =
let blendSmoker = houses |> List.find (fun h -> h.Smoke = Smoke.Blends)
let catPerson = houses |> List.find (fun h -> h.Pet = Pet.Cats)
livesNextTo(blendSmoker, catPerson)
And for the multi rules….
let multiRules = [multiRule1;multiRule2;multiRule3;multiRule4;multiRule5;]
let multiRulesPredicate(houses:List<House>)
= multiRules |> List.forall(fun rule -> rule(houses))
Next we are going to group the houses by the position they have been assigned.
let groupedHouses = housesPassedRules |> Seq.groupBy (fun (house:House) -> house.Number) |> Seq.toList
Now we just need to iterate through the values of each group, which will give us a set that correctly describes the index of each house. Now we just need to apply our filtering rules that apply to the sets of houses, and only a single set should be remaining.
let finalSets : List<List<House>> =
[for g1 in snd(groupedHouses.[0]) do
for g2 in snd(groupedHouses.[1]) do
for g3 in snd(groupedHouses.[2]) do
for g4 in snd(groupedHouses.[3]) do
for g5 in snd(groupedHouses.[4]) do
let houseGroup = [g1;g2;g3;g4;g5;]
if validHouseSet(houseGroup) && multiRulesPredicate(houseGroup) then yield houseGroup]
Finally, we’ll make sure we’ve only have a single set and print out the answer to the riddle with the house number of the fish.
let answerCheck = if finalSets.Length <> 1 then raise (new Exception("Answer not found."))
let finalSet = finalSets |> List.head
let fishHouse = finalSet |> List.find (fun house -> house.Pet = Pet.Fishes)
printf "%s" ("Fish is owned by: House:" ^ fishHouse.Number.ToString())
This problem was a great introduction to learning some of the concepts of functional programming as well as the features of the F#. In another blog series I’ll be taking a look at some of the distinguishing language features F# has compared to C# and other .NET languages.