Skip to content

Instantly share code, notes, and snippets.

@ishitatsuyuki
Created December 7, 2019 05:43
Show Gist options
  • Save ishitatsuyuki/0247ea038ec80b5f1ab962e27d4d59fc to your computer and use it in GitHub Desktop.
Save ishitatsuyuki/0247ea038ec80b5f1ab962e27d4d59fc to your computer and use it in GitHub Desktop.
use itertools::Itertools;
use std::io;
#[derive(Debug, Default)]
struct VM {
pc: usize,
opcode: i32,
mem: Vec<i32>,
input_state: usize,
phase: i32,
signal_in: i32,
signal_out: i32,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum ExecutionState {
Suspended,
Done,
}
impl VM {
fn get(&mut self) -> i32 {
let val = self.mem[self.pc];
let result = match self.opcode % 10 {
0 => self.mem[val as usize],
1 => val,
_ => panic!("Unexpected indirection mode"),
};
self.pc += 1;
self.opcode /= 10;
result
}
fn set(&mut self, val: i32) {
let target = self.mem[self.pc] as usize;
self.mem[target] = val;
self.pc += 1;
}
fn run(&mut self) -> ExecutionState {
use ExecutionState::*;
loop {
self.opcode = self.mem[self.pc];
let op = self.opcode % 100;
self.opcode /= 100;
self.pc += 1;
match op {
1 => {
let val = self.get() + self.get();
self.set(val);
}
2 => {
let val = self.get() * self.get();
self.set(val);
}
3 => {
if self.input_state == 0 {
self.set(self.phase);
} else if self.input_state == 1 {
self.set(self.signal_in);
} else {
self.pc -= 1;
self.input_state -= 1;
return Suspended;
}
self.input_state += 1;
}
4 => {
self.signal_out = self.get();
}
5 => {
let cond = self.get();
let target = self.get() as usize;
if cond != 0 {
self.pc = target;
}
}
6 => {
let cond = self.get();
let target = self.get() as usize;
if cond == 0 {
self.pc = target;
}
}
7 => {
let val = if self.get() < self.get() { 1 } else { 0 };
self.set(val);
}
8 => {
let val = if self.get() == self.get() { 1 } else { 0 };
self.set(val);
}
99 => return Done,
x => panic!("Unexpected opcode: {}", x),
};
}
}
}
fn main() {
let mut buf = String::new();
io::stdin().read_line(&mut buf).unwrap();
let mem: Vec<i32> = buf
.trim_end()
.split(',')
.map(|x| x.parse().unwrap())
.collect();
println!(
"{}",
(5..10)
.permutations(5)
.map(|c| {
let mut vms: Vec<_> = c
.into_iter()
.map(|phase| VM {
mem: mem.clone(),
phase,
..Default::default()
})
.collect();
let mut signal = 0;
'outer: loop {
for (i, vm) in vms.iter_mut().enumerate() {
vm.signal_in = signal;
if vm.run() == ExecutionState::Done && i == 4 {
break 'outer vm.signal_out;
}
signal = vm.signal_out;
}
}
})
.max()
.unwrap()
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment