Use intcode module for day 5
This commit is contained in:
parent
074d55a089
commit
b07f615aec
|
@ -7,3 +7,4 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
intcode = { path = "../intcode" }
|
||||||
|
|
|
@ -1,161 +1,7 @@
|
||||||
use std::io;
|
use intcode::*;
|
||||||
use std::io::BufRead;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Operation {
|
|
||||||
Add { x: i32, y: i32, addr: usize },
|
|
||||||
Multiply { x: i32, y: i32, addr: usize },
|
|
||||||
Input { value: i32, addr: usize },
|
|
||||||
Output { value: i32 },
|
|
||||||
JumpIfTrue { value: i32, addr: i32 },
|
|
||||||
JumpIfFalse { value: i32, addr: i32 },
|
|
||||||
LessThan { first: i32, second: i32, addr: i32 },
|
|
||||||
Equals { first: i32, second: i32, addr: i32 },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Mode {
|
|
||||||
Immediate,
|
|
||||||
Position,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ParameterPosition {
|
|
||||||
First,
|
|
||||||
Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<usize> for ParameterPosition {
|
|
||||||
fn into(self) -> usize {
|
|
||||||
match self {
|
|
||||||
ParameterPosition::First => 2,
|
|
||||||
ParameterPosition::Second => 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Mode> for &char {
|
|
||||||
fn into(self) -> Mode {
|
|
||||||
match self {
|
|
||||||
'0' => Mode::Position,
|
|
||||||
'1' => Mode::Immediate,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_next(input: &[i32], pos: &mut i32, mode: Mode) -> i32 {
|
|
||||||
let value = input[*pos as usize];
|
|
||||||
let next = match mode {
|
|
||||||
Mode::Position => input[value as usize],
|
|
||||||
Mode::Immediate => value,
|
|
||||||
};
|
|
||||||
*pos += 1;
|
|
||||||
next
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mode(raw_opcode: &[char], pos: ParameterPosition) -> Mode {
|
|
||||||
raw_opcode.get::<usize>(pos.into()).unwrap_or(&'0').into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_operation(input: &[i32], pos: &mut i32, inp: i32) -> Option<Operation> {
|
|
||||||
let next = get_next(input, 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,
|
|
||||||
}),
|
|
||||||
'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,
|
|
||||||
}),
|
|
||||||
'3' => Some(Operation::Input {
|
|
||||||
value: inp,
|
|
||||||
addr: get_next(input, pos, Mode::Immediate) as usize,
|
|
||||||
}),
|
|
||||||
'4' => Some(Operation::Output {
|
|
||||||
value: get_next(input, 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)),
|
|
||||||
}),
|
|
||||||
'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)),
|
|
||||||
}),
|
|
||||||
'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),
|
|
||||||
}),
|
|
||||||
'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),
|
|
||||||
}),
|
|
||||||
'9' => None,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute(op: Operation, input: &mut Vec<i32>, pos: &mut i32) {
|
|
||||||
match op {
|
|
||||||
Operation::Add { x, y, addr } => input[addr as usize] = x + y,
|
|
||||||
Operation::Multiply { x, y, addr } => input[addr as usize] = x * y,
|
|
||||||
Operation::Input { value, addr } => input[addr] = value,
|
|
||||||
Operation::Output { value } => {
|
|
||||||
if value != 0 {
|
|
||||||
println!("{}", value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Operation::JumpIfTrue { value, addr } => {
|
|
||||||
if value != 0 {
|
|
||||||
*pos = addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Operation::JumpIfFalse { value, addr } => {
|
|
||||||
if value == 0 {
|
|
||||||
*pos = addr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Operation::LessThan {
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
addr,
|
|
||||||
} => input[addr as usize] = (first < second) as i32,
|
|
||||||
Operation::Equals {
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
addr,
|
|
||||||
} => input[addr as usize] = (first == second) as i32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let mut input: Vec<i32> = io::stdin()
|
let input = read_input();
|
||||||
.lock()
|
println!("Part 1: {}", run_for_input(&input, &mut 0, vec![1]));
|
||||||
.lines()
|
println!("Part 2: {}", run_for_input(&input, &mut 0, vec![5]));
|
||||||
.next()
|
|
||||||
.unwrap()
|
|
||||||
.unwrap()
|
|
||||||
.split(',')
|
|
||||||
.map(|n| n.parse().unwrap())
|
|
||||||
.collect();
|
|
||||||
let mut pos = 0;
|
|
||||||
let mut part2_input = input.clone();
|
|
||||||
|
|
||||||
println!("Part 1:");
|
|
||||||
while let Some(op) = next_operation(&input, &mut pos, 1) {
|
|
||||||
execute(op, &mut input, &mut pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
println!("Part 2:");
|
|
||||||
while let Some(op) = next_operation(&part2_input, &mut pos, 5) {
|
|
||||||
execute(op, &mut part2_input, &mut pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
pub struct Amplifier {
|
||||||
|
pub pos: i64,
|
||||||
|
pub tape: Vec<i64>,
|
||||||
|
pub params: Vec<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Amplifier {
|
||||||
|
pub fn run(&mut self) -> Result<i64, i64> {
|
||||||
|
loop {
|
||||||
|
match self.decode_next() {
|
||||||
|
Some(op) => {
|
||||||
|
if let Some(o) = self.execute(op) {
|
||||||
|
return Err(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => return Ok(self.params.pop().unwrap()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_next(&mut self, mode: Mode) -> i64 {
|
||||||
|
let value = self.tape[self.pos as usize];
|
||||||
|
let next = match mode {
|
||||||
|
Mode::Position => self.tape[value as usize],
|
||||||
|
Mode::Immediate => value,
|
||||||
|
};
|
||||||
|
self.pos += 1;
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_next(&mut self) -> Option<Operation> {
|
||||||
|
let next = self.get_next(Mode::Immediate);
|
||||||
|
let mut raw_opcode: Vec<_> = next.to_string().chars().collect();
|
||||||
|
raw_opcode.reverse();
|
||||||
|
match raw_opcode[0] {
|
||||||
|
'1' => Some(Operation::Add {
|
||||||
|
x: self.get_next(get_mode(&raw_opcode, ParameterPosition::First)),
|
||||||
|
y: self.get_next(get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||||
|
addr: self.get_next(Mode::Immediate) as usize,
|
||||||
|
}),
|
||||||
|
'2' => Some(Operation::Multiply {
|
||||||
|
x: self.get_next(get_mode(&raw_opcode, ParameterPosition::First)),
|
||||||
|
y: self.get_next(get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||||
|
addr: self.get_next(Mode::Immediate) as usize,
|
||||||
|
}),
|
||||||
|
'3' => Some(Operation::Input {
|
||||||
|
value: self.params.pop().unwrap(),
|
||||||
|
addr: self.get_next(Mode::Immediate) as usize,
|
||||||
|
}),
|
||||||
|
'4' => Some(Operation::Output {
|
||||||
|
value: self.get_next(get_mode(&raw_opcode, ParameterPosition::First)),
|
||||||
|
}),
|
||||||
|
'5' => Some(Operation::JumpIfTrue {
|
||||||
|
value: self.get_next(get_mode(&raw_opcode, ParameterPosition::First)),
|
||||||
|
addr: self.get_next(get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||||
|
}),
|
||||||
|
'6' => Some(Operation::JumpIfFalse {
|
||||||
|
value: self.get_next(get_mode(&raw_opcode, ParameterPosition::First)),
|
||||||
|
addr: self.get_next(get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||||
|
}),
|
||||||
|
'7' => Some(Operation::LessThan {
|
||||||
|
first: self.get_next(get_mode(&raw_opcode, ParameterPosition::First)),
|
||||||
|
second: self.get_next(get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||||
|
addr: self.get_next(Mode::Immediate),
|
||||||
|
}),
|
||||||
|
'8' => Some(Operation::Equals {
|
||||||
|
first: self.get_next(get_mode(&raw_opcode, ParameterPosition::First)),
|
||||||
|
second: self.get_next(get_mode(&raw_opcode, ParameterPosition::Second)),
|
||||||
|
addr: self.get_next(Mode::Immediate),
|
||||||
|
}),
|
||||||
|
'9' => None,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(&mut self, op: Operation) -> Option<i64> {
|
||||||
|
match op {
|
||||||
|
Operation::Add { x, y, addr } => {
|
||||||
|
self.tape[addr as usize] = x + y;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Operation::Multiply { x, y, addr } => {
|
||||||
|
self.tape[addr as usize] = x * y;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Operation::Input { value, addr } => {
|
||||||
|
self.tape[addr] = value;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Operation::Output { value } => Some(value),
|
||||||
|
Operation::JumpIfTrue { value, addr } => {
|
||||||
|
if value != 0 {
|
||||||
|
self.pos = addr
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Operation::JumpIfFalse { value, addr } => {
|
||||||
|
if value == 0 {
|
||||||
|
self.pos = addr
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Operation::LessThan {
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
addr,
|
||||||
|
} => {
|
||||||
|
self.tape[addr as usize] = (first < second) as i64;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Operation::Equals {
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
addr,
|
||||||
|
} => {
|
||||||
|
self.tape[addr as usize] = (first == second) as i64;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mode(raw_opcode: &[char], pos: ParameterPosition) -> Mode {
|
||||||
|
raw_opcode.get::<usize>(pos.into()).unwrap_or(&'0').into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Operation {
|
||||||
|
Add { x: i64, y: i64, addr: usize },
|
||||||
|
Multiply { x: i64, y: i64, addr: usize },
|
||||||
|
Input { value: i64, addr: usize },
|
||||||
|
Output { value: i64 },
|
||||||
|
JumpIfTrue { value: i64, addr: i64 },
|
||||||
|
JumpIfFalse { value: i64, addr: i64 },
|
||||||
|
LessThan { first: i64, second: i64, addr: i64 },
|
||||||
|
Equals { first: i64, second: i64, addr: i64 },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Mode {
|
||||||
|
Immediate,
|
||||||
|
Position,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParameterPosition {
|
||||||
|
First,
|
||||||
|
Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<usize> for ParameterPosition {
|
||||||
|
fn into(self) -> usize {
|
||||||
|
match self {
|
||||||
|
ParameterPosition::First => 2,
|
||||||
|
ParameterPosition::Second => 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<Mode> for &char {
|
||||||
|
fn into(self) -> Mode {
|
||||||
|
match self {
|
||||||
|
'0' => Mode::Position,
|
||||||
|
'1' => Mode::Immediate,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,174 +2,28 @@ use itertools::Itertools;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::io::{self, BufRead};
|
use std::io::{self, BufRead};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
use amplifier::*;
|
||||||
|
mod amplifier;
|
||||||
|
|
||||||
#[derive(Debug)]
|
/**
|
||||||
enum Operation {
|
* Construct amplifiers and run all of them for a single given input tape
|
||||||
Add { x: i64, y: i64, addr: usize },
|
* and a vector of amplifier configurations.
|
||||||
Multiply { x: i64, y: i64, addr: usize },
|
*
|
||||||
Input { value: i64, addr: usize },
|
* Returns the return value of the first halted amplifier.
|
||||||
Output { value: i64 },
|
*/
|
||||||
JumpIfTrue { value: i64, addr: i64 },
|
pub fn run_for_input(input: &Vec<i64>, acc: &mut i64, amp_phases: Vec<i64>) -> i64 {
|
||||||
JumpIfFalse { value: i64, addr: i64 },
|
let mut amplifiers: Vec<_> = amp_phases
|
||||||
LessThan { first: i64, second: i64, addr: i64 },
|
|
||||||
Equals { first: i64, second: i64, addr: i64 },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum Mode {
|
|
||||||
Immediate,
|
|
||||||
Position,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ParameterPosition {
|
|
||||||
First,
|
|
||||||
Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Machine {
|
|
||||||
pos: i64,
|
|
||||||
tape: Vec<i64>,
|
|
||||||
params: Vec<i64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<usize> for ParameterPosition {
|
|
||||||
fn into(self) -> usize {
|
|
||||||
match self {
|
|
||||||
ParameterPosition::First => 2,
|
|
||||||
ParameterPosition::Second => 3,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<Mode> for &char {
|
|
||||||
fn into(self) -> Mode {
|
|
||||||
match self {
|
|
||||||
'0' => Mode::Position,
|
|
||||||
'1' => Mode::Immediate,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_next(input: &[i64], pos: &mut i64, mode: Mode) -> i64 {
|
|
||||||
let value = input[*pos as usize];
|
|
||||||
let next = match mode {
|
|
||||||
Mode::Position => input[value as usize],
|
|
||||||
Mode::Immediate => value,
|
|
||||||
};
|
|
||||||
*pos += 1;
|
|
||||||
next
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_mode(raw_opcode: &[char], pos: ParameterPosition) -> Mode {
|
|
||||||
raw_opcode.get::<usize>(pos.into()).unwrap_or(&'0').into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
fn decode_next(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(&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(&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: machine.params.pop().unwrap(),
|
|
||||||
addr: get_next(&machine.tape, &mut machine.pos, Mode::Immediate) as usize,
|
|
||||||
}),
|
|
||||||
'4' => Some(Operation::Output {
|
|
||||||
value: get_next(&machine.tape, &mut machine.pos, get_mode(&raw_opcode, ParameterPosition::First)),
|
|
||||||
}),
|
|
||||||
'5' => Some(Operation::JumpIfTrue {
|
|
||||||
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(&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(&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(&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!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn execute(op: Operation, input: &mut Vec<i64>, pos: &mut i64) -> Option<i64> {
|
|
||||||
match op {
|
|
||||||
Operation::Add { x, y, addr } => {
|
|
||||||
input[addr as usize] = x + y;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Operation::Multiply { x, y, addr } => {
|
|
||||||
input[addr as usize] = x * y;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Operation::Input { value, addr } => {
|
|
||||||
input[addr] = value;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Operation::Output { value } => Some(value),
|
|
||||||
Operation::JumpIfTrue { value, addr } => {
|
|
||||||
if value != 0 {
|
|
||||||
*pos = addr
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Operation::JumpIfFalse { value, addr } => {
|
|
||||||
if value == 0 {
|
|
||||||
*pos = addr
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Operation::LessThan {
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
addr,
|
|
||||||
} => {
|
|
||||||
input[addr as usize] = (first < second) as i64;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
Operation::Equals {
|
|
||||||
first,
|
|
||||||
second,
|
|
||||||
addr,
|
|
||||||
} => {
|
|
||||||
input[addr as usize] = (first == second) as i64;
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_for_input(input: &Vec<i64>, acc: &mut i64, amps: Vec<i64>) -> i64 {
|
|
||||||
let mut machines: Vec<_> = amps
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|amp| Machine {
|
.map(|amp| Amplifier {
|
||||||
tape: input.clone(),
|
tape: input.clone(),
|
||||||
pos: 0,
|
pos: 0,
|
||||||
params: vec![amp],
|
params: vec![amp],
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
for state in (0..machines.len()).cycle() {
|
for state in (0..amplifiers.len()).cycle() {
|
||||||
let mut machine = machines.get_mut(state).unwrap();
|
let amplifier = amplifiers.get_mut(state).unwrap();
|
||||||
machine.params.insert(0, *acc);
|
amplifier.params.insert(0, *acc);
|
||||||
match execute_machine(&mut machine) {
|
match amplifier.run() {
|
||||||
Err(output) => *acc = output,
|
Err(output) => *acc = output,
|
||||||
Ok(_) => break,
|
Ok(_) => break,
|
||||||
}
|
}
|
||||||
|
@ -177,6 +31,10 @@ pub fn run_for_input(input: &Vec<i64>, acc: &mut i64, amps: Vec<i64>) -> i64 {
|
||||||
*acc
|
*acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for day 7.
|
||||||
|
* Will try all combinations of parameters in the given range and return the maximum result.
|
||||||
|
*/
|
||||||
pub fn find_max(range: Range<i64>, input: &Vec<i64>) -> Option<i64> {
|
pub fn find_max(range: Range<i64>, input: &Vec<i64>) -> Option<i64> {
|
||||||
usize::try_from(range.end - range.start)
|
usize::try_from(range.end - range.start)
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -190,19 +48,6 @@ pub fn find_max(range: Range<i64>, input: &Vec<i64>) -> Option<i64> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_machine(machine: &mut Machine) -> Result<i64, i64> {
|
|
||||||
loop {
|
|
||||||
match decode_next(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()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub fn read_input() -> Vec<i64> {
|
pub fn read_input() -> Vec<i64> {
|
||||||
io::stdin().lock().lines().next().unwrap().unwrap().split(',').map(|n| n.parse().unwrap()).collect()
|
io::stdin().lock().lines().next().unwrap().unwrap().split(',').map(|n| n.parse().unwrap()).collect()
|
||||||
|
|
|
@ -49,3 +49,83 @@ fn test_find_max_with_loops() {
|
||||||
Some(18216)
|
Some(18216)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_position_less_than() {
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,9,8,9,10,9,4,9,99,-1,8"),
|
||||||
|
&mut 0,
|
||||||
|
vec![8]
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,9,8,9,10,9,4,9,99,-1,8"),
|
||||||
|
&mut 0,
|
||||||
|
vec![7]
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_position_equals() {
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,9,7,9,10,9,4,9,99,-1,8"),
|
||||||
|
&mut 0,
|
||||||
|
vec![8]
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,9,7,9,10,9,4,9,99,-1,8"),
|
||||||
|
&mut 0,
|
||||||
|
vec![7]
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_immediate_less_than() {
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,3,1107,-1,8,3,4,3,99"),
|
||||||
|
&mut 0,
|
||||||
|
vec![8]
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,3,1107,-1,8,3,4,3,99"),
|
||||||
|
&mut 0,
|
||||||
|
vec![7]
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_immediate_equals() {
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,3,1108,-1,8,3,4,3,99"),
|
||||||
|
&mut 0,
|
||||||
|
vec![8]
|
||||||
|
),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
run_for_input(
|
||||||
|
&parse_test_input("3,3,1108,-1,8,3,4,3,99"),
|
||||||
|
&mut 0,
|
||||||
|
vec![7]
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user