
Am Mittwoch 23 Dezember 2009 20:46:51 schrieb Patrick LeBoutillier:
Hi all,
I've been working hard at trying to solve Einstein's problem (http://www.davar.net/MATH/PROBLEMS/EINSTEIN.HTM) if an efficient manner using Haskell.
I have posted my solution here: http://haskell.pastebin.com/m3ff1973a
This exercise has been a real eye opener for me, especially for learning to work with the Maybe and List monads.
I'm looking for suggestions for making the "test" function nicer. In order to make my solution fast, I generate my test cases incrementally, thereby elimating most of the cases early on. However the function looks funny (deeply nested).
Instead of if checkStreet s then ... else [], use Control.Monad.guard: test = do ds <- drinkPerms ns <- nationPerms let s = Street $ makeHouses ds ns [] [] [] guard (checkStreet s) ss <- smokePerms ...
I'm also open to any comments about making better use of the different Haskell idioms.
There is a function permutations in Data.List, you can use that instead of writing your own (except if you want the permutations in a different order). xxxPerms = permutationsOf [toEnum 0 .. toEnum 4] :: [[XXX]] isn't particularly nice, better give the first and last constructor of each type or define allPerms :: (Enum a, Bounded a) => [[a]] allPerms = permutationsOf [minBound .. maxBound] and derive also Bounded for your types. nationPerms = filter rule1 $ permutationsOf [toEnum 0 .. toEnum 4] :: [[Nation]] where rule1 ns = (ns !! 0) == Norway is very inefficient, make that nationPerms = map (Norway:) $ permutationsOf [England .. Denmark] (yes, it's not so terrible for only five items, still it made me wince). Similar for drinkPerms. checkCond (f,c) h = fmap (== c) (f h) ~> checkCond (f,c) = fmap (== c) . f
Thanks a lot,
Patrick