summaryrefslogtreecommitdiff
path: root/2024/03/rust/src/main.rs
blob: b268463caa7611cdae0a1ee9c3ce145ac8932f3a (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
use std::io::{self, Read};

#[derive(Debug)]
enum Instruction {
    Do,
    Dont,
    Mul(u64, u64),
}

impl From<&Instruction> for u64 {
    fn from(val: &Instruction) -> Self {
        match val {
            Instruction::Mul(x, y) => x * y,
            _ => 0,
        }
    }
}

fn main() -> io::Result<()> {
    let mut program = String::new();
    io::stdin().read_to_string(&mut program)?;

    let instrs = (0..program.len())
        .filter_map(|idx| {
            let next = &program[idx..];
            if next.starts_with("do()") {
                Some(Instruction::Do)
            } else if next.starts_with("don't()") {
                Some(Instruction::Dont)
            } else if next.starts_with("mul(") {
                let mut first = 0;
                let mut curr = 0;

                for ch in next.bytes().skip(4) {
                    match (ch, curr) {
                        ((b'0'..=b'9'), _) => curr = curr * 10 + (ch - b'0') as u64,
                        (_, 0) => return None,
                        (b',', _) => {
                            first = curr;
                            curr = 0;
                        }
                        (b')', _) => {
                            return Some(Instruction::Mul(first, curr));
                        }
                        _ => return None,
                    };
                }
                None
            } else {
                None
            }
        })
        .collect::<Vec<_>>();

    let silver: u64 = instrs.iter().map(u64::from).sum();
    let (gold, _) = instrs
        .iter()
        .fold((0 as u64, true), |(acc, on), instr| match (instr, on) {
            (Instruction::Do, _) => (acc, true),
            (Instruction::Dont, _) => (acc, false),
            (Instruction::Mul(_, _), true) => (acc + u64::from(instr), true),
            _ => (acc, on),
        });
    println!("silver: {silver}");
    println!("gold: {gold}");

    return Ok(());
}