aboutsummaryrefslogtreecommitdiff
path: root/2022/11/common.rs
blob: 68a379afed97569317204c9fa473b95b63251ff0 (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#[derive(Debug)]
pub struct Monkey {
    items: Vec<i64>,
    op: fn(i64, i64) -> i64,
    oparg: i64,
    div: i64,
    iftrue: usize,
    iffalse: usize,
    pub inspected: usize
}

fn read_monkey_from_stdin() -> Monkey {
    let mut line = String::new();
    let stdin = std::io::stdin();

    let _ = stdin.read_line(&mut line);
    line.clear();

    let _ = stdin.read_line(&mut line);
    let mut l = 16;
    let mut items = Vec::<i64>::new();
    while line.chars().nth(l).unwrap() != '\n' {
        l += 2;
        let end = line[l..].find(|c| c == ',' || c == '\n').unwrap() + l;
        items.push(line[l..end].parse::<i64>().unwrap());
        l = end;
    }
    line.clear();

    let _ = stdin.read_line(&mut line);
    let old = line.chars().nth(25).unwrap() == 'o';
    let oparg = if old { 0 } else {
        line[25..line.len()-1].parse::<i64>().unwrap()
    };
    let op = match line.chars().nth(23).unwrap() {
        '*' => if old { |x, _| x * x } else { |x, y| x * y },
        '+' => if old { |x, _| x + x } else { |x, y| x + y },
        c => panic!("Expected operator, got {}", c)
    };
    line.clear();

    let _ = stdin.read_line(&mut line);
    let div = line[21..line.len()-1].parse::<i64>().unwrap();
    line.clear();

    let _ = stdin.read_line(&mut line);
    let iftrue = line[29..line.len()-1].parse::<usize>().unwrap();
    line.clear();

    let _ = stdin.read_line(&mut line);
    let iffalse = line[30..line.len()-1].parse::<usize>().unwrap();
    line.clear();

    Monkey { items, op, oparg, div, iftrue, iffalse, inspected: 0 }
}

pub fn read_input() -> Vec<Monkey> {
    let mut v = Vec::<Monkey>::new();
    let mut line = String::new();
    loop {
        v.push(read_monkey_from_stdin());
        if std::io::stdin().read_line(&mut line).unwrap() == 0 { break; }
    }
    v
}

fn play_round(m: &mut Vec<Monkey>, div: i64, modulus: i64) {
    for i in 0..m.len() {
        for k in 0..m[i].items.len() {
            let mut x = (m[i].op)(m[i].items[k], m[i].oparg) / div;
            if div == 1 { x %= modulus; }
            let j = if x % m[i].div == 0 { m[i].iftrue } else { m[i].iffalse };
            m[j].items.push(x);
        }
        m[i].inspected += m[i].items.len();
        m[i].items.clear();
    }
}

fn get_modulus(monkeys: &Vec<Monkey>) -> i64 {
    let mut modulus = 1;
    for m in monkeys { modulus *= m.div; }
    modulus
}

pub fn res_after_n_rounds(m: &mut Vec<Monkey>, n: usize, div: i64) -> usize {
    let modulus = get_modulus(&m);
    for _ in 0..n { play_round(m, div, modulus); }

    let mut m1 = 0;
    let mut m2 = 0;
    for m in m {
        if m.inspected >= m1 {
            m2 = m1;
            m1 = m.inspected;
        } else if m.inspected >= m2 {
            m2 = m.inspected;
        }
    }

    m1 * m2
}

Generated with cgit - Back to sebastiano.tronto.net