[Haskell-beginners] Einstein's Problem

Daniel Fischer daniel.is.fischer at web.de
Wed Dec 23 19:34:52 EST 2009


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



More information about the Beginners mailing list