{-# 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 [([[Char]], [[Char]])]
inp <- [format|2020 21 (%s& %(contains %s&(, )%)%n)*|]
let [Map [Char] [Char]
soln] = Map [Char] (Set [Char]) -> [Map [Char] [Char]]
forall (t :: * -> *) a.
(Traversable t, Ord a) =>
t (Set a) -> [t a]
uniqueAssignment ([([[Char]], [[Char]])] -> Map [Char] (Set [Char])
forall a b. (Ord a, Ord b) => [([a], [b])] -> Map b (Set a)
toConstraints [([[Char]], [[Char]])]
inp)
badFoods :: Set [Char]
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)
Int -> IO ()
forall a. Show a => a -> IO ()
print (([Char] -> Bool) -> [[Char]] -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countBy ([Char] -> Set [Char] -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.notMember` Set [Char]
badFoods) ((([[Char]], [[Char]]) -> [[Char]])
-> [([[Char]], [[Char]])] -> [[Char]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([[Char]], [[Char]]) -> [[Char]]
forall a b. (a, b) -> a
fst [([[Char]], [[Char]])]
inp))
[Char] -> IO ()
putStrLn ([Char] -> [[Char]] -> [Char]
forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"," (Map [Char] [Char] -> [[Char]]
forall k a. Map k a -> [a]
Map.elems Map [Char] [Char]
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]