import Control.Monad import Data.List values :: (Bounded a, Enum a) => [[a]] values = permutations [minBound..maxBound] data Nation = English | Swede | Dane | Norwegian | German deriving (Bounded, Enum, Eq, Show) data Color = Red | Green | White | Yellow | Blue deriving (Bounded, Enum, Eq, Show) data Pet = Dog | Birds | Cats | Horse | Zebra deriving (Bounded, Enum, Eq, Show) data Drink = Tea | Coffee | Milk | Beer | Water deriving (Bounded, Enum, Eq, Show) data Smoke = PallMall | Dunhill | Blend | BlueMaster | Prince deriving (Bounded, Enum, Eq, Show) answers = do color <- values leftOf color Green color White -- 5 nation <- values first nation Norwegian -- 10 same nation English color Red -- 2 nextTo nation Norwegian color Blue -- 15 drink <- values middle drink Milk -- 9 same nation Dane drink Tea -- 4 same drink Coffee color Green -- 6 pet <- values same nation Swede pet Dog -- 3 smoke <- values same smoke PallMall pet Birds -- 7 same color Yellow smoke Dunhill -- 8 nextTo smoke Blend pet Cats -- 11 nextTo pet Horse smoke Dunhill -- 12 same nation German smoke Prince -- 14 same smoke BlueMaster drink Beer -- 13 nextTo drink Water smoke Blend -- 16 return $ zip5 nation color pet drink smoke where same xs x ys y = guard $ (x, y) `elem` zip xs ys leftOf xs x ys y = same xs x (tail ys) y nextTo xs x ys y = leftOf xs x ys y `mplus` leftOf ys y xs x middle xs x = guard $ xs !! 2 == x first xs x = guard $ head xs == x main = do forM_ answers $ (\answer -> -- for answer in answers: do mapM_ print answer print [nation | (nation, _, Zebra, _, _) <- answer] putStrLn "" ) putStrLn "No more solutions!"