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    let a = check(&code, 1, 0);
18    let b = check(&code, 0, 1);
19    let c = check(&code, 0, 0);
20
21    [a - c, b - c, c]
22}
23
24pub fn part1([a, b, c]: &Input) -> i32 {
25    a * 12 + b * 2 + c
26}
27
28pub fn part2([a, b, c]: &Input) -> i32 {
29    (0..100)
30        .find_map(|x| {
31            let y = (19690720 - a * x - c) / b;
32            (a * x + b * y + c == 19690720 && (0..100).contains(&y)).then_some(100 * x + y)
33        })
34        .unwrap()
35}
36
37fn check(code: &[usize], first: usize, second: usize) -> i32 {
38    let mut pc = 0;
39    let code = &mut code.to_vec()[..];
40
41    code[1] = first;
42    code[2] = second;
43
44    loop {
45        match code[pc] {
46            1 => code[code[pc + 3]] = code[code[pc + 1]] + code[code[pc + 2]],
47            2 => code[code[pc + 3]] = code[code[pc + 1]] * code[code[pc + 2]],
48            _ => break code[0] as i32,
49        }
50        pc += 4;
51    }
52}