import Control. Applicative ( ( <$> ) , ( <*> ) )
import Data. List ( ( \\) , isInfixOf)
-- types
data House = House
{ color :: Color
, man :: Man
, pet :: Pet
, drink :: Drink
, smoke :: Smoke
}
data Color = Red | Green | Blue | Yellow | White
data Man = Eng | Swe | Dan | Nor | Ger
data Pet = Dog | Birds | Cats | Horse | Zebra
data Drink = Coffee | Tea | Milk | Beer | Water
data Smoke = PallMall | Dunhill | Blend | BlueMaster | Prince
main = do
solutions :: [ [ House] ]
solutions
= filter ( and . postChecks
) $ foldM next
[ ] [ 1 .. 5 ] where
next
:: [ House
] -> Int -> [ [ House
] ] next xs pos
= [ x:xs
| x
<- iterHouse xs
, and $ checks pos x
]
iterHouse :: [ House] -> [ House]
iterHouse xs =
House <$> new color <*> new man <*> new pet <*> new drink <*> new smoke
where
-- immediate checks
checks pos house =
[ man `is` Eng <=> color `is` Red -- 2
, man `is` Swe <=> pet `is` Dog -- 3
, man `is` Dan <=> drink `is` Tea -- 4
, color `is` Green <=> drink `is` Coffee -- 6
, pet `is` Birds <=> smoke `is` PallMall -- 7
, color `is` Yellow <=> smoke `is` Dunhill -- 8
, const ( pos
== 3 ) <=> drink `is` Milk
-- 9 , const ( pos
== 1 ) <=> man `is` Nor
-- 10 , drink `is` Beer <=> smoke `is` BlueMaster -- 13
, man `is` Ger <=> smoke `is` Prince -- 14
]
where
infix 4 <=>
p <=> q = p house == q house -- both True or both False
-- final checks
postChecks
:: [ House
] -> [ Bool ] postChecks houses =
-- NOTE: list of houses is generated "from tail"
[ [ White
, Green
] `isInfixOf`
map color houses
-- 5 , ( smoke `is` Blend ) `nextTo` ( pet `is` Cats ) -- 11
, ( smoke `is` Dunhill) `nextTo` ( pet `is` Horse) -- 12
, ( color `is` Blue ) `nextTo` ( man `is` Nor ) -- 15
, ( smoke `is` Blend ) `nextTo` ( drink `is` Water) -- 16
]
where
nextTo p q
where
match x = p x || q x
is
:: Eq a
=> ( House
-> a
) -> a
-> House
-> Bool getter `is` value = ( == value) . getter
{-
Success time: 0.04 memory: 6284 signal:0
House {color = Yellow,man = Nor, pet = Cats, drink = Water, smoke = Dunhill }
House {color = Blue, man = Dan, pet = Horse, drink = Tea, smoke = Blend }
House {color = Red, man = Eng, pet = Birds, drink = Milk, smoke = PallMall}
House {color = Green, man = Ger, pet = Zebra, drink = Coffee,smoke = Prince }
House {color = White, man = Swe, pet = Dog, drink = Beer, smoke=BlueMaster}
----
No More Solutions
-}
aW1wb3J0IENvbnRyb2wuQXBwbGljYXRpdmUgKCg8JD4pLCAoPCo+KSkKaW1wb3J0IENvbnRyb2wuTW9uYWQKaW1wb3J0IERhdGEuTGlzdCAoKFxcKSwgaXNJbmZpeE9mKQogCi0tIHR5cGVzCmRhdGEgSG91c2UgPSBIb3VzZQogICAgeyBjb2xvciA6OiBDb2xvcgogICAgLCBtYW4gICA6OiBNYW4KICAgICwgcGV0ICAgOjogUGV0CiAgICAsIGRyaW5rIDo6IERyaW5rCiAgICAsIHNtb2tlIDo6IFNtb2tlCiAgICB9CiAgICBkZXJpdmluZyAoRXEsIFNob3cpCiAKZGF0YSBDb2xvciA9IFJlZCB8IEdyZWVuIHwgQmx1ZSB8IFllbGxvdyB8IFdoaXRlCiAgICBkZXJpdmluZyAoRXEsIFNob3csIEVudW0sIEJvdW5kZWQpCiAKZGF0YSBNYW4gPSBFbmcgfCBTd2UgfCBEYW4gfCBOb3IgfCBHZXIKICAgIGRlcml2aW5nIChFcSwgU2hvdywgRW51bSwgQm91bmRlZCkKIApkYXRhIFBldCA9IERvZyB8IEJpcmRzIHwgQ2F0cyB8IEhvcnNlIHwgWmVicmEKICAgIGRlcml2aW5nIChFcSwgU2hvdywgRW51bSwgQm91bmRlZCkKIApkYXRhIERyaW5rID0gQ29mZmVlIHwgVGVhIHwgTWlsayB8IEJlZXIgfCBXYXRlcgogICAgZGVyaXZpbmcgKEVxLCBTaG93LCBFbnVtLCBCb3VuZGVkKQogCmRhdGEgU21va2UgPSBQYWxsTWFsbCB8IER1bmhpbGwgfCBCbGVuZCB8IEJsdWVNYXN0ZXIgfCBQcmluY2UKICAgIGRlcml2aW5nIChFcSwgU2hvdywgRW51bSwgQm91bmRlZCkKIAogCm1haW4gOjogSU8gKCkKbWFpbiA9IGRvCiAgbWFwTV8gKFx4LT4gbWFwTV8gcHJpbnQgKHJldmVyc2UgeCkgPj4gcHV0U3RyTG4gIi0tLS0iKSBzb2x1dGlvbnMKICBwdXRTdHJMbiAiTm8gTW9yZSBTb2x1dGlvbnMiCiAKc29sdXRpb25zIDo6IFtbSG91c2VdXQpzb2x1dGlvbnMgPSBmaWx0ZXIgKGFuZCAuIHBvc3RDaGVja3MpICQgZm9sZE0gbmV4dCBbXSBbMS4uNV0KICAgIHdoZXJlCiAgICAgIG5leHQgOjogW0hvdXNlXSAtPiBJbnQgLT4gW1tIb3VzZV1dCiAgICAgIG5leHQgeHMgcG9zID0gW3g6eHMgfCB4IDwtIGl0ZXJIb3VzZSB4cywgYW5kICQgY2hlY2tzIHBvcyB4XQogCiAKaXRlckhvdXNlIDo6IFtIb3VzZV0gLT4gW0hvdXNlXQppdGVySG91c2UgeHMgPQogICAgSG91c2UgPCQ+IG5ldyBjb2xvciA8Kj4gbmV3IG1hbiA8Kj4gbmV3IHBldCA8Kj4gbmV3IGRyaW5rIDwqPiBuZXcgc21va2UKICAgIHdoZXJlCiAgICAgIG5ldyBnZXR0ZXIgPSBbbWluQm91bmQgLi5dIFxcIG1hcCBnZXR0ZXIgeHMKIAogCi0tIGltbWVkaWF0ZSBjaGVja3MKY2hlY2tzIDo6IEludCAtPiBIb3VzZSAtPiBbQm9vbF0KY2hlY2tzIHBvcyBob3VzZSA9CiAgICBbIG1hbiAgIGBpc2AgRW5nICAgIDw9PiBjb2xvciBgaXNgIFJlZCAgICAgICAgICAgICAgLS0gIDIKICAgICwgbWFuICAgYGlzYCBTd2UgICAgPD0+IHBldCAgIGBpc2AgRG9nICAgICAgICAgICAgICAtLSAgMwogICAgLCBtYW4gICBgaXNgIERhbiAgICA8PT4gZHJpbmsgYGlzYCBUZWEgICAgICAgICAgICAgIC0tICA0CiAgICAsIGNvbG9yIGBpc2AgR3JlZW4gIDw9PiBkcmluayBgaXNgIENvZmZlZSAgICAgICAgICAgLS0gIDYKICAgICwgcGV0ICAgYGlzYCBCaXJkcyAgPD0+IHNtb2tlIGBpc2AgUGFsbE1hbGwgICAgICAgICAtLSAgNwogICAgLCBjb2xvciBgaXNgIFllbGxvdyA8PT4gc21va2UgYGlzYCBEdW5oaWxsICAgICAgICAgIC0tICA4CiAgICAsIGNvbnN0IChwb3MgPT0gMykgIDw9PiBkcmluayBgaXNgIE1pbGsgICAgICAgICAgICAgLS0gIDkKICAgICwgY29uc3QgKHBvcyA9PSAxKSAgPD0+IG1hbiAgIGBpc2AgTm9yICAgICAgICAgICAgICAtLSAxMAogICAgLCBkcmluayBgaXNgIEJlZXIgICA8PT4gc21va2UgYGlzYCBCbHVlTWFzdGVyICAgICAgIC0tIDEzCiAgICAsIG1hbiAgIGBpc2AgR2VyICAgIDw9PiBzbW9rZSBgaXNgIFByaW5jZSAgICAgICAgICAgLS0gMTQKICAgIF0KICAgIHdoZXJlCiAgICAgIGluZml4IDQgPD0+CiAgICAgIHAgPD0+IHEgPSBwIGhvdXNlID09IHEgaG91c2UgIC0tIGJvdGggVHJ1ZSBvciBib3RoIEZhbHNlCiAKIAotLSBmaW5hbCBjaGVja3MKcG9zdENoZWNrcyA6OiBbSG91c2VdIC0+IFtCb29sXQpwb3N0Q2hlY2tzIGhvdXNlcyA9CiAgICAtLSBOT1RFOiBsaXN0IG9mIGhvdXNlcyBpcyBnZW5lcmF0ZWQgImZyb20gdGFpbCIKICAgIFsgW1doaXRlLCBHcmVlbl0gYGlzSW5maXhPZmAgbWFwIGNvbG9yIGhvdXNlcyAgICAgICAtLSAgNQogICAgLCAoc21va2UgYGlzYCBCbGVuZCAgKSBgbmV4dFRvYCAocGV0ICAgYGlzYCBDYXRzICkgIC0tIDExCiAgICAsIChzbW9rZSBgaXNgIER1bmhpbGwpIGBuZXh0VG9gIChwZXQgICBgaXNgIEhvcnNlKSAgLS0gMTIKICAgICwgKGNvbG9yIGBpc2AgQmx1ZSAgICkgYG5leHRUb2AgKG1hbiAgIGBpc2AgTm9yICApICAtLSAxNQogICAgLCAoc21va2UgYGlzYCBCbGVuZCAgKSBgbmV4dFRvYCAoZHJpbmsgYGlzYCBXYXRlcikgIC0tIDE2CiAgICBdCiAgICB3aGVyZQogICAgICBuZXh0VG8gOjogKEhvdXNlIC0+IEJvb2wpIC0+IChIb3VzZSAtPiBCb29sKSAtPiBCb29sCiAgICAgIG5leHRUbyBwIHEKICAgICAgICAgIHwgKF86eDpfKSA8LSBkcm9wV2hpbGUgKG5vdCAuIG1hdGNoKSBob3VzZXMgPSBtYXRjaCB4CiAgICAgICAgICB8IG90aGVyd2lzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gRmFsc2UKICAgICAgICAgIHdoZXJlCiAgICAgICAgICAgIG1hdGNoIHggPSBwIHggfHwgcSB4CiAKIAppcyA6OiBFcSBhID0+IChIb3VzZSAtPiBhKSAtPiBhIC0+IEhvdXNlIC0+IEJvb2wKZ2V0dGVyIGBpc2AgdmFsdWUgPSAoPT0gdmFsdWUpIC4gZ2V0dGVyCgp7LQpTdWNjZXNzCSB0aW1lOiAwLjA0IG1lbW9yeTogNjI4NCBzaWduYWw6MApIb3VzZSB7Y29sb3IgPSBZZWxsb3csbWFuID0gTm9yLCBwZXQgPSBDYXRzLCAgZHJpbmsgPSBXYXRlciwgc21va2UgPSBEdW5oaWxsIH0KSG91c2Uge2NvbG9yID0gQmx1ZSwgIG1hbiA9IERhbiwgcGV0ID0gSG9yc2UsIGRyaW5rID0gVGVhLCAgIHNtb2tlID0gQmxlbmQgICB9CkhvdXNlIHtjb2xvciA9IFJlZCwgICBtYW4gPSBFbmcsIHBldCA9IEJpcmRzLCBkcmluayA9IE1pbGssICBzbW9rZSA9IFBhbGxNYWxsfQpIb3VzZSB7Y29sb3IgPSBHcmVlbiwgbWFuID0gR2VyLCBwZXQgPSBaZWJyYSwgZHJpbmsgPSBDb2ZmZWUsc21va2UgPSBQcmluY2UgIH0KSG91c2Uge2NvbG9yID0gV2hpdGUsIG1hbiA9IFN3ZSwgcGV0ID0gRG9nLCAgIGRyaW5rID0gQmVlciwgIHNtb2tlPUJsdWVNYXN0ZXJ9Ci0tLS0KTm8gTW9yZSBTb2x1dGlvbnMKLX0=