Skip to content

Commit ec15504

Browse files
committed
p2
1 parent 1544a16 commit ec15504

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

19.hs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import Data.Char (isDigit)
22
import Data.List (elemIndex, find)
33
import Data.Map qualified as M
4+
import Control.Arrow ((&&&))
45

56
main :: IO ()
6-
main = interact $ (++ "\n") . show . p1 . parse
7+
main = interact $ (++ "\n") . show . (p1 &&& p2) . parse
78

89
type Workflows = M.Map String [Rule]
910
type Rule = (Maybe Condition, String)
@@ -40,3 +41,33 @@ valid ws p = go "in"
4041

4142
p1 :: (Workflows, [Part]) -> Int
4243
p1 (workflows, parts) = sum . concat $ filter (valid workflows) parts
44+
45+
type Ranges = [(Int, Int)]
46+
type Thread = (Ranges, String)
47+
48+
validCombinations :: Workflows -> Int
49+
validCombinations ws = go [(replicate 4 (1, 4000), "in")]
50+
where
51+
combo :: Ranges -> Int
52+
combo ranges = product $ map ((+1) . uncurry subtract) ranges
53+
rules w = ((M.!) ws w)
54+
go :: [Thread] -> Int
55+
go [] = 0
56+
go ((rs, "A") : xs) = combo rs + go xs
57+
go ((_, "R") : xs) = go xs
58+
go ((rs, w) : xs) = go $ (splitThreads rs (rules w)) ++ xs
59+
splitThreads :: Ranges -> [Rule] -> [Thread]
60+
splitThreads rs ((Nothing, w) : _) = [(rs, w)]
61+
splitThreads rs ((Just c, w) : rest) =
62+
let (matching, notMatching) = split rs c
63+
in [(matching, w)] ++ splitThreads notMatching rest
64+
split :: Ranges -> Condition -> (Ranges, Ranges)
65+
split ranges (i, op, v) = foldl f ([], []) (zip [0..] ranges)
66+
where f (m, n) (j, r) | i == j = let (match, nomatch) = split' r op v
67+
in (m ++ [match], n ++ [nomatch])
68+
| otherwise = (m ++ [r], n ++ [r])
69+
split' (a, b) '<' v = ((a, v - 1), (v, b))
70+
split' (a, b) '>' v = ((v + 1, b), (a, v))
71+
72+
p2 :: (Workflows, [Part]) -> Int
73+
p2 (workflows, _) = validCombinations workflows

0 commit comments

Comments
 (0)