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.

Download the source code for this post.