summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2019/rust/Cargo.toml1
-rw-r--r--2019/rust/day07/Cargo.toml8
-rwxr-xr-x2019/rust/day07/calibrate_amplifiers.sh36
-rwxr-xr-x2019/rust/day07/calibrate_amplifiers_with_feedback.sh50
-rw-r--r--2019/rust/day07/src/main.rs195
5 files changed, 290 insertions, 0 deletions
diff --git a/2019/rust/Cargo.toml b/2019/rust/Cargo.toml
index cd02164..a361d72 100644
--- a/2019/rust/Cargo.toml
+++ b/2019/rust/Cargo.toml
@@ -6,4 +6,5 @@ members = [
"day04",
"day05",
"day06",
+ "day07",
]
diff --git a/2019/rust/day07/Cargo.toml b/2019/rust/day07/Cargo.toml
new file mode 100644
index 0000000..e4a691f
--- /dev/null
+++ b/2019/rust/day07/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "day07"
+version = "0.1.0"
+authors = ["cos <cos>"]
+edition = "2018"
+
+[dependencies]
+getopts = "0.2"
diff --git a/2019/rust/day07/calibrate_amplifiers.sh b/2019/rust/day07/calibrate_amplifiers.sh
new file mode 100755
index 0000000..917dfa7
--- /dev/null
+++ b/2019/rust/day07/calibrate_amplifiers.sh
@@ -0,0 +1,36 @@
+#!/bin/sh -e
+
+H=0
+I=0
+P=""
+for A in `seq 0 4`; do
+ for B in `seq 0 4`; do
+ for C in `seq 0 4`; do
+ for D in `seq 0 4`; do
+ for E in `seq 0 4`; do
+ [ ${A} -ne ${B} ] || continue
+ [ ${A} -ne ${C} ] || continue
+ [ ${A} -ne ${D} ] || continue
+ [ ${A} -ne ${E} ] || continue
+ [ ${B} -ne ${C} ] || continue
+ [ ${B} -ne ${D} ] || continue
+ [ ${B} -ne ${E} ] || continue
+ [ ${C} -ne ${D} ] || continue
+ [ ${C} -ne ${E} ] || continue
+ [ ${D} -ne ${E} ] || continue
+
+ O=`RUST_BACKTRACE=1 ../target/debug/day07 \
+ --mode arg --program input "${A},${I},${B},${C},${D},${E}"`
+ V=`echo "${O}" | tail -1`
+ [ "${H}" -ge "${V}" ] || {
+ P="${A},${B},${C},${D},${E}";
+ H="${V}";
+ HI="${I}";
+ }
+ done
+ done
+ done
+ done
+done
+
+echo "Highest value: ${H} for phase set ${P}"
diff --git a/2019/rust/day07/calibrate_amplifiers_with_feedback.sh b/2019/rust/day07/calibrate_amplifiers_with_feedback.sh
new file mode 100755
index 0000000..7a3a896
--- /dev/null
+++ b/2019/rust/day07/calibrate_amplifiers_with_feedback.sh
@@ -0,0 +1,50 @@
+#!/bin/sh -e
+
+launch_chain()
+{
+ local input_file="input_$1_$2_$3_$4_$5_$6.txt"
+ local p="input"
+
+ (echo ${6}; (echo ${5}; (echo ${4}; (echo ${3}; (echo "${2}
+ ${1}" > "${input_file}";tail -f "${input_file}")| RUST_BACKTRACE=1 \
+ ../target/debug/day07 --mode stdio --program "${p}") | \
+ ../target/debug/day07 --mode stdio --program "${p}") | \
+ ../target/debug/day07 --mode stdio --program "${p}") | \
+ ../target/debug/day07 --mode stdio --program "${p}") | \
+ ../target/debug/day07 --mode stdio --program "${p}" >> "${input_file}"
+ tail -1 "${input_file}"
+}
+
+H=0
+I=0
+P=""
+for A in `seq 5 9`; do
+ for B in `seq 5 9`; do
+ for C in `seq 5 9`; do
+ for D in `seq 5 9`; do
+ for E in `seq 5 9`; do
+ [ ${A} -ne ${B} ] || continue
+ [ ${A} -ne ${C} ] || continue
+ [ ${A} -ne ${D} ] || continue
+ [ ${A} -ne ${E} ] || continue
+ [ ${B} -ne ${C} ] || continue
+ [ ${B} -ne ${D} ] || continue
+ [ ${B} -ne ${E} ] || continue
+ [ ${C} -ne ${D} ] || continue
+ [ ${C} -ne ${E} ] || continue
+ [ ${D} -ne ${E} ] || continue
+
+ O=`launch_chain ${I} ${A} ${B} ${C} ${D} ${E}`
+ V=`echo "${O}" | tail -1 `
+ [ "${H}" -ge "${V}" ] || {
+ P="${A},${B},${C},${D},${E}";
+ H="${V}";
+ HI="${I}";
+ }
+ done
+ done
+ done
+ done
+done
+
+echo "Highest value: ${H} for phase set ${P}"
diff --git a/2019/rust/day07/src/main.rs b/2019/rust/day07/src/main.rs
new file mode 100644
index 0000000..98b02ce
--- /dev/null
+++ b/2019/rust/day07/src/main.rs
@@ -0,0 +1,195 @@
+use std::env;
+use std::fs;
+use std::io::{self, BufRead};
+
+type BusWidth = i32;
+type IOType = i32;
+type IOData = Vec<IOType>;
+
+fn read_program(filename: &str) -> Vec<BusWidth> {
+ let contents = fs::read_to_string(filename)
+ .expect(filename);
+
+ contents.split(',').map(|v| {
+ v.trim_end().parse().unwrap()
+ }).collect()
+}
+
+#[derive(Debug)]
+enum Arithm {
+ Add,
+ Mul,
+ LessThan,
+ Equals,
+}
+
+#[derive(Debug)]
+enum IO {
+ In,
+ Out,
+}
+
+#[derive(Debug)]
+enum Jmp {
+ JmpTrue,
+ JmpFalse,
+}
+
+#[derive(Debug, PartialEq)]
+enum ParameterMode {
+ Position,
+ Immediate,
+}
+
+fn arithm(op:Arithm, ip:usize, modes:Vec<ParameterMode>, memory:&mut Vec<BusWidth>) {
+ if modes[2] == ParameterMode::Immediate {
+ panic!("Instruction can not store in immediate mode parameter. (IP: {})", ip);
+ }
+ let params:Vec<usize> = (0..=2).map(|n| match &modes[n] {
+ ParameterMode::Position => memory[ip + n + 1] as usize,
+ ParameterMode::Immediate => ip + n + 1,
+ }).collect();
+ let left = params[0];
+ let right = params[1];
+ let result = params[2];
+
+ match op {
+ Arithm::Add => memory[result] = memory[left] + memory[right],
+ Arithm::Mul => memory[result] = memory[left] * memory[right],
+ Arithm::LessThan => memory[result] = if memory[left] < memory[right] { 1 } else { 0 },
+ Arithm::Equals => memory[result] = if memory[left] == memory[right] { 1 } else { 0 },
+ }
+}
+
+fn jmp(op:Jmp, ip:usize, modes:Vec<ParameterMode>, memory:&mut Vec<BusWidth>) -> usize {
+ let params:Vec<usize> = (0..=2).map(|n| match &modes[n] {
+ ParameterMode::Position => memory[ip + n + 1] as usize,
+ ParameterMode::Immediate => ip + n + 1,
+ }).collect();
+ let value = params[0];
+ let address = params[1];
+
+ match op {
+ Jmp::JmpTrue => (if memory[value] != 0 { memory[address] as usize } else { ip + 3 }),
+ Jmp::JmpFalse => (if memory[value] == 0 { memory[address] as usize } else { ip + 3 }),
+ }
+}
+
+fn io(op: IO, ip: usize, modes: Vec<ParameterMode>, memory:&mut Vec<BusWidth>, input:&mut IOData,
+ output:&mut IOData, var_io: bool)
+{
+ let stdin = io::stdin();
+
+ match op {
+ IO::In => {
+ let address = match &modes[0] {
+ ParameterMode::Position => memory[ip + 1] as usize,
+ ParameterMode::Immediate =>
+ panic!("Cannot store input in immediate mode parameter. (IP: {})", ip),
+ };
+
+ match var_io {
+ false => {
+ let invalue = stdin.lock().lines().next().map(|s| {
+ match s {
+ Ok(s) => Some(s.trim_end().trim_start().parse::<BusWidth>().unwrap()),
+ _ => None,
+ }
+ });
+ match invalue {
+ Some(v) => memory[address] = v.unwrap() as BusWidth,
+ _ => {},
+ };
+ },
+ true => {
+ memory[address] = input.remove(0) as BusWidth;
+ },
+ }
+
+ },
+ IO::Out => {
+ let o = match &modes[0] {
+ ParameterMode::Position => memory[memory[ip + 1] as usize],
+ ParameterMode::Immediate => memory[ip + 1],
+ };
+ println!("{}", o);
+ if var_io {
+ output.push(o as IOType);
+ }
+ },
+ }
+}
+
+fn intcode<F>(mut memory:Vec<BusWidth>, mut input: &mut IOData, mut output:&mut IOData,
+ f: F, var_io: bool) where
+F: Fn(&mut Vec<BusWidth>, &mut IOData, &mut IOData)
+{
+ let mut ip = 0;
+
+ while ip < memory.len() {
+
+ let op = memory[ip] % 100;
+ let modes:Vec<ParameterMode> = (2..=4).map(|e| memory[ip] / 10i32.pow(e) as BusWidth % 10)
+ .map(|n| match n {
+ 0 => ParameterMode::Position,
+ 1 => ParameterMode::Immediate,
+ p => panic!("Invalid parameter mode {} at IP: {}", p, ip),
+ }).collect();
+ match op {
+ 1 => { arithm(Arithm::Add, ip, modes, &mut memory); ip += 4 },
+ 2 => { arithm(Arithm::Mul, ip, modes, &mut memory); ip += 4 },
+ 7 => { arithm(Arithm::LessThan, ip, modes, &mut memory); ip += 4 },
+ 8 => { arithm(Arithm::Equals, ip, modes, &mut memory); ip += 4 },
+ 3 => { io(IO::In, ip, modes, &mut memory, &mut input, &mut output, var_io); ip += 2 },
+ 4 => { io(IO::Out, ip, modes, &mut memory, &mut input, &mut output, var_io); ip += 2 },
+ 5 => { ip = jmp(Jmp::JmpTrue, ip, modes, &mut memory); },
+ 6 => { ip = jmp(Jmp::JmpFalse, ip, modes, &mut memory); },
+ 99 => break,
+ op => panic!("Invalid operation {} at IP: {}", op, ip),
+ }
+
+ if var_io {
+ f(&mut memory, &mut input, &mut output);
+ }
+ }
+}
+
+fn func(_memory:&mut Vec<BusWidth>, input:&mut IOData, output:&mut IOData) {
+ if output.len() > 0 && input.len() > 0 {
+ let v = output.remove(0);
+ input.insert(1, v);
+ }
+}
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+
+ let mut opts = getopts::Options::new();
+ opts.reqopt("m", "mode", "Mode of IO operations", "[arg|stdio]");
+ opts.reqopt("p", "program", "File to load program from", "FILE");
+ let matches = match opts.parse(&args[1..]) {
+ Ok(m) => { m }
+ Err(f) => { panic!(f.to_string()) }
+ };
+ let program:String = matches.opt_str("program").unwrap();
+ let mode = matches.opt_str("mode").unwrap();
+ let memory = read_program(&program);
+
+ if mode == "arg" {
+ let mut input:IOData = matches.free[0].split(",").map(|v| {
+ let i = v.trim_end().parse().unwrap();
+ i
+ }).collect();
+ let mut output = Vec::new();
+ while input.len() > 1 {
+ intcode(memory.clone(), &mut input, &mut output, &func, true);
+ }
+ } else if mode == "stdio" {
+ let mut input = vec![];
+ let mut output = vec![];
+
+ intcode(memory.clone(), &mut input, &mut output, &func, false);
+ } else {
+ panic!("Unknown mode: {}", mode);
+ }
+}