1
1
import Data.Char (isDigit )
2
- import Data.List (elemIndex )
2
+ import Data.List (elemIndex , find )
3
3
import Data.Map qualified as M
4
4
5
5
main :: IO ()
6
- main = interact $ (++ " \n " ) . show . parse
6
+ main = interact $ (++ " \n " ) . show . p1 . parse
7
7
8
8
type Workflows = M. Map String [Rule ]
9
9
type Rule = (Maybe Condition , String )
@@ -13,14 +13,14 @@ type Part = [Int]
13
13
parse :: String -> (Workflows , [Part ])
14
14
parse = both . lines
15
15
where
16
- both s = let (a, b) = span (/= " " ) s in (workflows a, map part b )
16
+ both s = let (a, b) = span (/= " " ) s in (workflows a, map part ( drop 1 b) )
17
17
workflows = M. fromList . map workflow
18
18
workflow s = (rules . drop 1 ) <$> break (== ' {' ) s
19
19
rules [] = []
20
20
rules s = let (a, b) = break (`elem` " ,}" ) s in rule a : rules (drop 1 b)
21
21
rule s = case break (== ' :' ) s of
22
22
(r, [] ) -> (Nothing , r)
23
- (c, r) -> (Just (condition c), r)
23
+ (c, r) -> (Just (condition c), drop 1 r)
24
24
condition (p: c: rs) = case p `elemIndex` " xmas" of
25
25
Just i -> (i, c, read rs)
26
26
part s = case reads (snd $ break isDigit s) of
@@ -32,3 +32,11 @@ valid ws p = go "in"
32
32
where
33
33
go " A" = True
34
34
go " R" = False
35
+ go w = go $ next ((M. !) ws w)
36
+ next ((Nothing , r) : _) = r
37
+ next ((Just c, r) : rs) = if test c then r else next rs
38
+ test (i, ' <' , v) = (p !! i) < v
39
+ test (i, ' >' , v) = (p !! i) > v
40
+
41
+ p1 :: (Workflows , [Part ]) -> Int
42
+ p1 (workflows, parts) = sum . concat $ filter (valid workflows) parts
0 commit comments