aboutsummaryrefslogtreecommitdiff
path: root/2022/21/b.rs
blob: e674dd4e0ea93cfdaa39da81be501982773fa591 (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
mod common;
use common::*;

fn solve_for_humn(name: &str, n1: i64, monkeys: &Vec<Monkey>) -> i64 {
    if name == "humn" { return n1; }

    let i = monkeys.iter().position(|m| m.name == name).unwrap();
    if let MonkeyType::Op(op) = &monkeys[i].kind {
        if let Some(n2) = result_or_unknown(&op.m1, &monkeys) {
            // n1 = n2 [op] [unknown]
            match op.op {
                '+' => solve_for_humn(&op.m2, n1-n2, &monkeys),
                '-' => solve_for_humn(&op.m2, n2-n1, &monkeys),
                '*' => solve_for_humn(&op.m2, n1/n2, &monkeys),
                '/' => solve_for_humn(&op.m2, n2/n1, &monkeys),
                _ => panic!("invalid operator")
            }
        } else {
            if let Some(n2) = result_or_unknown(&op.m2, &monkeys) {
                // n1 = [unknown] [op] n2
                match op.op {
                    '+' => solve_for_humn(&op.m1, n1-n2, &monkeys),
                    '-' => solve_for_humn(&op.m1, n1+n2, &monkeys),
                    '*' => solve_for_humn(&op.m1, n1/n2, &monkeys),
                    '/' => solve_for_humn(&op.m1, n1*n2, &monkeys),
                    _ => panic!("invalid operator")
                }
            } else { panic!("both sides undetermined"); }
        }
    } else { panic!("found number when trying to solve for humn"); }
}

fn result_or_unknown(name: &str, monkeys: &Vec<Monkey>) -> Option<i64> {
    if name == "humn" { return None; }

    let i = monkeys.iter().position(|m| m.name == name).unwrap();
    match &monkeys[i].kind {
        MonkeyType::Num(n) => Some(*n),
        MonkeyType::Op(op) => {
            let n1 = result_or_unknown(&op.m1, &monkeys)?;
            let n2 = result_or_unknown(&op.m2, &monkeys)?;
            Some(apply_op(n1, n2, op))
        }
    }
}

pub fn solve(monkeys: &Vec<Monkey>) -> i64 {
    let i = monkeys.iter().position(|m| m.name == "root").unwrap();
    if let MonkeyType::Op(op) = &monkeys[i].kind {
        if let Some(n) = result_or_unknown(&op.m1, &monkeys) {
            return solve_for_humn(&op.m2, n, monkeys);
        } else {
            if let Some(n) = result_or_unknown(&op.m2, &monkeys) {
                return solve_for_humn(&op.m1, n, &monkeys);
            } else { panic!("humn not found"); }
        }
    } else { panic!("root monkey is of type number"); }
}

fn main() {
    let monkeys = read_monkeys_from_stdin();
    println!("{}", solve(&monkeys));
}

Generated with cgit - Back to sebastiano.tronto.net