45 lines
2.4 KiB
Haskell
45 lines
2.4 KiB
Haskell
module Part2 where
|
|
|
|
import Data.Map ((!), Map, foldl, empty, filterWithKey, insert, member, fromList)
|
|
import Commons
|
|
|
|
|
|
type Intervals = Map Char (Int, Int)
|
|
|
|
applyRule :: Rule -> Intervals -> (String, Intervals, Intervals)
|
|
applyRule rule i
|
|
| r rule == '*' = (destination rule, i, empty)
|
|
| member (r rule) i = let (start, end) = i ! r rule
|
|
in case s rule of
|
|
'>' -> if start > v rule
|
|
then (destination rule, i, empty)
|
|
else if end <= v rule
|
|
then (destination rule, empty, i)
|
|
else (destination rule, insert (r rule) (v rule + 1, end) i,
|
|
insert (r rule) (start, v rule) i)
|
|
'<' -> if end < v rule
|
|
then (destination rule, i, empty)
|
|
else if start >= v rule
|
|
then (destination rule, empty, i)
|
|
else (destination rule, insert (r rule) (start, v rule - 1) i,
|
|
insert (r rule) (v rule, end) i)
|
|
| otherwise = (destination rule, empty, i)
|
|
|
|
applyRules :: [Rule] -> Intervals -> [(String, Intervals)]
|
|
applyRules [] _ = []
|
|
applyRules (h: t) i = let (destination, accepted, left) = applyRule h i
|
|
in if destination == "R" then applyRules t left
|
|
else (destination, accepted): applyRules t left
|
|
|
|
applyWorkflow :: Workflows -> [(String, Intervals)] -> Int
|
|
applyWorkflow _ [] = 0
|
|
applyWorkflow workflows ((wName, i): t) | wName == "A" = Data.Map.foldl (\ a (start, end) -> a * (end - start + 1)) 1 i
|
|
+ applyWorkflow workflows t
|
|
| otherwise = let afterRules = applyRules (workflows ! wName) i
|
|
in applyWorkflow workflows afterRules
|
|
+ applyWorkflow workflows t
|
|
|
|
getNCombinations :: Workflows -> Int
|
|
getNCombinations w = applyWorkflow w [("in", fromList [('x', (1, 4000)), ('m', (1, 4000)), ('a', (1, 4000)),
|
|
('s', (1, 4000))])]
|