{-# Language QuasiQuotes, ImportQualifiedPost #-}
{-|
Module      : Main
Description : Day 25 solution
Copyright   : (c) Eric Mertens, 2022
License     : ISC
Maintainer  : emertens@gmail.com

<https://adventofcode.com/2022/day/25>

>>> :{
:main +
    "1=-0-2\n\
    \12111\n\
    \2=0=\n\
    \21\n\
    \2=01\n\
    \111\n\
    \20012\n\
    \112\n\
    \1=-1=\n\
    \1-12\n\
    \12\n\
    \1=\n\
    \122\n"
:}
2=-1=0

-}
module Main where

import Advent (format)

-- |
-- >>> :main
-- 20-==01-2-=1-2---1-0
main :: IO ()
IO ()
main =
 do [[Char]]
input <- [format|2022 25 (%s%n)*|]
    [Char] -> IO ()
putStrLn (Int -> [Char]
toSnafu ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (([Char] -> Int) -> [[Char]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [Char] -> Int
fromSnafu [[Char]]
input)))

fromSnafu :: String -> Int
fromSnafu :: [Char] -> Int
fromSnafu = (Int -> Char -> Int) -> Int -> [Char] -> Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Int -> Char -> Int
f Int
0
  where
    f :: Int -> Char -> Int
f Int
acc Char
c = Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
acc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
fromS Char
c

toSnafu :: Int -> String
toSnafu :: Int -> [Char]
toSnafu = [Char] -> Int -> [Char]
go [Char]
""
  where
    go :: [Char] -> Int -> [Char]
go [Char]
acc Int
0 = [Char]
acc
    go [Char]
acc Int
n = [Char] -> Int -> [Char]
go (Int -> Char
toS (Int
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2) Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: [Char]
acc) Int
n'
      where
        (Int
n',Int
m) = (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
5

toS :: Int -> Char
toS :: Int -> Char
toS (-2) = Char
'='
toS (-1) = Char
'-'
toS Int
0 = Char
'0'
toS Int
1 = Char
'1'
toS Int
2 = Char
'2'
toS Int
_ = [Char] -> Char
forall a. HasCallStack => [Char] -> a
error [Char]
"toS: bad digit"

fromS :: Char -> Int
fromS :: Char -> Int
fromS Char
'2' = Int
2
fromS Char
'1' = Int
1
fromS Char
'0' = Int
0
fromS Char
'-' = -Int
1
fromS Char
'=' = -Int
2
fromS Char
_ = [Char] -> Int
forall a. HasCallStack => [Char] -> a
error [Char]
"fromS: bad digit"