This repository was archived by the owner on Nov 17, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathDay21.hs
66 lines (57 loc) · 1.93 KB
/
Day21.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Module : AOC.Challenge.Day21
-- License : BSD3
--
-- Stability : experimental
-- Portability : non-portable
--
-- Day 21. See "AOC.Solver" for the types used in this module!
module AOC.Challenge.Day21 (
day21a
, day21b
) where
import AOC.Common (parseLines, pickUnique, countTrue)
import AOC.Solver ((:~>)(..))
import Data.Foldable (toList)
import Data.Functor ((<&>))
import Data.List (intercalate)
import Data.Maybe (listToMaybe)
import Data.Set (Set)
import Data.Void (Void)
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Text.Megaparsec as P
import qualified Text.Megaparsec.Char as P
assembleOptions
:: (Ord k, Ord a)
=> [(Set a, Set k)]
-> [(k, Set a)]
assembleOptions info = M.toList . M.unionsWith S.intersection $
info <&> \(igr, alg) -> M.fromSet (const igr) alg
day21a :: [(Set String, Set String)] :~> Int
day21a = MkSol
{ sParse = parseLines lineParser
, sShow = show
, sSolve = \igrsAlgs ->
fmap (countNotIn (concatMap (toList . fst) igrsAlgs))
. listToMaybe
. map (S.fromList . toList)
. pickUnique
$ assembleOptions igrsAlgs
}
where
countNotIn xs bad = countTrue (`S.notMember` bad) xs
day21b :: [(Set String, Set String)] :~> [String]
day21b = MkSol
{ sParse = parseLines lineParser
, sShow = intercalate ","
, sSolve = fmap toList . listToMaybe . pickUnique . assembleOptions
}
type Parser = P.Parsec Void String
lineParser :: Parser (Set String, Set String)
lineParser =
(,) <$> (S.fromList <$> P.many (P.some P.letterChar <* " "))
<*> (S.fromList <$> P.between "(" ")"
("contains " *> P.some P.letterChar `P.sepBy` ", ")
)