1
1
import Data.Char (isDigit )
2
2
import Data.List (elemIndex , find )
3
+ import Data.Map ((!) )
3
4
import Data.Map qualified as M
4
5
import Control.Arrow ((&&&) )
5
6
@@ -33,7 +34,7 @@ valid ws p = go "in"
33
34
where
34
35
go " A" = True
35
36
go " R" = False
36
- go w = go $ next (( M. !) ws w)
37
+ go w = go $ next (ws ! w)
37
38
next ((Nothing , r) : _) = r
38
39
next ((Just c, r) : rs) = if test c then r else next rs
39
40
test (i, ' <' , v) = (p !! i) < v
@@ -42,25 +43,27 @@ valid ws p = go "in"
42
43
p1 :: (Workflows , [Part ]) -> Int
43
44
p1 (workflows, parts) = sum . concat $ filter (valid workflows) parts
44
45
45
- type Ranges = [(Int , Int )]
46
- type Thread = (Ranges , String )
46
+ type Ranges = [(Int , Int )] -- 4 ranges, one for each attribute of a part
47
+ type Thread = (Ranges , String ) -- Ranges undergoing a particular workflow
47
48
48
49
validCombinations :: Workflows -> Int
49
50
validCombinations ws = go [(replicate 4 (1 , 4000 ), " in" )]
50
51
where
51
52
combo :: Ranges -> Int
52
- combo ranges = product $ map ((+ 1 ) . uncurry subtract ) ranges
53
- rules w = ( ( M. !) ws w)
53
+ combo = product . map ((+ 1 ) . uncurry subtract )
54
+
54
55
go :: [Thread ] -> Int
55
56
go [] = 0
56
57
go ((rs, " A" ) : xs) = combo rs + go xs
57
58
go ((_, " R" ) : xs) = go xs
58
- go ((rs, w) : xs) = go $ (splitThreads rs (rules w)) ++ xs
59
+ go ((rs, w) : xs) = go $ splitThreads rs (ws ! w) ++ xs
60
+
59
61
splitThreads :: Ranges -> [Rule ] -> [Thread ]
60
62
splitThreads rs ((Nothing , w) : _) = [(rs, w)]
61
63
splitThreads rs ((Just c, w) : rest) =
62
64
let (matching, notMatching) = split rs c
63
65
in [(matching, w)] ++ splitThreads notMatching rest
66
+
64
67
split :: Ranges -> Condition -> (Ranges , Ranges )
65
68
split ranges (i, op, v) = foldl f ([] , [] ) (zip [0 .. ] ranges)
66
69
where f (m, n) (j, r) | i == j = let (match, nomatch) = split' r op v
0 commit comments