advent-2021/6/solution.hs

48 lines
1.4 KiB
Haskell

import Data.List
main :: IO ()
main = do
input <- readFile "6/input.txt"
let x = parse input
-- Problem 1
print $ f x
-- Problem 2
print $ g x
where
f = solve 80
g = solve 256
parse :: String -> [Int]
parse = map read . words . map f
where f ',' = ' '
f x = x
-- Solve the problem by creating an association list mapping a
-- value for the internal timer to a number of fishies as the seed,
-- and then simulating `n` iterations of growth.
solve :: Int -- ^ n: The number of generations to simulate
-> [Int] -- ^ The initial population
-> Int -- ^ The total population at the end of n generations
solve n = sum . map snd . simulate n . map assoc . group . sort
where assoc x = (head x, length x)
-- Simulate `n` iterations of growth and return the state
-- after that many iterations.
simulate :: Int -> [(Int, Int)] -> [(Int, Int)]
simulate 0 st = st
simulate n st = simulate (n - 1) (update st)
-- Update the simulation state by one iteration.
update :: [(Int, Int)] -> [(Int, Int)]
update = merge . (>>= f)
where f (0, n) = [(6, n), (8, n)]
f (t, n) = [(t - 1, n)]
-- Merge the values of duplicate key entries and produce a new list
-- where each key is mapped to the sum of all values associated with
-- that key.
merge :: [(Int, Int)] -> [(Int, Int)]
merge [] = []
merge ((t,n) : ls) = (t, n + sum (map snd x)) : merge r
where (x,r) = partition ((== t) . fst) ls