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
//! # Springdroid Adventure
//!
//! Jumps are always 4 tiles wide landing on `D`. If needed we can jump again immediately
//! landing on `H`.
//!
//! ## Part One
//!
//! We jump if any of `A`, `B` or `C` are holes and there is ground where we will land at `D`.
//! This take 7 instructions:
//!
//! `J = (NOT A OR NOT B OR NOT C) AND D`
//!
//! Using [De Morgan's laws](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) we can simplify
//! to 5 instructions:
//!
//! `J = NOT (A AND B AND C) AND D`
//!
//! ## Part Two
//!
//! We add two rules, either `H` needs to be ground so that we double jump immediately or `E`
//! needs to be ground, so that we can wait and not jump too early.
use super::intcode::*;
use crate::util::parse::*;

const SLOW: &str = "\
OR A J
AND B J
AND C J
NOT J J
AND D J";

const FAST: &str = "\
OR E T
OR H T
AND T J";

pub fn parse(input: &str) -> Vec<i64> {
    input.iter_signed().collect()
}

pub fn part1(input: &[i64]) -> i64 {
    survey(input, &format!("{SLOW}\nWALK\n"))
}

pub fn part2(input: &[i64]) -> i64 {
    survey(input, &format!("{SLOW}\n{FAST}\nRUN\n"))
}

fn survey(input: &[i64], springscript: &str) -> i64 {
    let mut computer = Computer::new(input);
    computer.input_ascii(springscript);

    let mut result = 0;
    while let State::Output(next) = computer.run() {
        result = next;
    }
    result
}