···11+-- |
22+33+{-# LANGUAGE TupleSections #-}
44+55+module AoC.Y2018.Day2
66+where
77+88+import Papa
99+import qualified Data.Map as M (fromListWith, toList)
1010+import qualified Data.Text as T (lines, unpack)
1111+import qualified Data.Text.IO as T (readFile)
1212+import qualified Data.Sequence as C (fromList, elemIndicesL,deleteAt)
1313+1414+type BoxIDs = [String]
1515+data IDMeta = IDMeta
1616+ {
1717+ _id :: String
1818+ , _numTwice :: Int
1919+ , _numThrice :: Int
2020+ } deriving Show
2121+2222+type IDDB = [IDMeta]
2323+2424+parseInput :: FilePath -> IO BoxIDs
2525+parseInput f = do
2626+ ls <- T.readFile f
2727+ return $ T.unpack <$> T.lines ls
2828+2929+transformToIDMeta :: String -> IDMeta
3030+transformToIDMeta s = mkMeta (filter (> 1) $ snd <$> M.toList (M.fromListWith (+) $ (, 1) <$> s)) where
3131+ f :: (Int -> Bool) -> [Int] -> Int
3232+ f p xs = maybe 0 (const 1) (find p xs)
3333+ mkMeta :: [Int] -> IDMeta
3434+ mkMeta xs = IDMeta s (f (==2) xs) (f (==3) xs)
3535+3636+totalTwiceCounts :: IDDB -> Int
3737+totalTwiceCounts = sum . (_numTwice <$>)
3838+3939+totalThriceCounts :: IDDB -> Int
4040+totalThriceCounts = sum . (_numThrice <$>)
4141+4242+checksum :: BoxIDs -> Int
4343+checksum is = let db = transformToIDMeta <$> is
4444+ in
4545+ liftA2 (*) totalTwiceCounts totalThriceCounts db
4646+4747+doDay2Puzzle1 :: FilePath -> IO Int
4848+doDay2Puzzle1 = (<$>) checksum . parseInput
4949+5050+eqIndex :: String -> String -> Maybe Int
5151+eqIndex a b = let is = C.elemIndicesL False $ C.fromList $ zipWith (==) a b
5252+ in
5353+ case is of
5454+ [x] -> Just x
5555+ _ -> Nothing
5656+5757+commonLetters :: [String] -> Maybe String
5858+commonLetters xs = let cs = take 1 $ do
5959+ a <- xs
6060+ b <- xs
6161+ case eqIndex a b of
6262+ Just i -> [toList $ C.deleteAt i (C.fromList a)]
6363+ Nothing -> []
6464+ in
6565+ case cs of
6666+ [x] -> Just x
6767+ _ -> Nothing
6868+6969+doDay2Puzzle2 :: FilePath -> IO (Maybe String)
7070+doDay2Puzzle2 = (<$>) commonLetters . parseInput