Amidst all my other projects and pastimes, I’ve decided to make a serious effort to learn Haskell.
I’m still working my way through Learn You A Haskell For Great Good, but it’s time to practice writing some actual programs.
It’s time for Advent of Code!
This is a correct solution for part 1 of the puzzle for
Day 1, 2025. It’s the
most complex Haskell program I’ve written to date, and I think I
might even almost understand the bind operator (>>=)!
{--
Haskell solution for Advent Of Code 2025 day 1 (a).
Given:
* A virtual combination lock whose dial can freely rotate through
positions numbered 0 to 99 so that rotating right (clockwise) one
step from position 99 goes to position 0 and rotating left
(anticlockwise) one step from position 0 goes to position 99.
* An initial dial position of 50.
* A file `input.txt` containing a list of rotations, one per line,
of the form Lx or Rx (regex: "[LR]\d+") denoting rotations by
x steps left or right. E.g:
L68
L30
R48
L5
Find:
* The number of times the dial is at position 0 after a rotation.
Run with:
runghc aoc-2025-01a.hs
December 31, 2025 by Jarvis Cochrane
Copyright (c) 2025 Jarvis Cochrane
--}
initial_position = 50 :: Int
-- Convert a code to a positive (right) or negative (left) integer
readCode :: String -> Int
readCode ('L':xs) = - (read xs :: Int)
readCode ('R':xs) = (read xs :: Int)
-- Convert list of codes to list of +/- integers
readCodes :: [String] -> [Int]
readCodes xs = map readCode xs
-- Replace each code with the result of rotating the dial as specified
-- rotateDial 50 (readCodes ["L5", "R10"]) -> [45, 55]
rotateDial :: Int -> [Int] -> [Int]
rotateDial dialPosition [] = []
rotateDial dialPosition (x:xs) =
let newDialPosition = (dialPosition + x) `mod` 100
in newDialPosition : rotateDial newDialPosition xs
-- Return the number of zeros found in the list
countZeros :: [Int] -> Int
countZeros xs = length $ filter (\x -> x == 0) xs
-- Return the number of zeroes found by applying the code sequence to
-- the initial position
solve :: [String] -> Int
solve xs = countZeros $ rotateDial initial_position $ readCodes xs
-- Read input file, solve, and output result
main = readFile "input.txt" >>= (putStrLn . show . solve . lines)