aboutsummaryrefslogtreecommitdiff
path: root/2021/day14/14.hs
diff options
context:
space:
mode:
Diffstat (limited to '2021/day14/14.hs')
-rw-r--r--2021/day14/14.hs43
1 files changed, 43 insertions, 0 deletions
diff --git a/2021/day14/14.hs b/2021/day14/14.hs
new file mode 100644
index 0000000..3221655
--- /dev/null
+++ b/2021/day14/14.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Main where
+
+import Data.Map (Map)
+import qualified Data.Map as M
+import qualified Data.Text as T
+
+type Pair = (Char, Char)
+
+doSubstitutions :: Map Pair Char -> Map Pair Int -> Map Pair Int
+doSubstitutions rules s = M.fromListWith (+) $ concatMap checkPair (M.toList s)
+ where checkPair ((a, b), count) = case M.lookup (a, b) rules of
+ Just v -> [((a, v), count), ((v, b), count)]
+ Nothing -> [((a, b), count)]
+
+stringToPairs :: String -> Map Pair Int
+stringToPairs s = M.fromListWith (+) $ [((a, b), 1) | (a, b) <- (zip s (tail s))] ++ [((last s, '_'), 1)]
+
+countLetters :: Map Pair Int -> Map Char Int
+countLetters m = M.fromListWith (+) [(a, count) | ((a, _), count) <- M.toList m]
+
+parseRuleEntry :: String -> (Pair, Char)
+parseRuleEntry s = ((a, b), head $ T.unpack r)
+ where [t, r] = T.splitOn " -> " (T.pack s)
+ [a, b] = T.unpack t
+
+parseFile :: String -> (Map Pair Int, Map Pair Char)
+parseFile s = (stringToPairs (T.unpack initial), M.fromList $ map parseRuleEntry rules)
+ where [initial, rulesSection] = T.splitOn "\n\n" (T.pack s)
+ rules = lines (T.unpack rulesSection)
+
+
+main :: IO ()
+main = do
+ input <- readFile "./input"
+ let (initial, rules) = parseFile input
+ let result = foldr (\_ acc -> doSubstitutions rules acc) initial [1..40]
+ let counts = countLetters result
+
+ let mx = maximum (M.elems counts)
+ let mi = minimum (M.elems counts)
+ print (mx, mi)
+ print $ mx - mi