Skip to main content

aoc/year2019/
day02.rs

1//! # 1202 Program Alarm
2//!
3//! Substituting symbols instead of numbers into the program shows that it calculates the value of:
4//!
5//! `a * noun + b * verb + c`
6//!
7//! We can isolate the value of the constants a, b, c in order to speed up subsequent calculations.
8//!
9//! Since the equation is linear in noun and verb, we can efficiently solve part two by iterating
10//! over possible noun values and computing the corresponding verb directly.
11use crate::util::parse::*;
12
13type Input = [i32; 3];
14
15pub fn parse(input: &str) -> Input {
16    let code: Vec<_> = input.iter_unsigned().collect();
17
18    let c = check(&code, 0, 0) as i32;
19    let a = check(&code, 1, 0) as i32;
20    let b = check(&code, 0, 1) as i32;
21
22    [a - c, b - c, c]
23}
24
25pub fn part1([a, b, c]: &Input) -> i32 {
26    a * 12 + b * 2 + c
27}
28
29pub fn part2([a, b, c]: &Input) -> i32 {
30    (0..100)
31        .find_map(|x| {
32            let y = (19690720 - a * x - c) / b;
33            (a * x + b * y + c == 19690720 && (0..100).contains(&y)).then_some(100 * x + y)
34        })
35        .unwrap()
36}
37
38fn check(input: &[usize], first: usize, second: usize) -> usize {
39    let mut code = input.to_vec();
40    code[1] = first;
41    code[2] = second;
42
43    execute(&mut code)
44}
45
46fn execute(code: &mut [usize]) -> usize {
47    let mut pc = 0;
48
49    loop {
50        match code[pc] {
51            1 => code[code[pc + 3]] = code[code[pc + 1]] + code[code[pc + 2]],
52            2 => code[code[pc + 3]] = code[code[pc + 1]] * code[code[pc + 2]],
53            _ => break code[0],
54        }
55        pc += 4;
56    }
57}