Einstein meet F#, part 3

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.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s