year2019/
day02.rs

1use crate::intcode::Interpreter;
2use crate::intcode::features::Day02Features;
3use utils::prelude::*;
4
5/// Interpreting assembly with add and multiply instructions.
6///
7/// Part 2 assumes the output grows monotonically with both inputs and that the first input
8/// is more significant than the second input.
9#[derive(Clone, Debug)]
10pub struct Day02 {
11    interpreter: Interpreter,
12}
13
14const PART2_TARGET: i64 = 19_690_720;
15
16impl Day02 {
17    pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
18        Ok(Self {
19            interpreter: Interpreter::parse(input, 3)?,
20        })
21    }
22
23    #[must_use]
24    pub fn part1(&self) -> i64 {
25        self.run(12, 2)
26    }
27
28    #[must_use]
29    pub fn part2(&self) -> u32 {
30        let mut noun_lo = 0u32;
31        let mut noun_hi = 99u32;
32        while noun_lo + 1 < noun_hi {
33            let mid = noun_lo + (noun_hi - noun_lo) / 2;
34            if self.run(mid as i64, 0) <= PART2_TARGET {
35                noun_lo = mid;
36            } else {
37                noun_hi = mid;
38            }
39        }
40
41        let mut verb_lo = 0u32;
42        let mut verb_hi = 99u32;
43        while verb_lo + 1 < verb_hi {
44            let mid = verb_lo + (verb_hi - verb_lo) / 2;
45            if self.run(noun_lo as i64, mid as i64) <= PART2_TARGET {
46                verb_lo = mid;
47            } else {
48                verb_hi = mid;
49            }
50        }
51
52        assert_eq!(
53            self.run(noun_lo as i64, verb_lo as i64),
54            PART2_TARGET,
55            "no solution found"
56        );
57
58        noun_lo * 100 + verb_lo
59    }
60
61    fn run(&self, noun: i64, verb: i64) -> i64 {
62        let mut interpreter = self.interpreter.clone();
63        interpreter.mem[1] = noun;
64        interpreter.mem[2] = verb;
65
66        let _ = interpreter.run::<Day02Features>();
67
68        interpreter.mem[0]
69    }
70}
71
72examples!(Day02 -> (i64, u32) []);