2019: day07: part 2
This commit is contained in:
parent
27f6a072da
commit
83e99215fb
|
@ -12,6 +12,7 @@ pub fn run() -> Result<String> {
|
||||||
let mut res = String::with_capacity(128);
|
let mut res = String::with_capacity(128);
|
||||||
|
|
||||||
writeln!(res, "part 1: {}", part1(INPUT)?)?;
|
writeln!(res, "part 1: {}", part1(INPUT)?)?;
|
||||||
|
writeln!(res, "part 2: {}", part2(INPUT)?)?;
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
@ -67,6 +68,79 @@ fn part1(input: &str) -> Result<i64> {
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn part2(input: &str) -> Result<i64> {
|
||||||
|
let memory = parse_memory(input)?;
|
||||||
|
|
||||||
|
let combinations = permutations(&[5, 6, 7, 8, 9]);
|
||||||
|
|
||||||
|
let mut res = 0;
|
||||||
|
for combination in combinations {
|
||||||
|
let intcodes = &mut [
|
||||||
|
Intcode::with_memory(memory.clone()),
|
||||||
|
Intcode::with_memory(memory.clone()),
|
||||||
|
Intcode::with_memory(memory.clone()),
|
||||||
|
Intcode::with_memory(memory.clone()),
|
||||||
|
Intcode::with_memory(memory.clone()),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (phase, intcode) in combination.iter().zip(intcodes.iter_mut()) {
|
||||||
|
intcode.add_input(*phase);
|
||||||
|
}
|
||||||
|
intcodes[0].add_input(0);
|
||||||
|
|
||||||
|
let mut signal = None;
|
||||||
|
let mut num_halted = 0;
|
||||||
|
loop {
|
||||||
|
for i in 0..(intcodes.len() - 1) {
|
||||||
|
let (first, second) = intcodes.split_at_mut(i + 1);
|
||||||
|
let intcode = &mut first[i];
|
||||||
|
let next = &mut second[0];
|
||||||
|
|
||||||
|
let halted = intcode.run_and_wait()?;
|
||||||
|
if halted {
|
||||||
|
num_halted += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for out in intcode.output.iter() {
|
||||||
|
next.add_input(*out);
|
||||||
|
}
|
||||||
|
intcode.output.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_index = intcodes.len() - 1;
|
||||||
|
let (first, second) = intcodes.split_at_mut(last_index);
|
||||||
|
let first = &mut first[0];
|
||||||
|
let last = &mut second[0];
|
||||||
|
let halted = last.run_and_wait()?;
|
||||||
|
|
||||||
|
if halted {
|
||||||
|
let out = last
|
||||||
|
.output
|
||||||
|
.last()
|
||||||
|
.copied()
|
||||||
|
.ok_or_else(|| err!("last amplifier halted without output"))?;
|
||||||
|
signal = Some(out);
|
||||||
|
} else {
|
||||||
|
for out in last.output.iter() {
|
||||||
|
first.add_input(*out);
|
||||||
|
}
|
||||||
|
last.output.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(signal) = signal {
|
||||||
|
res = std::cmp::max(res, signal);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if num_halted >= 4 {
|
||||||
|
return Err(err!("all non final amplifiers halted, feedback loop stuck"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -87,4 +161,19 @@ mod tests {
|
||||||
fn part1_real() {
|
fn part1_real() {
|
||||||
assert_eq!(part1(INPUT).unwrap(), 844468);
|
assert_eq!(part1(INPUT).unwrap(), 844468);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PROVIDED4: &str =
|
||||||
|
"3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5";
|
||||||
|
const PROVIDED5: &str = "3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_provided() {
|
||||||
|
assert_eq!(part2(PROVIDED4).unwrap(), 139629729);
|
||||||
|
assert_eq!(part2(PROVIDED5).unwrap(), 18216);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn part2_real() {
|
||||||
|
assert_eq!(part2(INPUT).unwrap(), 4215746);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,14 @@ enum Opcode {
|
||||||
Halt,
|
Halt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Intcode {
|
pub struct Intcode {
|
||||||
pub memory: Vec<i64>,
|
pub memory: Vec<i64>,
|
||||||
input: Vec<i64>,
|
input: Vec<i64>,
|
||||||
pub output: Vec<i64>,
|
pub output: Vec<i64>,
|
||||||
ip: usize,
|
ip: usize,
|
||||||
next_input: usize,
|
next_input: usize,
|
||||||
|
wait_input: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Intcode {
|
impl Intcode {
|
||||||
|
@ -46,6 +48,7 @@ impl Intcode {
|
||||||
output: Vec::new(),
|
output: Vec::new(),
|
||||||
ip: 0,
|
ip: 0,
|
||||||
next_input: 0,
|
next_input: 0,
|
||||||
|
wait_input: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +139,7 @@ impl Intcode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> Result<()> {
|
fn exec(&mut self) -> Result<bool> {
|
||||||
loop {
|
loop {
|
||||||
if self.ip >= self.memory.len() {
|
if self.ip >= self.memory.len() {
|
||||||
return Err(err!("reached end of program without halting"));
|
return Err(err!("reached end of program without halting"));
|
||||||
|
@ -165,10 +168,12 @@ impl Intcode {
|
||||||
let input = if self.next_input < self.input.len() {
|
let input = if self.next_input < self.input.len() {
|
||||||
let res = self.input[self.next_input];
|
let res = self.input[self.next_input];
|
||||||
self.next_input += 1;
|
self.next_input += 1;
|
||||||
Ok(res)
|
res
|
||||||
|
} else if self.wait_input {
|
||||||
|
break Ok(false);
|
||||||
} else {
|
} else {
|
||||||
Err(err!("tried to read input but it was empty"))
|
break Err(err!("tried to read input but it was empty"));
|
||||||
}?;
|
};
|
||||||
dst.set(&mut self.memory, input)?;
|
dst.set(&mut self.memory, input)?;
|
||||||
|
|
||||||
self.ip += 2;
|
self.ip += 2;
|
||||||
|
@ -223,11 +228,22 @@ impl Intcode {
|
||||||
|
|
||||||
self.ip += 4;
|
self.ip += 4;
|
||||||
}
|
}
|
||||||
Opcode::Halt => break Ok(()),
|
Opcode::Halt => break Ok(true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_and_wait(&mut self) -> Result<bool> {
|
||||||
|
self.wait_input = true;
|
||||||
|
self.exec()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(&mut self) -> Result<()> {
|
||||||
|
self.wait_input = false;
|
||||||
|
self.exec()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_day02_output(&self) -> Option<i64> {
|
pub fn get_day02_output(&self) -> Option<i64> {
|
||||||
self.memory.get(0).copied()
|
self.memory.get(0).copied()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue