aboutsummaryrefslogtreecommitdiff
path: root/2021/day14/14.hs
blob: 322165584d3ca00645aca327401176334e2c9e20 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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