summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--Cargo.toml3
-rw-r--r--inputs/day_7.txt1
-rw-r--r--src/bin/day_7.rs91
4 files changed, 95 insertions, 1 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a8be1c4..30421cf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,6 +12,7 @@ dependencies = [
name = "aoc2019"
version = "0.1.0"
dependencies = [
+ "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)",
"im 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/Cargo.toml b/Cargo.toml
index cef1cae..eb300fe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,4 +8,5 @@ edition = "2018"
structopt = "0.3.5"
derive_more = "0.99.2"
im = "14.0.0"
-rpds = "0.7.0" \ No newline at end of file
+rpds = "0.7.0"
+archery = "0.3.0" \ No newline at end of file
diff --git a/inputs/day_7.txt b/inputs/day_7.txt
new file mode 100644
index 0000000..b21d6af
--- /dev/null
+++ b/inputs/day_7.txt
@@ -0,0 +1 @@
+3,8,1001,8,10,8,105,1,0,0,21,46,59,84,93,110,191,272,353,434,99999,3,9,101,2,9,9,102,3,9,9,1001,9,5,9,102,4,9,9,1001,9,4,9,4,9,99,3,9,101,3,9,9,102,5,9,9,4,9,99,3,9,1001,9,4,9,1002,9,2,9,101,2,9,9,102,2,9,9,1001,9,3,9,4,9,99,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,1001,9,5,9,1002,9,3,9,4,9,99,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,99
diff --git a/src/bin/day_7.rs b/src/bin/day_7.rs
new file mode 100644
index 0000000..d412734
--- /dev/null
+++ b/src/bin/day_7.rs
@@ -0,0 +1,91 @@
+use aoc2019::*;
+use rpds::list;
+use rpds::list::List;
+use std::io;
+use std::io::prelude::*;
+use std::process;
+use structopt::StructOpt;
+
+#[derive(Debug, StructOpt)]
+#[structopt(name = "Day 7: Amplification Circuit")]
+/// Executes an Intcode program on 5 amplifiers, and finds the input that gives the max output
+///
+/// See https://adventofcode.com/2019/day/7 for details.
+struct Opt {
+ #[structopt(short = "f", long = "feedback-loop")]
+ feedback_loop_mode: bool,
+}
+
+fn main() {
+ let stdin = io::stdin();
+ let opt = Opt::from_args();
+
+ let program: IntcodeProgram = stdin
+ .lock()
+ .split(b',')
+ .map(|x| exit_on_failed_assertion(x, "Error reading input"))
+ .map(|x| exit_on_failed_assertion(String::from_utf8(x), "Input was not valid UTF-8"))
+ .map(|x| exit_on_failed_assertion(x.trim().parse::<Intcode>(), "Invalid number"))
+ .collect::<IntcodeProgram>();
+
+ let result = exit_on_failed_assertion(find_max_power(&program), "Program errored");
+ println!("{}", result);
+}
+
+fn exit_on_failed_assertion<A, E: std::error::Error>(data: Result<A, E>, message: &str) -> A {
+ match data {
+ Ok(data) => data,
+ Err(e) => {
+ eprintln!("{}: {}", message, e);
+ process::exit(1);
+ }
+ }
+}
+
+fn find_max_power(program: &IntcodeProgram) -> Result<Intcode, IntcodeProgramError> {
+ PhaseSetting::all()
+ .map(|phase| run_amplifiers(program, phase))
+ .collect::<Result<Vec<Intcode>, _>>()
+ .map(|powers| powers.into_iter().max().unwrap_or(0))
+}
+
+fn run_amplifiers(
+ program: &IntcodeProgram,
+ phase: PhaseSetting,
+) -> Result<Intcode, IntcodeProgramError> {
+ run_amp(program, phase, 0, 0)
+ .and_then(|pipe| run_amp(program, phase, 1, pipe))
+ .and_then(|pipe| run_amp(program, phase, 2, pipe))
+ .and_then(|pipe| run_amp(program, phase, 3, pipe))
+ .and_then(|pipe| run_amp(program, phase, 4, pipe))
+}
+
+fn run_amp(
+ program: &IntcodeProgram,
+ phase: PhaseSetting,
+ n: usize,
+ input: Intcode,
+) -> Result<Intcode, IntcodeProgramError> {
+ program
+ .with_input(list![phase.0[n], input])
+ .execute()
+ .and_then(|output_vec| output_vec.get(0).cloned().ok_or(IntcodeProgramError))
+}
+
+#[derive(Debug, Clone, Copy)]
+struct PhaseSetting([Intcode; 5]);
+
+impl PhaseSetting {
+ fn all() -> impl Iterator<Item = PhaseSetting> {
+ (0..=4)
+ .flat_map(move |a| {
+ (0..=4).flat_map(move |b| {
+ (0..=4).flat_map(move |c| {
+ (0..=4)
+ .flat_map(move |d| (0..=4).map(move |e| PhaseSetting([a, b, c, d, e])))
+ })
+ })
+ })
+ .filter(|phase| (0..=4).all(|x| phase.0.contains(&x)))
+ }
+}