aoc/year2022/
day25.rs

1//! # Full of Hot Air
2//!
3//! The SNAFU numbers are balanced quinary, similar to
4//! [an actual base](https://en.wikipedia.org/wiki/Balanced_ternary)
5//! used by some experimental computers.
6pub fn parse(input: &str) -> Vec<&str> {
7    input.lines().collect()
8}
9
10pub fn part1(input: &[&str]) -> String {
11    to_snafu(input.iter().map(from_snafu).sum())
12}
13
14pub fn part2(_input: &[&str]) -> &'static str {
15    "n/a"
16}
17
18/// Converting from SNAFU to decimal is straightforward.
19fn from_snafu(snafu: &&str) -> i64 {
20    snafu.bytes().fold(0, |acc, c| {
21        let digit = match c {
22            b'=' => -2,
23            b'-' => -1,
24            b'0' => 0,
25            b'1' => 1,
26            b'2' => 2,
27            _ => unreachable!(),
28        };
29        5 * acc + digit
30    })
31}
32
33/// Convert to decimal by first finding the result modulus 5 for each digit.
34/// If the answer is 3 or 4 then we must add a carry to the next digit so account for the
35/// subtraction.
36fn to_snafu(mut n: i64) -> String {
37    let mut digits = String::new();
38
39    while n > 0 {
40        let next = match n % 5 {
41            0 => '0',
42            1 => '1',
43            2 => '2',
44            3 => '=',
45            4 => '-',
46            _ => unreachable!(),
47        };
48        digits.insert(0, next);
49        // If the remainder of n is 3 or higher then this will add a carry digit to account
50        // for the subtraction.
51        n = (n + 2) / 5;
52    }
53
54    digits
55}