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