refactor out find_max function
This commit is contained in:
parent
55bf996963
commit
45e5da75b0
|
@ -1,6 +1,7 @@
|
|||
use itertools::Itertools;
|
||||
use std::io;
|
||||
use std::io::BufRead;
|
||||
use std::ops::Range;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Operation {
|
||||
|
@ -25,6 +26,12 @@ enum ParameterPosition {
|
|||
Second,
|
||||
}
|
||||
|
||||
struct Machine {
|
||||
pos: i64,
|
||||
tape: Vec<i64>,
|
||||
params: Vec<i64>,
|
||||
}
|
||||
|
||||
impl Into<usize> for ParameterPosition {
|
||||
fn into(self) -> usize {
|
||||
match self {
|
||||
|
@ -58,45 +65,46 @@ fn get_mode(raw_opcode: &[char], pos: ParameterPosition) -> Mode {
|
|||
raw_opcode.get::<usize>(pos.into()).unwrap_or(&'0').into()
|
||||
}
|
||||
|
||||
fn next_operation(input: &[i64], pos: &mut i64, inputs: &mut Vec<i64>) -> Option<Operation> {
|
||||
let next = get_next(input, pos, Mode::Immediate);
|
||||
#[rustfmt::skip]
|
||||
fn next_operation(machine: &mut Machine) -> Option<Operation> {
|
||||
let next = get_next(&machine.tape, &mut machine.pos, Mode::Immediate);
|
||||
let mut raw_opcode: Vec<_> = next.to_string().chars().collect();
|
||||
raw_opcode.reverse();
|
||||
match raw_opcode[0] {
|
||||
'1' => Some(Operation::Add {
|
||||
x: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
y: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(input, pos, Mode::Immediate) as usize,
|
||||
x: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
y: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(&machine.tape, &mut machine.pos, Mode::Immediate) as usize,
|
||||
}),
|
||||
'2' => Some(Operation::Multiply {
|
||||
x: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
y: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(input, pos, Mode::Immediate) as usize,
|
||||
x: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
y: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(&machine.tape, &mut machine.pos, Mode::Immediate) as usize,
|
||||
}),
|
||||
'3' => Some(Operation::Input {
|
||||
value: inputs.pop().unwrap(),
|
||||
addr: get_next(input, pos, Mode::Immediate) as usize,
|
||||
value: machine.params.pop().unwrap(),
|
||||
addr: get_next(&machine.tape, &mut machine.pos, Mode::Immediate) as usize,
|
||||
}),
|
||||
'4' => Some(Operation::Output {
|
||||
value: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
value: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
}),
|
||||
'5' => Some(Operation::JumpIfTrue {
|
||||
value: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
addr: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
value: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
addr: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
}),
|
||||
'6' => Some(Operation::JumpIfFalse {
|
||||
value: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
addr: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
value: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
addr: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
}),
|
||||
'7' => Some(Operation::LessThan {
|
||||
first: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
second: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(input, pos, Mode::Immediate),
|
||||
first: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
second: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(&machine.tape, &mut machine.pos, Mode::Immediate),
|
||||
}),
|
||||
'8' => Some(Operation::Equals {
|
||||
first: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
second: get_next(input, pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(input, pos, Mode::Immediate),
|
||||
first: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
||||
second: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||
addr: get_next(&machine.tape, &mut machine.pos, Mode::Immediate),
|
||||
}),
|
||||
'9' => None,
|
||||
_ => unreachable!(),
|
||||
|
@ -149,6 +157,46 @@ fn execute(op: Operation, input: &mut Vec<i64>, pos: &mut i64) -> Option<i64> {
|
|||
}
|
||||
}
|
||||
|
||||
fn find_max(range: Range<i64>, input: &Vec<i64>) -> i64 {
|
||||
range
|
||||
.permutations(5)
|
||||
.map(|amps| {
|
||||
let mut last_output = 0;
|
||||
let mut machines: Vec<_> = amps
|
||||
.into_iter()
|
||||
.map(|amp| Machine {
|
||||
tape: input.clone(),
|
||||
pos: 0,
|
||||
params: vec![amp],
|
||||
})
|
||||
.collect();
|
||||
for state in (0..5).cycle() {
|
||||
let mut machine = machines.get_mut(state).unwrap();
|
||||
machine.params.insert(0, last_output);
|
||||
match execute_machine(&mut machine) {
|
||||
Err(output) => last_output = output,
|
||||
Ok(_) => break,
|
||||
}
|
||||
}
|
||||
last_output
|
||||
})
|
||||
.max()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn execute_machine(machine: &mut Machine) -> Result<i64, i64> {
|
||||
loop {
|
||||
match next_operation(machine) {
|
||||
Some(op) => {
|
||||
if let Some(o) = execute(op, &mut machine.tape, &mut machine.pos) {
|
||||
return Err(o);
|
||||
}
|
||||
}
|
||||
None => return Ok(machine.params.pop().unwrap()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let input: Vec<i64> = io::stdin()
|
||||
.lock()
|
||||
|
@ -160,60 +208,6 @@ pub fn main() {
|
|||
.map(|n| n.parse().unwrap())
|
||||
.collect();
|
||||
|
||||
let p1: i64 = (0..5)
|
||||
.permutations(5)
|
||||
.map(|amps| {
|
||||
let mut last_output = 0;
|
||||
for amp in amps {
|
||||
let mut pos = 0;
|
||||
let mut tape = input.clone();
|
||||
let mut params = vec![last_output, amp];
|
||||
match execute_machine(&mut tape, &mut pos, &mut params) {
|
||||
Ok(o) => last_output = o,
|
||||
Err(o) => last_output = o,
|
||||
}
|
||||
}
|
||||
last_output
|
||||
})
|
||||
.max()
|
||||
.unwrap();
|
||||
println!("Part 1: {}", p1);
|
||||
|
||||
let p2: i64 = (5..10)
|
||||
.permutations(5)
|
||||
.map(|amps| {
|
||||
let mut last_output = 0;
|
||||
let mut inputs: Vec<_> = amps.into_iter().map(move |amp| vec![amp]).collect();
|
||||
let mut positions = vec![0, 0, 0, 0, 0];
|
||||
let mut states: Vec<_> = (0..5).map(|_| input.clone()).collect();
|
||||
for state in (0..5).cycle() {
|
||||
let mut part1_input = states.get_mut(state).unwrap();
|
||||
let mut pos = positions.get_mut(state).unwrap();
|
||||
let mut params = inputs.get_mut(state).unwrap();
|
||||
params.insert(0, last_output);
|
||||
match execute_machine(&mut part1_input, &mut pos, &mut params) {
|
||||
Err(output) => last_output = output,
|
||||
Ok(_) => break,
|
||||
}
|
||||
}
|
||||
last_output
|
||||
})
|
||||
.max()
|
||||
.unwrap();
|
||||
println!("Part 2: {}", p2);
|
||||
}
|
||||
|
||||
fn execute_machine(tape: &mut Vec<i64>, pos: &mut i64, params: &mut Vec<i64>) -> Result<i64, i64> {
|
||||
loop {
|
||||
match next_operation(tape, pos, params) {
|
||||
Some(op) => {
|
||||
if let Some(o) = execute(op, tape, pos) {
|
||||
return Err(o);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return Ok((params.pop().unwrap()));
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("Part 1: {}", find_max(0..5, &input));
|
||||
println!("Part 2: {}", find_max(5..10, &input));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user