diff options
Diffstat (limited to '2022')
| -rw-r--r-- | 2022/25/a.rs | 13 | ||||
| -rw-r--r-- | 2022/25/common.rs | 72 |
2 files changed, 85 insertions, 0 deletions
diff --git a/2022/25/a.rs b/2022/25/a.rs new file mode 100644 index 0000000..1d7e62b --- /dev/null +++ b/2022/25/a.rs | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | mod common; | ||
| 2 | use common::*; | ||
| 3 | |||
| 4 | fn main() { | ||
| 5 | let mut line = String::new(); | ||
| 6 | let mut sum = Snafu::zero(); | ||
| 7 | while std::io::stdin().read_line(&mut line).unwrap() > 0 { | ||
| 8 | let s = Snafu::from_str(&line[..line.len()-1]); | ||
| 9 | sum += &s; | ||
| 10 | line.clear(); | ||
| 11 | } | ||
| 12 | println!("{sum}"); | ||
| 13 | } | ||
diff --git a/2022/25/common.rs b/2022/25/common.rs new file mode 100644 index 0000000..de86470 --- /dev/null +++ b/2022/25/common.rs | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | use std::fmt; | ||
| 2 | use std::ops; | ||
| 3 | use std::cmp; | ||
| 4 | |||
| 5 | pub struct Snafu { | ||
| 6 | d: Vec<i8> | ||
| 7 | } | ||
| 8 | |||
| 9 | impl Snafu { | ||
| 10 | const DIGITS: [char; 5] = ['=', '-', '0', '1', '2']; | ||
| 11 | |||
| 12 | fn digit_to_i8(c: char) -> i8 { | ||
| 13 | for i in 0..5 { | ||
| 14 | if c == Snafu::DIGITS[i] { return i as i8 - 2; } | ||
| 15 | } | ||
| 16 | panic!("Invalid Snafu digit '{}'", c); | ||
| 17 | } | ||
| 18 | |||
| 19 | fn i8_to_digit(i: i8) -> char { | ||
| 20 | if i < -2 || i > 2 { | ||
| 21 | panic!("Invalid Snafu digit value {}", i); | ||
| 22 | } | ||
| 23 | Snafu::DIGITS[(i + 2) as usize] | ||
| 24 | } | ||
| 25 | |||
| 26 | pub fn ndigits(&self) -> usize { | ||
| 27 | self.d.len() | ||
| 28 | } | ||
| 29 | |||
| 30 | pub fn zero() -> Snafu { | ||
| 31 | Snafu { d: vec![0] } | ||
| 32 | } | ||
| 33 | |||
| 34 | pub fn from_str(s: &str) -> Snafu { | ||
| 35 | let mut d = vec![]; | ||
| 36 | for c in s.chars() { d.push(Self::digit_to_i8(c)); } | ||
| 37 | d.reverse(); | ||
| 38 | Snafu { d } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | impl fmt::Display for Snafu { | ||
| 43 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 44 | // Strip leading zeros | ||
| 45 | let mut n = self.ndigits()-1; | ||
| 46 | while self.d[n] == 0 { n -= 1; } | ||
| 47 | |||
| 48 | for i in (0..=n).rev() { | ||
| 49 | write!(f, "{}", Self::i8_to_digit(self.d[i]))?; | ||
| 50 | } | ||
| 51 | Ok(()) | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | impl ops::AddAssign<&Snafu> for Snafu { | ||
| 56 | fn add_assign(&mut self, other: &Snafu) { | ||
| 57 | for i in 0..cmp::max(self.ndigits(), other.ndigits()) { | ||
| 58 | if i < other.ndigits() { | ||
| 59 | self.d[i] += other.d[i]; | ||
| 60 | } | ||
| 61 | |||
| 62 | // Carry over, both ways | ||
| 63 | if i == self.ndigits()-1 { self.d.push(0); } | ||
| 64 | while self.d[i] > 2 { self.d[i+1] += 1; self.d[i] -= 5; } | ||
| 65 | while self.d[i] < -2 { self.d[i+1] -= 1; self.d[i] += 5; } | ||
| 66 | } | ||
| 67 | |||
| 68 | for i in 0..self.ndigits() { | ||
| 69 | if self.d[i] == 0 { self.d.pop(); } else { break; } | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
