I liked this one!
import Control.Arrow
import Control.Monad
import Data.List
import Data.Ratio
simpleTrain = uncurry (%) . (head &&& last) . map read
compoundTrain input =
let a = read $ head input
z = read $ last input
gs =
map
( uncurry (%)
. (read *** read . tail)
. break (== '|')
)
$ (tail . init) input
in foldl' (/) (a % z) gs
part1, part2, part3 :: [String] -> Integer
part1 = floor . (2025 *) . simpleTrain
part2 = ceiling . (10000000000000 /) . simpleTrain
part3 = floor . (100 *) . compoundTrain
main =
forM_
[ ("everybody_codes_e2025_q04_p1.txt", part1),
("everybody_codes_e2025_q04_p2.txt", part2),
("everybody_codes_e2025_q04_p3.txt", part3)
]
$ \(input, solve) -> readFile input >>= print . solve . lines
I forgot that "weekdays" for a US website means something different for me here in UTC+9.
This was surprisingly fiddly, but I think I managed to do it reasonably neatly.