Optimised day 19
[advent-of-code-22.git] / advent25 / Main.hs
1 -- Writeup at https://work.njae.me.uk/2022/12/01/advent-of-code-2022-day-1/
2
3 import AoC
4 import Data.List
5
6
7 main :: IO ()
8 main =
9 do dataFileName <- getDataFileName
10 numStrs <- readFile dataFileName
11 let fuels = fmap readSnafu $ lines numStrs
12 putStrLn $ showSnafu $ sum fuels
13
14 readSnafu :: String -> Int
15 readSnafu cs = foldl' go 0 cs
16 where go acc c = acc * 5 + (snafuValue c)
17
18 snafuValue :: Char -> Int
19 snafuValue '2' = 2
20 snafuValue '1' = 1
21 snafuValue '0' = 0
22 snafuValue '-' = -1
23 snafuValue '=' = -2
24 snafuValue _ = error "Illegal digit in read"
25
26 showSnafu :: Int -> String
27 showSnafu = packSnafu . toBase5R
28
29 toBase5R :: Int -> [Int]
30 toBase5R 0 = []
31 toBase5R n = (r : (toBase5R k))
32 where (k, r) = n `divMod` 5
33
34 packSnafu :: [Int] -> String
35 packSnafu digits
36 | carry == 0 = shown
37 | otherwise = (snafuRep carry) : shown
38 where (carry, shown) = foldl' packSnafuDigit (0, "") digits
39
40 packSnafuDigit :: (Int, String) -> Int -> (Int, String)
41 packSnafuDigit (carry, acc) d
42 | d' <= 2 = (0, (snafuRep d') : acc)
43 | otherwise = (1, (snafuRep (d' - 5) : acc))
44 where d' = d + carry
45
46 snafuRep :: Int -> Char
47 snafuRep 2 = '2'
48 snafuRep 1 = '1'
49 snafuRep 0 = '0'
50 snafuRep -1 = '-'
51 snafuRep -2 = '='
52 snafuRep _ = error "Illegal number in show"