5! 5 = 24.883.200.000
5! 5 = 24.883.200.000
, which is quite a lot.
- import data . List ( lookup , nub)
- import data . Maybe (fromMaybe , catMaybes)
- -----------------------------------------------
- - The Mystery of Einstein -
- - by Atamur -
- -----------------------------------------------
- ---------------------------
- - General description of the task -
- ---------------------------
- - The solution is a sequence of objects
- type Solution = [Object]
- - Each object is described by a set of attribute pairs and their values.
- type Object = [( String , String )]
- - indicating the attribute-value pair with the = sign:
- attr = : value = (attr , value)
- attributes = [ "nationality" , "house" , "pet" , "drink" , "smoke" ]
- size = 5
- - We will solve the problem of finding a solution that satisfies some
- - restrictions
- - We will do this starting from the set of all solutions and gradually refining
- - this is a set until it decreases to one solution, which will be
- - true.
- - Therefore, an object can immediately describe a set of real objects
- - which have some attributes set, and the rest (not set)
- - can be any. Therefore, an empty object is a template of all possible
- - objects:
- anyObject = [] :: Object
- - A set of empty objects - the set of all solutions for a given
- - dimensions:
- anySolution = [anyObject | n ← [1 .. size]]
- - Each solution describes a compatible set of solutions, for example, a solution
- - [["nationality" =: "Englishman"], anyObject, anyObject]
- - describes all three objects, the first of which has an attribute
- - "nationality is English"
- “But when refining solutions, we will need to have sets of incompatible
- - decisions (for example, “Englishman or first or second but not at the same time”):
- type Solutions = [Solution]
- empty = [] :: Solutions
- - To solve the problem, we need to impose restrictions on the solution
- - Each constraint will transform a variety of solutions.
- - As a result, there may be several unrelated sets or
- - empty solution set
- type Restriction = Solution → Solutions
- - applying a constraint to a set of solutions
- - when transforming a set of solutions, we will check for
- - uniqueness of attribute values:
- apply :: Restriction → Solutions → Solutions
- apply restrict sols =
- concat [ filter ( not . duplicates) (restrict solution) | solution ← sols]
- where
- duplicates sols = any duplicateValues ( map (values sols) attributes)
- values sols attr = map ( lookup attr) sols
- duplicateValues vals' =
- let vals = catMaybes vals'
- in (vals ≠ nub vals)
- - the intersection of two patterns describing objects
- - can be a template containing attributes from both source templates,
- - or it may be incompatible if the source templates contain different
- - values of the same attributes
- both :: Object → Object → Maybe Object
- both obj obj ' = foldl join (Just []) attributes - combine by attributes
- where
- - if we already have an empty set then the result is also empty
- join Nothing _ = Nothing
- - otherwise compare values of attributes by attributes.
- join (Just rest) attr =
- case ( lookup attr obj , lookup attr obj ') of
- (Nothing , Nothing) → Just rest
- (Just value , Nothing) → Just ((attr = : value): rest)
- (Nothing , Just value) → Just ((attr = : value): rest)
- (Just value , Just value ') →
- if value == value '
- then Just ((attr = : value): rest)
- else Nothing
- - basic restriction - the object in some position must coincide with
- - set by template
- objectAt :: Int → Object → Restriction
- objectAt n obj solution =
- case both obj (solution !! (n - 1)) of
- Nothing → empty - if the template is not compatible with the one already there
- Just res → [replace n res solution]
- where
- replace nx xs = take (n - 1) xs ++ [x] ++ drop n xs
- - Operations on constraints ---------------------------------------------
- - intersection - both restrictions are true
- ( < & > ) rs rs 'solution = apply rs (rs' solution)
- r _ all = foldl1 ( < & > ) - all restrictions from the set
- - association - one or the other is true
- ( <|> ) rs rs 'solution = rs solution ++ rs' solution
- r _ any = foldl1 ( <|> ) - one of the limitations
- - Derived constraints ---------------------------------------------- -
- - there is some object (either in the first position, or in the second, etc.)
- exists obj = r _ any [objectAt n obj | n ← [1 .. 5]]
- - one object always follows another
- before obj obj ' = r _ any [
- objectAt n obj < & > objectAt (n + 1) obj ' | n ← [1 .. size - 1]]
- - near (or one before the second, or second before the first)
- near obj obj ' = (obj `before` obj') <|> (obj 'before` obj)
- ------------------------------------------------
- - Description of the specific problem
- ------------------------------------------------
- restrictions =
- objectAt 1 [ "nationality" = : "Norwegian" ] < & >
- exists [ "nationality" = : "Englishman" , "house" = : "Red" ] < & >
- ([ "house" = : "Green" ] `before` [ " house " = : " White " ]) < & >
- exists [ "nationality" = : "Dane" , "drink" = : "Tea" ] < & >
- ([ "smoke" = : "Malboro" ] `near` [ " pet " = : " Cat " ]) < & >
- exists [ "smoke" = : "Dunhill" , "house" = : "Yellow" ] < & >
- exists [ "nationality" = : "German" , "smoke" = : "Rothmans" ] < & >
- objectAt 3 [ "drink" = : "Milk" ] < & >
- ([ "smoke" = : "Malboro" ] `near` [ " drink " = : " Water " ]) < & >
- exists [ "smoke" = : "Pallmall" , "pet" = : "Bird" ] < & >
- exists [ "nationality" = : "Swede" , "pet" = : "Dog" ] < & >
- ([ "nationality" = : "Norwegian" ] `near` [ " house " = : " Blue " ]) < & >
- exists [ "pet" = : "Horse" , "house" = : "Blue" ] < & >
- exists [ "smoke" = : "Winfield" , "drink" = : "Beer" ] < & >
- exists [ "house" = : "Green" , "drink" = : "Coffee" ] < & >
- exists [ "pet" = : "Fish" ]
- - the fish does not appear anywhere, you need to ask what it is
- main = let solutions = apply restrictions [anySolution]
- in if length solutions > 1
- then putStrLn ( "Total solution sets:" ++ show ( length solutions))
- else putStrLn $ descrSolution $ head solutions
- -----------------------------
- - String views -
- -----------------------------
- - a string representation of a person:
- descrMan man = descr "nationality" ++ "lives in" ++
- descr "house" ++ "house, owns" ++
- descr "pet" ++ ", drinks" ++
- descr "drink" ++ "and smokes" ++
- descr "smoke"
- where descr attr = fromMaybe "?" ( lookup attr man)
- - string representation of the solution:
- descrSolution sol = concat [descrMan man ++ " \ n " | man ← sol]
Source: https://habr.com/ru/post/122123/
All Articles