{-# Language ImportQualifiedPost, QuasiQuotes #-}
module Main (main) where
import Advent (countBy, uniqueAssignment)
import Advent.Format (format)
import Data.List (intercalate, sort)
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Set (Set)
import Data.Set qualified as Set
main :: IO ()
IO ()
main =
do inp <- [format|2020 21 (%s& %(contains %s&(, )%)%n)*|]
let [soln] = uniqueAssignment (toConstraints inp)
badFoods = [[Char]] -> Set [Char]
forall a. Ord a => [a] -> Set a
Set.fromList (Map [Char] [Char] -> [[Char]]
forall k a. Map k a -> [a]
Map.elems Map [Char] [Char]
soln)
print (countBy (`Set.notMember` badFoods) (concatMap fst inp))
putStrLn (intercalate "," (Map.elems soln))
toConstraints :: (Ord a, Ord b) => [([a],[b])] -> Map b (Set a)
toConstraints :: forall a b. (Ord a, Ord b) => [([a], [b])] -> Map b (Set a)
toConstraints [([a], [b])]
inp =
(Set a -> Set a -> Set a) -> [(b, Set a)] -> Map b (Set a)
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Set a -> Set a -> Set a
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection
[(b
y, [a] -> Set a
forall a. Ord a => [a] -> Set a
Set.fromList [a]
xs) | ([a]
xs, [b]
ys) <- [([a], [b])]
inp, b
y <- [b]
ys]