aoc2017 icon indicating copy to clipboard operation
aoc2017 copied to clipboard

Advent of Code 2017 - my answers

Advent of Code 2017

my answers in Haskell

This project builds with The Haskell Tool Stack.

Setup:

curl -sSL https://get.haskellstack.org/ | sh -s -
stack setup

If you encounter linker errors with the commands below, try stack setup --ghc-build=nopie or adding

ghc-build: nopie

to ~/.stack/config.yaml.

Run the HSpec test suite:

stack test aoc2017:test:aoc2017-test

Run criterion benchmarks:

stack bench aoc2017:bench:aoc2017-bench

Print solutions for the inputs provided in local data files:

stack build aoc2017:exe:aoc2017-exe
stack exec aoc2017-exe

Animate the Day 11 path (rendered at Gyfcat):

stack build aoc2017:exe:aoc2017-day11
stack exec aoc2017-day11
ffmpeg -vf lavfi -i nullsrc=s=$(identify day11-0000.png | cut -d' ' -f3):d=30 -framerate 300 -i 'day11-%04d.png' -vf '[0:v][1:v]overlay[video]' -map '[video]' -r 60 -c:v libx264 -pix_fmt yuv420p -profile:v baseline -level 3.0 -movflags +faststart -y day11.mp4

Animate the Day 14 grid (rendered at Gyfcat):

stack build aoc2017:exe:aoc2017-day14
stack exec aoc2017-day14
ffmpeg -framerate 60 -i 'day11-%04d.png' -c:v libx264 -pix_fmt yuv420p -profile:v baseline -level 3.0 -movflags +faststart -y day11.mp4

Generate Haddock API documentation (rendered at ephemient.github.io/aoc2017):

stack haddock aoc2017:lib

Day 1: Inverse Captcha

import Day1 (day1a, day1b)

Day 2: Corruption Checksum

import Day2 (day2a, day2b)

Day 3: Spiral Memory

import Day3 (day3a, day3b)

Day 4: High-Entropy Passphrases

import Day4 (day4a, day4b)

Day 5: A Maze of Twisty Trampolines, All Alike

import Day5 (day5a, day5b)

Day 6: Memory Reallocation

import Day6 (day6a, day6b)

Day 7: Recursive Circus

import Day7 (day7a, day7b)

Day 8: I Heard You Like Registers

import Day8 (day8a, day8b)

Day 9: Stream Processing

import Day9 (day9a, day9b)

Day 10: Knot Hash

import Day10 (day10a, day10b)

Day 11: Hex Ed

import Day11 (day11a, day11b)

Day 12: Digital Plumber

import Day12 (day12a, day12b)

Day 13: Packet Scanners

import Day13 (day13a, day13b)

Day 14: Disk Defragmentation

import Day14 (day14a, day14b)

Day 15: Dueling Generators

import Day15 (day15a, day15b)

Day 16: Permutation Promenade

import Day16 (day16a, day16b)

Day 17: Spinlock

import Day17 (day17a, day17b)

Day 18: Duet

import Day18 (day18a, day18b)

Day 19: A Series of Tubes

import Day19 (day19a, day19b)

Day 20: Particle Swarm

import Day20 (day20a, day20b)

Day 21: Fractal Art

import Day21 (day21a, day21b)

Day 22: Sporifica Virus

import Day22 (day22a, day22b)

Day 23: Coprocessor Conflagration

import Day23 (day23a, day23b)

Day 24: Electromagnetic Moat

import Day24 (day24a, day24b)

Day 25: The Halting Problem

import Day25 (day25)

import Control.Monad (when)
import Data.Maybe (mapMaybe)
import Paths_aoc2017 (getDataFileName)
import System.Environment (getArgs)
import Text.Read (readMaybe)

getDayInput :: Int -> IO String
getDayInput i = getDataFileName ("day" ++ show i ++ ".txt") >>= readFile

readDayInput :: (Read a) => Int -> IO a
readDayInput = fmap read . getDayInput

maybeBottom :: (a -> String) -> Maybe a -> String
maybeBottom = maybe "(⊥)"

showError :: (Show a) => (b -> String) -> Either a b -> String
showError = either (\err -> "(" ++ show err ++ ")")

run :: Int -> (Int -> IO a) -> (b -> IO ()) -> [a -> b] -> IO ()
run day readIO showIO funcs = do
    days <- mapMaybe readMaybe <$> getArgs
    when (null days || day `elem` days) $ do
    putStrLn $ "Day " ++ show day
    contents <- readIO day
    mapM_ (showIO . ($ contents)) funcs
    putStrLn ""

main :: IO ()
main = do
    run 1 getDayInput print [day1a, day1b]
    run 2 getDayInput print [day2a, day2b]
    run 3 readDayInput print [day3a, day3b]
    run 4 getDayInput print [day4a, day4b]
    run 5 getDayInput print [day5a, day5b]
    run 6 getDayInput (putStrLn . maybeBottom show) [day6a, day6b]
    run 7 getDayInput (putStrLn . maybeBottom id) [day7a, fmap show . day7b]
    run 8 getDayInput print [day8a, day8b]
    run 9 getDayInput print [day9a, day9b]
    run 10 getDayInput putStrLn [show . day10a 256, day10b]
    run 11 getDayInput print [day11a, day11b]
    run 12 getDayInput print [day12a, day12b]
    run 13 getDayInput print [day13a, day13b]
    run 14 getDayInput print [day14a, day14b]
    run 15 getDayInput print [day15a, day15b]
    run 16 getDayInput putStrLn [day16a 16, day16b 16 1000000000]
    run 17 readDayInput print [day17a, day17b]
    run 18 getDayInput print [fromIntegral . day18a, day18b]
    run 19 getDayInput putStrLn [day19a, show . day19b]
    run 20 getDayInput print [day20a, length . day20b]
    run 21 getDayInput print [day21a, day21b]
    run 22 getDayInput print [day22a, day22b]
    run 23 getDayInput print [day23a, day23b]
    run 24 getDayInput print [day24a, day24b]
    run 25 getDayInput print [day25]