From 9892e3ebde304726903a1e5c358d05c2e343ea5e Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 19 Apr 2022 20:26:36 +0200 Subject: Refile for merging repos --- 2019/src/bin/day_2.rs | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 2019/src/bin/day_2.rs (limited to '2019/src/bin/day_2.rs') diff --git a/2019/src/bin/day_2.rs b/2019/src/bin/day_2.rs new file mode 100644 index 0000000..ba9e189 --- /dev/null +++ b/2019/src/bin/day_2.rs @@ -0,0 +1,96 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 2: 1202 Program Alarm")] +/// Executes an Intcode program +/// +/// The program is read from stdin as a series of comma-separated +/// values. Newlines are ignored. When the program halts, the value at +/// position 0 is returned. +/// +/// If an output is provided, all possible inputs are tried to find +/// the input that results in the desired output. In this case, the +/// inputs are returned in the format (noun, verb). +/// +///See https://adventofcode.com/2019/day/2 for details. +struct Opt { + #[structopt(short = "n", long = "noun")] + noun: Option, + #[structopt(short = "v", long = "verb")] + verb: Option, + #[structopt(short = "o", long = "output")] + output: Option, +} + +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::(), "Invalid number")) + .collect(); + + match (opt.noun, opt.verb, opt.output) { + (Some(noun), Some(verb), _) => { + let result = exit_on_failed_assertion( + program + .with_noun_verb_input(noun, verb) + .execute_returning_memory_0(), + "Program errored", + ); + println!("{}", result); + } + (_, _, Some(output)) => { + let (noun, verb) = + exit_on_failed_assertion(find_input(&program, output), "Program errored"); + println!("({}, {})", noun, verb); + } + (None, None, None) => { + let result = + exit_on_failed_assertion(program.execute_returning_memory_0(), "Program errored"); + println!("{}", result); + } + _ => { + eprintln!("Either a noun and verb or an expected output must be provided"); + process::exit(1); + } + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn find_input( + program: &IntcodeProgram, + output: Intcode, +) -> Result<(Intcode, Intcode), IntcodeProgramError> { + (0..99) + .flat_map(|noun| (0..99).map(move |verb| (Intcode::from(noun), Intcode::from(verb)))) + .map(|(noun, verb)| { + ( + noun.clone(), + verb.clone(), + program + .with_noun_verb_input(noun, verb) + .execute_returning_memory_0(), + ) + }) + .find(|(_noun, _verb, out)| *out == Ok(output.clone())) + .map(|(noun, verb, _out)| Ok((noun, verb))) + .unwrap_or(Err(IntcodeProgramError::Unknown)) +} -- cgit v1.2.3