aboutsummaryrefslogtreecommitdiffstats
path: root/day14/main.hs
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2021-12-14 08:45:15 +0200
committerJan Tuomi <jans.tuomi@gmail.com>2021-12-15 09:59:09 +0200
commitca42298c307a3009720d6bc93f294ae308168262 (patch)
tree14a79e1132340b198cde39410e24ebbbfad46014 /day14/main.hs
parent31ca38b2824a8d4e8257e14b1a783016ff37258e (diff)
Day 14
Diffstat (limited to 'day14/main.hs')
-rw-r--r--day14/main.hs87
1 files changed, 87 insertions, 0 deletions
diff --git a/day14/main.hs b/day14/main.hs
new file mode 100644
index 0000000..46974d1
--- /dev/null
+++ b/day14/main.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
+
+module Main where
+
+import Data.Function (on)
+import qualified Data.List as L
+import Data.Map.Strict (Map, (!))
+import qualified Data.Map.Strict as M
+import Data.Text (pack, replace, unpack)
+import Data.Vector.Unboxed (Vector)
+import qualified Data.Vector.Unboxed as V
+import Debug.Trace (traceShow)
+import Utils
+
+recur1 :: Vector Char -> Map (Char, Char) Char -> Int -> Vector Char
+recur1 initial rules n
+ | n == 0 = initial
+ | otherwise =
+ let pairs = V.zip initial (V.tail initial)
+ inserted = pairs $> V.concatMap (\p@(a, _) -> V.fromList [a, rules ! p])
+ result = V.snoc inserted (V.last initial)
+ in recur1 result rules (n - 1)
+
+e1 initial rules =
+ let polymer = recur1 (V.fromList initial) rules 10
+ lengthPairs = polymer $> V.map (\c -> (c, V.length $ V.filter (== c) polymer))
+ (mc, mcN) = lengthPairs $> V.maximumBy (compare `on` snd)
+ (lc, lcN) = lengthPairs $> V.minimumBy (compare `on` snd)
+ in mcN - lcN
+
+type CPair = (Char, Char)
+
+type PairFreqMap = Map CPair Integer
+
+type CFreqMap = Map Char Integer
+
+type RuleMap = Map CPair Char
+
+type Maps = (PairFreqMap, CFreqMap, RuleMap)
+
+recur2 :: Maps -> Int -> CFreqMap
+recur2 maps@(pairFreq, cFreq, rules) n
+ | n == 0 = cFreq
+ | otherwise =
+ let pairs = M.keys pairFreq
+ (pairFreq', cFreq') =
+ L.foldl'
+ ( \(accPairFreq, accCFreq) pair@(a, b) ->
+ let c = rules ! pair
+ totalPairFreq = pairFreq ! pair
+ pairFreq' =
+ accPairFreq
+ $> M.insertWith (+) (a, c) totalPairFreq
+ .> M.insertWith (+) (c, b) totalPairFreq
+ .> M.adjust (\v -> v - totalPairFreq) pair
+ cFreq' = M.insertWith (+) c totalPairFreq accCFreq
+ in (pairFreq', cFreq')
+ )
+ (pairFreq, cFreq)
+ pairs
+ in recur2 (pairFreq', cFreq', rules) (n - 1)
+
+e2 initial rules =
+ let pairs = zip initial (tail initial)
+ pairFreqMap = L.foldl' (\acc p -> M.insertWith (+) p 1 acc) M.empty pairs
+ cFreqMap = L.foldl' (\acc c -> M.insertWith (+) c 1 acc) M.empty initial
+ resultCFreqMap = recur2 (pairFreqMap, cFreqMap, rules) 40
+ mcN = L.maximum (M.elems resultCFreqMap)
+ lcN = L.minimum (M.elems resultCFreqMap)
+ in mcN - lcN
+
+main :: IO ()
+main =
+ do
+ contents <- getContents
+
+ let input = contents $> lines
+ let initial = head input
+ let rules' =
+ tail (tail input)
+ $> map (pack .> replace (pack " -> ") (pack "") .> unpack)
+ .> map (\[x, y, z] -> ((x, y), z))
+
+ let rules = M.fromList rules'
+ e1 initial rules $> print
+ e2 initial rules $> print