summaryrefslogtreecommitdiff
path: root/src/bin/day_7.rs
diff options
context:
space:
mode:
authorJustin Wernick <justin@worthe-it.co.za>2019-12-12 00:37:55 +0200
committerJustin Wernick <justin@worthe-it.co.za>2019-12-12 00:37:55 +0200
commit22fc69709731ba039f321c48670584c50f48d9ab (patch)
tree4cc6aadb925285f1081d1d953f58c2304b186293 /src/bin/day_7.rs
parent003a62f1c38344c5a647170bd2472c4eab39cf75 (diff)
Day 7 part 1 (it's dirty and doesn't solve part 2 yet)
Diffstat (limited to 'src/bin/day_7.rs')
-rw-r--r--src/bin/day_7.rs91
1 files changed, 91 insertions, 0 deletions
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)))
+ }
+}