Advent of Code 2022 day 25

    Day 25 was the Advent of Code tradition of a one-part problem, even though this had two parts. (And it wasn't until after I'd done this that I found the name for this kind of representation: balanced numbers, such as balanced ternary.)

    The conversion from SNAFU numbers to decimal was just like any other base conversion: read a digit, multiply by the base, convert the rest.

    readSnafu :: String -> Int
    readSnafu cs = foldl' go 0 cs
      where go acc c = acc * 5 + (snafuValue c)
    
    snafuValue :: Char -> Int
    snafuValue '2' = 2
    snafuValue '1' = 1
    snafuValue '0' = 0
    snafuValue '-' = -1
    snafuValue '=' = -2

    The conversion from decimal to SNAFU took a bit more thinking. Eventually I worked out that, once you'd fixed the least significant few digits, those wouldn't change as more significant digits were added.

    I took a long-winded approach of converting the number into a list of base-five elements (from least significant digit to most significant), then converting each digit in turn. If a digit was 3 or 4, I added a carry to the next digit.

    showSnafu :: Int -> String
    showSnafu = packSnafu . toBase5R
    
    toBase5R :: Int -> [Int]
    toBase5R 0 = []
    toBase5R n = (r : (toBase5R k))
      where (k, r) = n `divMod` 5
    
    packSnafu :: [Int] -> String
    packSnafu digits
      | carry == 0 = shown
      | otherwise = (snafuRep carry) : shown
      where (carry, shown) = foldl' packSnafuDigit (0, "") digits
    
    packSnafuDigit :: (Int, String) -> Int -> (Int, String)
    packSnafuDigit (carry, acc) d 
      | d' <= 2 = (0, (snafuRep d') : acc)
      | otherwise = (1, (snafuRep (d' - 5) : acc))
      where d' = d + carry
    
    snafuRep :: Int -> Char
    snafuRep 2 = '2'
    snafuRep 1 = '1'
    snafuRep 0 = '0'
    snafuRep -1 = '-'
    snafuRep -2 = '='
    snafuRep _ = error "Illegal number in show"

    And that was it! All over for another year.

    Code

    You can get the code from my locally-hosted Git repo, or from Gitlab.

    Neil Smith

    Read more posts by this author.