aboutsummaryrefslogtreecommitdiff
path: root/2022/25/common.rs
blob: de86470684413860718ecae66a12f6c0fcb3ecf2 (plain)
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use std::fmt;
use std::ops;
use std::cmp;

pub struct Snafu {
    d: Vec<i8>
}

impl Snafu {
    const DIGITS: [char; 5] = ['=', '-', '0', '1', '2'];

    fn digit_to_i8(c: char) -> i8 {
        for i in 0..5 {
            if c == Snafu::DIGITS[i] { return i as i8 - 2; }
        }
        panic!("Invalid Snafu digit '{}'", c);
    }

    fn i8_to_digit(i: i8) -> char {
        if i < -2 || i > 2 {
            panic!("Invalid Snafu digit value {}", i);
        }
        Snafu::DIGITS[(i + 2) as usize]
    }

    pub fn ndigits(&self) -> usize {
        self.d.len()
    }

    pub fn zero() -> Snafu {
        Snafu { d: vec![0] }
    }

    pub fn from_str(s: &str) -> Snafu {
        let mut d = vec![];
        for c in s.chars() { d.push(Self::digit_to_i8(c)); }
        d.reverse();
        Snafu { d }
    }
}

impl fmt::Display for Snafu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Strip leading zeros
        let mut n = self.ndigits()-1;
        while self.d[n] == 0 { n -= 1; }

        for i in (0..=n).rev() {
            write!(f, "{}", Self::i8_to_digit(self.d[i]))?;
        }
        Ok(())
    }
}

impl ops::AddAssign<&Snafu> for Snafu {
    fn add_assign(&mut self, other: &Snafu) {
        for i in 0..cmp::max(self.ndigits(), other.ndigits()) {
            if i < other.ndigits() {
                self.d[i] += other.d[i];
            }

            // Carry over, both ways
            if i == self.ndigits()-1 { self.d.push(0); }
            while self.d[i] > 2  { self.d[i+1] += 1; self.d[i] -= 5; }
            while self.d[i] < -2 { self.d[i+1] -= 1; self.d[i] += 5; }
        }

        for i in 0..self.ndigits() {
            if self.d[i] == 0 { self.d.pop(); } else { break; }
        }
    }
}

Generated with cgit - Back to sebastiano.tronto.net