From c98244df602a3f3d745f5971e22b1031c3e55770 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sat, 30 Nov 2019 17:23:02 +0200 Subject: Initial commit --- .gitignore | 2 ++ Cargo.toml | 9 +++++++++ src/main.rs | 3 +++ 3 files changed, 14 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..53eaa21 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +**/*.rs.bk diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..870468a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "advent-of-code-2019" +version = "0.1.0" +authors = ["Justin Worthe "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} -- cgit v1.2.3 From 34bffc49705fb31f947ad0f2f45494dc9472e81b Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sun, 1 Dec 2019 09:24:11 +0200 Subject: Day 1 --- Cargo.lock | 6 ++++ inputs/day_1.txt | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.org | 12 +++++++ src/bin/day_1.rs | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 11 +++++- 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 Cargo.lock create mode 100644 inputs/day_1.txt create mode 100644 readme.org create mode 100644 src/bin/day_1.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..3719353 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "advent-of-code-2019" +version = "0.1.0" + diff --git a/inputs/day_1.txt b/inputs/day_1.txt new file mode 100644 index 0000000..5c720ed --- /dev/null +++ b/inputs/day_1.txt @@ -0,0 +1,100 @@ +66690 +86239 +75191 +140364 +95979 +106923 +95229 +123571 +84764 +89444 +98107 +89062 +109369 +146067 +124760 +76900 +139198 +111441 +74046 +84920 +54397 +143807 +121654 +93863 +73909 +104121 +58485 +119084 +126227 +142078 +79820 +132617 +108430 +98032 +107434 +127307 +105619 +57741 +53468 +63301 +137970 +136780 +80897 +133205 +79159 +89124 +94477 +56714 +143704 +122097 +117335 +108246 +75507 +101459 +101162 +146197 +121884 +66217 +57074 +142903 +140951 +64883 +124556 +67382 +142407 +121778 +57933 +94599 +87426 +143758 +64043 +65678 +90137 +61090 +77315 +102383 +146607 +139290 +85394 +149787 +125611 +106405 +91561 +135739 +54845 +68782 +111175 +61011 +125658 +70751 +85607 +75458 +75419 +124311 +66022 +122784 +129018 +54901 +73788 +108240 diff --git a/readme.org b/readme.org new file mode 100644 index 0000000..c1923ac --- /dev/null +++ b/readme.org @@ -0,0 +1,12 @@ +* Advent of Code 2019 + +** Personal challenge + +Try to keep the solution pure. Only main can do IO things, like return +different results when it's called differently. The rest of the +program should only be pure expressions. + +** Optimizations + +- Limit the use of statements. Try to use expressions instead, or move + the statement out to a function. diff --git a/src/bin/day_1.rs b/src/bin/day_1.rs new file mode 100644 index 0000000..7c8f104 --- /dev/null +++ b/src/bin/day_1.rs @@ -0,0 +1,97 @@ +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::Sum; +use std::num::ParseIntError; +use std::ops::Add; +use std::str::FromStr; + +fn main() { + let stdin = io::stdin(); + + let input = stdin + .lock() + .lines() + .map(|l| l.unwrap().parse::().unwrap()); + + dbg!(fuel_required(input)); +} + +// TODO: If this were a nice CLI program, it would probably have a switch to choose between these two rather than doing both? +fn fuel_required(it: impl Iterator) -> (Fuel, Fuel) { + it.map(|m| { + ( + m.fuel_excluding_fuel_weight(), + m.fuel_including_fuel_weight(), + ) + }) + .fold((Fuel(0), Fuel(0)), |(sum_x, sum_y), (x, y)| { + (sum_x + x, sum_y + y) + }) +} + +struct Module { + weight: Weight, +} + +impl FromStr for Module { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result { + Ok(Module { + weight: Weight(s.parse()?), + }) + } +} + +impl Module { + fn fuel_excluding_fuel_weight(&self) -> Fuel { + self.weight.required_fuel() + } + + fn fuel_including_fuel_weight(&self) -> Fuel { + iter::successors(Some(self.weight.required_fuel()), |fuel| { + if fuel.weight().is_zero() { + None + } else { + Some(fuel.weight().required_fuel()) + } + }) + .sum() + } +} + +struct Weight(u32); + +impl Weight { + fn is_zero(&self) -> bool { + self.0 == 0 + } + + fn required_fuel(&self) -> Fuel { + Fuel((self.0 / 3).saturating_sub(2)) + } +} + +#[derive(Debug)] +struct Fuel(u32); + +impl Fuel { + fn weight(&self) -> Weight { + Weight(self.0) + } +} + +impl Add for Fuel { + type Output = Self; + + fn add(self, other: Self) -> Self { + Fuel(self.0 + other.0) + } +} + +impl Sum for Fuel { + fn sum>(iter: I) -> Self { + iter.fold(Fuel(0), Add::add) + } +} diff --git a/src/main.rs b/src/main.rs index e7a11a9..0c24a73 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,12 @@ +use std::io; +use std::io::prelude::*; + fn main() { - println!("Hello, world!"); + let stdin = io::stdin(); + let answer = string_length_sum(stdin.lock().lines().map(|l| l.unwrap())); + dbg!(answer); +} + +fn string_length_sum(it: impl Iterator) -> usize { + it.map(|l| l.len()).sum() } -- cgit v1.2.3 From ecfa5bb0f3caf66f05a7b99d204978496dae4bd7 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sun, 1 Dec 2019 11:27:04 +0200 Subject: Dressed day 1 up as a cli app --- Cargo.lock | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + readme.org | 7 ++ src/bin/day_1.rs | 80 ++++++++++------------- 4 files changed, 237 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3719353..149a347 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,4 +3,199 @@ [[package]] name = "advent-of-code-2019" version = "0.1.0" +dependencies = [ + "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "derive_more" +version = "0.99.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro-error" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" +"checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 870468a..69a0b81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +structopt = "0.3.5" +derive_more = "0.99.2" \ No newline at end of file diff --git a/readme.org b/readme.org index c1923ac..97f5511 100644 --- a/readme.org +++ b/readme.org @@ -10,3 +10,10 @@ program should only be pure expressions. - Limit the use of statements. Try to use expressions instead, or move the statement out to a function. + +** Findings + +- Having iterators that you can't clone (like stdin) makes certain + things difficult. Eg, doing part 1 and 2 together. +- Using "new type" structs can be a pain. derive_more crate made most + of that pain go away. diff --git a/src/bin/day_1.rs b/src/bin/day_1.rs index 7c8f104..b9a6c18 100644 --- a/src/bin/day_1.rs +++ b/src/bin/day_1.rs @@ -1,57 +1,56 @@ +use derive_more; use std::io; use std::io::prelude::*; use std::iter; -use std::iter::Sum; -use std::num::ParseIntError; -use std::ops::Add; -use std::str::FromStr; + +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 1: The Tyranny of the Rocket Equation")] +/// Calculates the fuel needed for your rocket to save Santa. +/// +/// The weight of each module is read from stdin, one module weight +/// per line. See https://adventofcode.com/2019/day/1 for details. +struct Opt { + /// Includes the weight of flue + #[structopt(short = "i", long = "include-fuel-weight")] + include_fuel_weight: bool, +} fn main() { let stdin = io::stdin(); + let opt = Opt::from_args(); let input = stdin .lock() .lines() .map(|l| l.unwrap().parse::().unwrap()); - dbg!(fuel_required(input)); + println!("{}", fuel_required(input, opt.include_fuel_weight)) } -// TODO: If this were a nice CLI program, it would probably have a switch to choose between these two rather than doing both? -fn fuel_required(it: impl Iterator) -> (Fuel, Fuel) { - it.map(|m| { - ( - m.fuel_excluding_fuel_weight(), - m.fuel_including_fuel_weight(), - ) - }) - .fold((Fuel(0), Fuel(0)), |(sum_x, sum_y), (x, y)| { - (sum_x + x, sum_y + y) +fn fuel_required(it: impl Iterator, include_fuel_weight: bool) -> Fuel { + it.map(if include_fuel_weight { + Module::fuel_including_fuel_weight + } else { + Module::fuel_excluding_fuel_weight }) + .sum() } +#[derive(Debug, derive_more::FromStr, Clone, Copy)] struct Module { weight: Weight, } -impl FromStr for Module { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - Ok(Module { - weight: Weight(s.parse()?), - }) - } -} - impl Module { - fn fuel_excluding_fuel_weight(&self) -> Fuel { + fn fuel_excluding_fuel_weight(self) -> Fuel { self.weight.required_fuel() } - fn fuel_including_fuel_weight(&self) -> Fuel { + fn fuel_including_fuel_weight(self) -> Fuel { iter::successors(Some(self.weight.required_fuel()), |fuel| { - if fuel.weight().is_zero() { + if fuel.is_zero() { None } else { Some(fuel.weight().required_fuel()) @@ -61,37 +60,24 @@ impl Module { } } +#[derive(Debug, derive_more::FromStr, Clone, Copy)] struct Weight(u32); impl Weight { - fn is_zero(&self) -> bool { - self.0 == 0 - } - - fn required_fuel(&self) -> Fuel { + fn required_fuel(self) -> Fuel { Fuel((self.0 / 3).saturating_sub(2)) } } -#[derive(Debug)] +#[derive(Debug, derive_more::Add, derive_more::Sum, Clone, Copy, derive_more::Display)] struct Fuel(u32); impl Fuel { - fn weight(&self) -> Weight { + fn weight(self) -> Weight { Weight(self.0) } -} - -impl Add for Fuel { - type Output = Self; - - fn add(self, other: Self) -> Self { - Fuel(self.0 + other.0) - } -} -impl Sum for Fuel { - fn sum>(iter: I) -> Self { - iter.fold(Fuel(0), Add::add) + fn is_zero(self) -> bool { + self.0 == 0 } } -- cgit v1.2.3 From 92106a053f87d44d5dba28a628aaeecba8417b5a Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sun, 1 Dec 2019 13:11:13 +0200 Subject: Better error handling --- src/bin/day_1.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/bin/day_1.rs b/src/bin/day_1.rs index b9a6c18..f40237d 100644 --- a/src/bin/day_1.rs +++ b/src/bin/day_1.rs @@ -2,6 +2,7 @@ use derive_more; use std::io; use std::io::prelude::*; use std::iter; +use std::process; use structopt::StructOpt; @@ -21,10 +22,19 @@ fn main() { let stdin = io::stdin(); let opt = Opt::from_args(); - let input = stdin - .lock() - .lines() - .map(|l| l.unwrap().parse::().unwrap()); + let input = stdin.lock().lines().map(|l| match l { + Ok(s) => match s.parse::() { + Ok(module) => module, + Err(e) => { + eprintln!("Invalid input \"{}\": {}", s, e); + process::exit(1); + } + }, + Err(e) => { + eprintln!("Error reading input: {}", e); + process::exit(1); + } + }); println!("{}", fuel_required(input, opt.include_fuel_weight)) } -- cgit v1.2.3 From af487fe8cb2d7732283971a416d015234e8f71cc Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 2 Dec 2019 22:08:56 +0200 Subject: Day 2: Intcode machine! --- Cargo.lock | 61 +++++++++++++++++ Cargo.toml | 7 +- inputs/day_2.txt | 1 + src/bin/day_1.rs | 2 +- src/bin/day_2.rs | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 inputs/day_2.txt create mode 100644 src/bin/day_2.rs diff --git a/Cargo.lock b/Cargo.lock index 149a347..9a70fd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,6 +5,7 @@ name = "advent-of-code-2019" version = "0.1.0" dependencies = [ "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)", "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -30,6 +31,14 @@ name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitmaps" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "clap" version = "2.33.0" @@ -62,6 +71,19 @@ dependencies = [ "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "im" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libc" version = "0.2.66" @@ -93,6 +115,28 @@ dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_xoshiro" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sized-chunks" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "strsim" version = "0.8.0" @@ -137,6 +181,11 @@ dependencies = [ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-segmentation" version = "1.6.0" @@ -157,6 +206,11 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.8" @@ -180,22 +234,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum im 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1f9b6540e530defef7f2df4ed330d45b739b10450548c74a9913f63ea1acc6b" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" +"checksum sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62db64dd92b3b54314b1e216c274634ca2b3fe8da8b3873be670cb1ac4dad30f" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" "checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 69a0b81..18b5ff5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "advent-of-code-2019" version = "0.1.0" -authors = ["Justin Worthe "] +authors = ["Justin Wernick "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] structopt = "0.3.5" -derive_more = "0.99.2" \ No newline at end of file +derive_more = "0.99.2" +im = "14.0.0" \ No newline at end of file diff --git a/inputs/day_2.txt b/inputs/day_2.txt new file mode 100644 index 0000000..dd34cff --- /dev/null +++ b/inputs/day_2.txt @@ -0,0 +1 @@ +1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,9,1,19,1,19,5,23,1,23,6,27,2,9,27,31,1,5,31,35,1,35,10,39,1,39,10,43,2,43,9,47,1,6,47,51,2,51,6,55,1,5,55,59,2,59,10,63,1,9,63,67,1,9,67,71,2,71,6,75,1,5,75,79,1,5,79,83,1,9,83,87,2,87,10,91,2,10,91,95,1,95,9,99,2,99,9,103,2,10,103,107,2,9,107,111,1,111,5,115,1,115,2,119,1,119,6,0,99,2,0,14,0 diff --git a/src/bin/day_1.rs b/src/bin/day_1.rs index f40237d..572d287 100644 --- a/src/bin/day_1.rs +++ b/src/bin/day_1.rs @@ -13,7 +13,7 @@ use structopt::StructOpt; /// The weight of each module is read from stdin, one module weight /// per line. See https://adventofcode.com/2019/day/1 for details. struct Opt { - /// Includes the weight of flue + /// Includes the weight of fuel #[structopt(short = "i", long = "include-fuel-weight")] include_fuel_weight: bool, } diff --git a/src/bin/day_2.rs b/src/bin/day_2.rs new file mode 100644 index 0000000..184c06c --- /dev/null +++ b/src/bin/day_2.rs @@ -0,0 +1,204 @@ +use im::vector::Vector; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::iter::IntoIterator; +use std::process; +use structopt::StructOpt; + +type Intcode = u32; + +#[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: Program = 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.set_input(noun, verb).execute(), + "Program errored", + ); + println!("{}", result); + } + (_, _, Some(output)) => { + let (noun, verb) = + exit_on_failed_assertion(program.find_input(output), "Program errored"); + println!("({}, {})", noun, verb); + } + (None, None, None) => { + let result = exit_on_failed_assertion(program.execute(), "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); + } + } +} + +#[derive(Debug, Clone)] +struct Program { + program_counter: usize, + error: bool, + halted: bool, + codes: Vector, +} + +impl FromIterator for Program { + fn from_iter>(iter: I) -> Self { + Program { + program_counter: 0, + error: false, + halted: false, + codes: iter.into_iter().collect(), + } + } +} + +impl Program { + fn set_input(&self, noun: Intcode, verb: Intcode) -> Program { + Program { + codes: self.codes.update(1, noun).update(2, verb), + ..self.clone() + } + } + + fn find_input(&self, output: Intcode) -> Result<(Intcode, Intcode), ProgramError> { + (0..99) + .flat_map(|noun| (0..99).map(move |verb| (noun, verb))) + .map(|(noun, verb)| (noun, verb, self.set_input(noun, verb).execute())) + .find(|(_noun, _verb, out)| *out == Ok(output)) + .map(|(noun, verb, _out)| Ok((noun, verb))) + .unwrap_or(Err(ProgramError)) + } + + fn execute(&self) -> Result { + if self.run_to_termination().error { + Err(ProgramError) + } else { + Ok(self.run_to_termination().codes.head().unwrap().clone()) + } + } + + fn run_to_termination(&self) -> Program { + iter::successors(Some(self.clone()), |p| Some(Program::next(&p))) + .find(|p| p.halted) + .unwrap() // successors doesn't terminate, so this will never be none. + } + + fn next(&self) -> Program { + //eprintln!("{:?}", self); + match self.codes.get(self.program_counter) { + Some(1) => self.add(), + Some(2) => self.multiply(), + Some(99) => self.halt(), + Some(_) => self.error(), + None => self.error(), + } + } + + fn add(&self) -> Program { + match ( + self.codes + .get(self.program_counter + 1) + .and_then(|r| self.codes.get(*r as usize)), + self.codes + .get(self.program_counter + 2) + .and_then(|r| self.codes.get(*r as usize)), + self.codes.get(self.program_counter + 3), + ) { + (Some(in1), Some(in2), Some(out)) => Program { + program_counter: self.program_counter + 4, + codes: self.codes.update(*out as usize, in1 + in2), + ..self.clone() + }, + _ => self.error(), + } + } + + fn multiply(&self) -> Program { + match ( + self.codes + .get(self.program_counter + 1) + .and_then(|r| self.codes.get(*r as usize)), + self.codes + .get(self.program_counter + 2) + .and_then(|r| self.codes.get(*r as usize)), + self.codes.get(self.program_counter + 3), + ) { + (Some(in1), Some(in2), Some(out)) => Program { + program_counter: self.program_counter + 4, + codes: self.codes.update(*out as usize, in1 * in2), + ..self.clone() + }, + _ => self.error(), + } + } + + fn halt(&self) -> Program { + Program { + halted: true, + ..self.clone() + } + } + + fn error(&self) -> Program { + Program { + halted: true, + error: true, + ..self.clone() + } + } +} + +#[derive(Debug, PartialEq)] +struct ProgramError; + +impl fmt::Display for ProgramError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Unknown error") + } +} +impl std::error::Error for ProgramError {} -- cgit v1.2.3 From 203431863570652f859ba4fe76dda5a5ea8ccac3 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 2 Dec 2019 22:09:52 +0200 Subject: Extra finding --- readme.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.org b/readme.org index 97f5511..936550a 100644 --- a/readme.org +++ b/readme.org @@ -17,3 +17,5 @@ program should only be pure expressions. things difficult. Eg, doing part 1 and 2 together. - Using "new type" structs can be a pain. derive_more crate made most of that pain go away. +- With immutable types, 'reset the machine to try again' type + constraints were handled for free. -- cgit v1.2.3 From 3988b89729bda5d43f36c2de65ad88000c6c6b02 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 2 Dec 2019 22:22:23 +0200 Subject: Abstract the repeated code --- src/bin/day_2.rs | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/bin/day_2.rs b/src/bin/day_2.rs index 184c06c..f1a1ac7 100644 --- a/src/bin/day_2.rs +++ b/src/bin/day_2.rs @@ -140,15 +140,7 @@ impl Program { } fn add(&self) -> Program { - match ( - self.codes - .get(self.program_counter + 1) - .and_then(|r| self.codes.get(*r as usize)), - self.codes - .get(self.program_counter + 2) - .and_then(|r| self.codes.get(*r as usize)), - self.codes.get(self.program_counter + 3), - ) { + match (self.get_deref(1), self.get_dered(2), self.get(3)) { (Some(in1), Some(in2), Some(out)) => Program { program_counter: self.program_counter + 4, codes: self.codes.update(*out as usize, in1 + in2), @@ -159,15 +151,7 @@ impl Program { } fn multiply(&self) -> Program { - match ( - self.codes - .get(self.program_counter + 1) - .and_then(|r| self.codes.get(*r as usize)), - self.codes - .get(self.program_counter + 2) - .and_then(|r| self.codes.get(*r as usize)), - self.codes.get(self.program_counter + 3), - ) { + match (self.get_deref(1), self.get_dered(2), self.get(3)) { (Some(in1), Some(in2), Some(out)) => Program { program_counter: self.program_counter + 4, codes: self.codes.update(*out as usize, in1 * in2), @@ -191,6 +175,15 @@ impl Program { ..self.clone() } } + + fn get(&self, pointer_offset: usize) -> Option { + self.codes.get(self.program_counter + pointer_offset) + } + + fn get_deref(&self, pointer_offset: usize) -> Option { + self.get(pointer_offset) + .and_then(|r| self.codes.get(*r as usize)) + } } #[derive(Debug, PartialEq)] -- cgit v1.2.3 From efbf5a4ef9296ef0ae20876a002f7fd0570ad6e8 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 2 Dec 2019 22:52:37 +0200 Subject: Removed redundant call to run program --- src/bin/day_2.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/bin/day_2.rs b/src/bin/day_2.rs index f1a1ac7..172a89a 100644 --- a/src/bin/day_2.rs +++ b/src/bin/day_2.rs @@ -115,10 +115,14 @@ impl Program { } fn execute(&self) -> Result { - if self.run_to_termination().error { + self.run_to_termination().into_result() + } + + fn into_result(&self) -> Result { + if self.error { Err(ProgramError) } else { - Ok(self.run_to_termination().codes.head().unwrap().clone()) + Ok(self.codes.head().unwrap().clone()) } } @@ -140,10 +144,10 @@ impl Program { } fn add(&self) -> Program { - match (self.get_deref(1), self.get_dered(2), self.get(3)) { + match (self.get_deref(1), self.get_deref(2), self.get(3)) { (Some(in1), Some(in2), Some(out)) => Program { program_counter: self.program_counter + 4, - codes: self.codes.update(*out as usize, in1 + in2), + codes: self.codes.update(out as usize, in1 + in2), ..self.clone() }, _ => self.error(), @@ -151,10 +155,10 @@ impl Program { } fn multiply(&self) -> Program { - match (self.get_deref(1), self.get_dered(2), self.get(3)) { + match (self.get_deref(1), self.get_deref(2), self.get(3)) { (Some(in1), Some(in2), Some(out)) => Program { program_counter: self.program_counter + 4, - codes: self.codes.update(*out as usize, in1 * in2), + codes: self.codes.update(out as usize, in1 * in2), ..self.clone() }, _ => self.error(), @@ -177,12 +181,15 @@ impl Program { } fn get(&self, pointer_offset: usize) -> Option { - self.codes.get(self.program_counter + pointer_offset) + self.codes + .get(self.program_counter + pointer_offset) + .cloned() } fn get_deref(&self, pointer_offset: usize) -> Option { self.get(pointer_offset) - .and_then(|r| self.codes.get(*r as usize)) + .and_then(|r| self.codes.get(r as usize)) + .cloned() } } -- cgit v1.2.3 From 3d1a9640016ee8c065ab49d0060d6cd0c3325aad Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 5 Dec 2019 00:03:02 +0200 Subject: Day 3: It's clunky in parts but it solves the problem --- Cargo.lock | 25 +++++ Cargo.toml | 3 +- inputs/day_3.txt | 2 + src/bin/day_3.rs | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 inputs/day_3.txt create mode 100644 src/bin/day_3.rs diff --git a/Cargo.lock b/Cargo.lock index 9a70fd1..127971b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,7 @@ version = "0.1.0" dependencies = [ "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)", "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -17,6 +18,14 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "archery" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "atty" version = "0.2.13" @@ -128,6 +137,14 @@ dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rpds" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sized-chunks" version = "0.5.0" @@ -137,6 +154,11 @@ dependencies = [ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "static_assertions" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.8.0" @@ -232,6 +254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d308d8fa3f687f7a7588fccc4812ed6914be09518232f00454693a7417273ad2" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" @@ -245,7 +268,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" +"checksum rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1196a0a2f52d343bd32179834273eaac7d8739f7e3f8b700227d2fa06b9a423b" "checksum sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62db64dd92b3b54314b1e216c274634ca2b3fe8da8b3873be670cb1ac4dad30f" +"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" "checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" diff --git a/Cargo.toml b/Cargo.toml index 18b5ff5..937d8e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" [dependencies] structopt = "0.3.5" derive_more = "0.99.2" -im = "14.0.0" \ No newline at end of file +im = "14.0.0" +rpds = "0.7.0" \ No newline at end of file diff --git a/inputs/day_3.txt b/inputs/day_3.txt new file mode 100644 index 0000000..504e9fe --- /dev/null +++ b/inputs/day_3.txt @@ -0,0 +1,2 @@ +R995,D882,R144,U180,L638,U282,L907,D326,R731,D117,R323,U529,R330,U252,R73,U173,R345,U552,R230,U682,R861,U640,L930,U590,L851,D249,R669,D878,R951,D545,L690,U392,R609,D841,R273,D465,R546,U858,L518,U567,L474,D249,L463,D390,L443,U392,L196,U418,R433,U651,R520,D450,R763,U714,R495,D716,L219,D289,L451,D594,R874,U451,R406,U662,R261,D242,R821,D951,R808,D862,L871,U133,R841,D465,R710,U300,R879,D497,R85,U173,R941,U953,R705,U972,R260,D315,L632,U182,L26,D586,R438,U275,L588,U956,L550,D576,R738,U974,R648,D880,R595,D510,L789,U455,R627,U709,R7,D486,L184,U999,L404,U329,L852,D154,L232,U398,L587,U881,R938,D40,L657,D164,R45,D917,R106,U698,L824,D426,R879,U700,R847,D891,L948,U625,R663,D814,R217,U30,R610,D781,L415,D435,L904,U815,R152,U587,R287,U141,R866,D636,L290,D114,L751,D660,R6,U383,L263,U799,R330,U96,L6,U542,L449,D361,R486,U278,L990,U329,L519,U605,R501,D559,R916,U198,L499,D174,R513,U396,L473,D565,R337,D770,R211,D10,L591,D920,R367,D748,L330,U249,L307,D645,R661,U266,R234,D403,L513,U443,L989,D1,L674,D210,L537,D872,L607,D961,R894,U632,L195,U744,L426,U531,R337,D821,R113,U436,L700,U779,R555,U891,R268,D30,R958,U411,R904,U24,R760,D958,R231,U229,L561,D134,L382,D961,L237,U676,L223,U324,R663,D186,R833,U188,R419,D349,L721,U152,L912,U490,R10,D995,L98,U47,R140,D815,R826,U730,R808,U256,R479,D322,L504,D891,L413,D848,L732,U375,L307,U7,R682,U270,L495,D248,R691,D945,L70,U220,R635,D159,R269,D15,L161,U214,R814,D3,R354,D632,R469,D36,R85,U215,L243,D183,R140,U179,R812,U180,L905,U136,L34,D937,L875 +L999,D22,L292,U843,R390,U678,R688,D492,L489,U488,R305,U951,L636,U725,R402,U84,L676,U171,L874,D201,R64,D743,R372,U519,R221,U986,L393,D793,R72,D184,L553,D137,L187,U487,L757,U880,L535,U887,R481,U236,L382,D195,L388,D90,R125,U414,R512,D382,R972,U935,L172,D1,R957,U593,L151,D158,R396,D42,L30,D178,R947,U977,R67,D406,R744,D64,L677,U23,R792,U864,R259,U315,R314,U17,L37,D658,L642,U135,R624,U601,L417,D949,R203,D122,R76,D493,L569,U274,L330,U933,R815,D30,L630,D43,R86,U926,L661,D491,L541,D96,R868,D565,R664,D935,L336,D152,R63,U110,L782,U14,R172,D945,L732,D870,R404,U767,L907,D558,R748,U591,R461,D153,L635,D457,R241,U478,L237,U218,R393,U468,L182,D745,L388,D360,L222,D642,L151,U560,R437,D326,R852,U525,R717,U929,L470,U621,R421,U408,L540,D176,L69,U753,L200,U251,R742,U628,R534,U542,R85,D71,R283,U905,L418,D755,L593,U335,L114,D684,L576,D645,R652,D49,R86,D991,L838,D309,L73,U847,L418,U675,R991,U463,R314,D618,L433,U173,R869,D115,L18,U233,R541,U516,L570,U340,R264,D442,L259,U276,R433,D348,R524,D353,R336,D883,R580,U157,R79,D27,L134,D161,L748,D278,R322,D581,R654,D156,L930,D293,L156,U311,R807,D618,R408,U719,R366,D632,R307,D565,R478,D620,R988,D821,R365,D581,L946,D138,L943,U69,R620,U208,L407,U188,L122,U353,L751,U565,R849,D874,R668,D794,L140,D474,R289,D773,R344,D220,L55,D385,L394,U208,R305,U736,L896,D376,R331,D855,L466,U516,L741,U124,L825,U467,L525,D911,R76,U220,L610,U102,L261,D891,L585,U397,L152,U753,R822,D252,R106,U145,L7,U524,R343,U352,L357,D399,L446,D140,L723,U46,R687,D409,R884 diff --git a/src/bin/day_3.rs b/src/bin/day_3.rs new file mode 100644 index 0000000..f4163bd --- /dev/null +++ b/src/bin/day_3.rs @@ -0,0 +1,333 @@ +use rpds::vector::Vector; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 3: Crossed Wires")] +/// Finds the closest intersection between two wires. By default, +/// 'closest' is defined as closest in terms of Manhattan distance. If +/// --signal-distance is set, distance is defined in terms of the +/// total distance along the wire. +/// +/// See https://adventofcode.com/2019/day/3 for details. +struct Opt { + #[structopt(short = "s", long = "signal-distance")] + /// returns the closest intersection by signal distance. + signal_distance: bool, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let mut input = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid wire")); + + let (wire1, wire2) = match (input.next(), input.next()) { + (Some(w1), Some(w2)) => (w1, w2), + _ => { + eprintln!("Input must have two wires"); + process::exit(1); + } + }; + + match wire1.closest_collision(&wire2, opt.signal_distance) { + Some(c) => println!( + "{}", + if opt.signal_distance { + c.signal_distance + } else { + c.manhattan_distance() + } + ), + None => { + eprintln!("No collisions"); + 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); + } + } +} + +#[derive(Debug, Clone)] +struct Wire { + segments: Vector, +} + +impl FromStr for Wire { + type Err = UnknownError; + + fn from_str(s: &str) -> Result { + s.split(',') + .fold( + Ok(Vector::new()), + |acc: Result, UnknownError>, next_str| { + acc.and_then(|previous_segments| { + WireSegment::from_str( + previous_segments.last().map(|l| l.end()).unwrap_or((0, 0)), + previous_segments + .last() + .map(|l| l.end_signal_distance()) + .unwrap_or(0), + next_str, + ) + .map(|seg| previous_segments.push_back(seg)) + }) + }, + ) + .map(|segments| Wire { segments }) + } +} + +impl Wire { + fn closest_collision(&self, other: &Wire, use_signal_distance: bool) -> Option { + self.collisions(other).min_by_key(|c| { + if use_signal_distance { + c.signal_distance + } else { + c.manhattan_distance() + } + }) + } + + fn collisions<'a>(&'a self, other: &'a Wire) -> impl Iterator + 'a { + self.segments + .iter() + .flat_map(move |seg1| other.segments.iter().map(move |seg2| (seg1, seg2))) + .flat_map(|(seg1, seg2)| seg1.collisions(seg2)) + .filter(|c| !(c.x == 0 && c.y == 0)) + } +} + +#[derive(Debug, Clone)] +struct WireSegment { + start: (i32, i32), + start_signal_distance: i32, + direction: Direction, + length: i32, +} + +impl WireSegment { + fn from_str( + start: (i32, i32), + start_signal_distance: i32, + s: &str, + ) -> Result { + s.parse::().and_then(|direction| { + WireSegment::length_from_str(s).map(|length| WireSegment { + start, + start_signal_distance, + direction, + length, + }) + }) + } + + fn length_from_str(s: &str) -> Result { + s.chars() + .skip(1) + .collect::() + .parse() + .map_err(|_| UnknownError) + } + + fn end(&self) -> (i32, i32) { + ( + self.start.0 + self.direction.as_vec().0 * self.length, + self.start.1 + self.direction.as_vec().1 * self.length, + ) + } + + fn end_signal_distance(&self) -> i32 { + self.start_signal_distance + self.length + } + + fn collisions(&self, other: &WireSegment) -> Option { + use Direction::*; + + match (self.direction, other.direction) { + (Left, Left) | (Right, Right) | (Up, Up) | (Down, Down) => None, + (Left, Right) | (Right, Left) | (Up, Down) | (Down, Up) => None, + (Left, Up) => collisions( + self.end(), + self.end_signal_distance(), + self.length, + -1, + other.start, + other.start_signal_distance, + other.length, + 1, + ), + (Left, Down) => collisions( + self.end(), + self.end_signal_distance(), + self.length, + -1, + other.end(), + other.end_signal_distance(), + other.length, + -1, + ), + (Right, Up) => collisions( + self.start, + self.start_signal_distance, + self.length, + 1, + other.start, + other.start_signal_distance, + other.length, + 1, + ), + (Right, Down) => collisions( + self.start, + self.start_signal_distance, + self.length, + 1, + other.end(), + other.end_signal_distance(), + other.length, + -1, + ), + (Down, Right) => collisions( + other.start, + other.start_signal_distance, + other.length, + 1, + self.end(), + self.end_signal_distance(), + self.length, + -1, + ), + (Down, Left) => collisions( + other.end(), + other.end_signal_distance(), + other.length, + -1, + self.end(), + self.end_signal_distance(), + self.length, + -1, + ), + (Up, Right) => collisions( + other.start, + other.start_signal_distance, + other.length, + 1, + self.start, + self.start_signal_distance, + self.length, + 1, + ), + (Up, Left) => collisions( + other.end(), + other.end_signal_distance(), + other.length, + -1, + self.start, + self.start_signal_distance, + self.length, + 1, + ), + } + } +} + +fn collisions( + horizontal_start: (i32, i32), + horizontal_start_signal_distance: i32, + horizontal_length: i32, + horizontal_signal_distance_multiplier: i32, + vertical_start: (i32, i32), + vertical_start_signal_distance: i32, + vertical_length: i32, + vertical_signal_distance_multiplier: i32, +) -> Option { + if horizontal_start.1 >= vertical_start.1 + && horizontal_start.1 <= vertical_start.1 + vertical_length + && vertical_start.0 >= horizontal_start.0 + && vertical_start.0 <= horizontal_start.0 + horizontal_length + { + Some(Collision { + x: vertical_start.0, + y: horizontal_start.1, + signal_distance: horizontal_start_signal_distance + + (vertical_start.0 - horizontal_start.0) * horizontal_signal_distance_multiplier + + vertical_start_signal_distance + + (horizontal_start.1 - vertical_start.1) * vertical_signal_distance_multiplier, + }) + } else { + None + } +} + +#[derive(Debug, Clone, Copy)] +enum Direction { + Up, + Down, + Left, + Right, +} + +impl FromStr for Direction { + type Err = UnknownError; + + fn from_str(s: &str) -> Result { + use Direction::*; + match s.chars().next() { + Some('L') => Ok(Left), + Some('R') => Ok(Right), + Some('U') => Ok(Up), + Some('D') => Ok(Down), + Some(_) => Err(UnknownError), + None => Err(UnknownError), + } + } +} +impl Direction { + fn as_vec(&self) -> (i32, i32) { + use Direction::*; + match self { + Up => (0, 1), + Down => (0, -1), + Left => (-1, 0), + Right => (1, 0), + } + } +} + +struct Collision { + x: i32, + y: i32, + signal_distance: i32, +} + +impl Collision { + fn manhattan_distance(&self) -> i32 { + self.x.abs() + self.y.abs() + } +} + +#[derive(Debug, PartialEq)] +struct UnknownError; + +impl fmt::Display for UnknownError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Unknown error") + } +} +impl std::error::Error for UnknownError {} -- cgit v1.2.3 From fb535480020886dfbf41f682f1b9f7b284249912 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 5 Dec 2019 00:29:40 +0200 Subject: Day 4 - some quick iteration --- inputs/day_4.txt | 2 ++ src/bin/day_4.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 inputs/day_4.txt create mode 100644 src/bin/day_4.rs diff --git a/inputs/day_4.txt b/inputs/day_4.txt new file mode 100644 index 0000000..f62320b --- /dev/null +++ b/inputs/day_4.txt @@ -0,0 +1,2 @@ +138241 +674034 diff --git a/src/bin/day_4.rs b/src/bin/day_4.rs new file mode 100644 index 0000000..3cb8d38 --- /dev/null +++ b/src/bin/day_4.rs @@ -0,0 +1,59 @@ +use std::io; +use std::io::prelude::*; + +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 4: Secure Container")] +/// Calculates how many possible lock values there are +/// +/// See https://adventofcode.com/2019/day/4 for details. +struct Opt { + /// Repeated digits must be exactly 2 long + #[structopt(long = "larger-range-rule")] + larger_range_rule: bool, + min: u32, + max: u32, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + println!( + "{}", + valid_combinations(opt.min, opt.max, opt.larger_range_rule) + ) +} + +fn valid_combinations(min: u32, max: u32, larger_range_rule: bool) -> u32 { + (min..max) + .filter(|x| { + two_adjacent_identical_digits(*x, larger_range_rule) && digits_never_decrease(*x) + }) + .count() as u32 +} + +fn two_adjacent_identical_digits(x: u32, larger_range_rule: bool) -> bool { + if larger_range_rule { + (0..5).any(|d| { + digit(x, d) == digit(x, d + 1) + && digit(x, d) != digit(x, d + 2) + && digit(x, d) != digit(x, d - 1) + }) + } else { + (0..5).any(|d| digit(x, d) == digit(x, d + 1)) + } +} + +fn digits_never_decrease(x: u32) -> bool { + (0..5).all(|d| digit(x, d) >= digit(x, d + 1)) +} + +fn digit(x: u32, digit: i32) -> u32 { + if digit < 0 { + 0 + } else { + (x / 10u32.pow(digit as u32)) % 10 + } +} -- cgit v1.2.3 From 955de25778eb7e93e7872dfafbc9569cb345e920 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 5 Dec 2019 22:05:56 +0200 Subject: Day 5: It technically works, even if it's ugly --- inputs/day_5.txt | 1 + src/bin/day_5.rs | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 273 insertions(+) create mode 100644 inputs/day_5.txt create mode 100644 src/bin/day_5.rs diff --git a/inputs/day_5.txt b/inputs/day_5.txt new file mode 100644 index 0000000..f8c2724 --- /dev/null +++ b/inputs/day_5.txt @@ -0,0 +1 @@ +3,225,1,225,6,6,1100,1,238,225,104,0,1102,57,23,224,101,-1311,224,224,4,224,1002,223,8,223,101,6,224,224,1,223,224,223,1102,57,67,225,102,67,150,224,1001,224,-2613,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,2,179,213,224,1001,224,-469,224,4,224,102,8,223,223,101,7,224,224,1,223,224,223,1001,188,27,224,101,-119,224,224,4,224,1002,223,8,223,1001,224,7,224,1,223,224,223,1,184,218,224,1001,224,-155,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1101,21,80,224,1001,224,-101,224,4,224,102,8,223,223,1001,224,1,224,1,224,223,223,1101,67,39,225,1101,89,68,225,101,69,35,224,1001,224,-126,224,4,224,1002,223,8,223,1001,224,1,224,1,224,223,223,1102,7,52,225,1102,18,90,225,1101,65,92,225,1002,153,78,224,101,-6942,224,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,1101,67,83,225,1102,31,65,225,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1007,226,226,224,102,2,223,223,1005,224,329,1001,223,1,223,108,677,226,224,1002,223,2,223,1005,224,344,1001,223,1,223,1007,677,677,224,1002,223,2,223,1005,224,359,1001,223,1,223,1107,677,226,224,102,2,223,223,1006,224,374,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,389,101,1,223,223,8,677,677,224,102,2,223,223,1006,224,404,1001,223,1,223,1008,226,226,224,102,2,223,223,1006,224,419,1001,223,1,223,107,677,226,224,102,2,223,223,1006,224,434,101,1,223,223,7,226,226,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,226,226,224,1002,223,2,223,1006,224,464,1001,223,1,223,1107,226,677,224,1002,223,2,223,1005,224,479,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,494,1001,223,1,223,1108,226,677,224,1002,223,2,223,1006,224,509,101,1,223,223,1008,677,677,224,1002,223,2,223,1006,224,524,1001,223,1,223,1008,677,226,224,102,2,223,223,1006,224,539,1001,223,1,223,1108,677,677,224,102,2,223,223,1005,224,554,101,1,223,223,108,677,677,224,102,2,223,223,1006,224,569,101,1,223,223,1108,677,226,224,102,2,223,223,1005,224,584,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,599,1001,223,1,223,1007,226,677,224,102,2,223,223,1005,224,614,1001,223,1,223,7,226,677,224,102,2,223,223,1006,224,629,1001,223,1,223,107,226,226,224,102,2,223,223,1005,224,644,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,659,101,1,223,223,107,677,677,224,1002,223,2,223,1005,224,674,1001,223,1,223,4,223,99,226 diff --git a/src/bin/day_5.rs b/src/bin/day_5.rs new file mode 100644 index 0000000..a6de781 --- /dev/null +++ b/src/bin/day_5.rs @@ -0,0 +1,272 @@ +use rpds::{list::List, vector::Vector}; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::iter::IntoIterator; +use std::process; +use structopt::StructOpt; + +type Intcode = i32; + +#[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. +/// +/// 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/5 for details. +struct Opt { + #[structopt(short = "i", long = "input")] + input: Vec, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let program: Program = 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::() + .with_input(opt.input.into_iter().collect()); + + let result = exit_on_failed_assertion(program.execute(), "Program errored"); + println!("{}", result); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug, Clone)] +struct Program { + program_counter: usize, + error: bool, + halted: bool, + codes: Vector, + input: List, + output: Vector, +} + +impl FromIterator for Program { + fn from_iter>(iter: I) -> Self { + Program { + program_counter: 0, + error: false, + halted: false, + codes: iter.into_iter().collect(), + input: List::new(), + output: Vector::new(), + } + } +} + +impl Program { + fn with_input(&self, input: List) -> Program { + Program { + input, + ..self.clone() + } + } + + fn execute(&self) -> Result, ProgramError> { + self.run_to_termination().into_result() + } + + fn into_result(&self) -> Result, ProgramError> { + if self.error { + Err(ProgramError) + } else { + Ok(self.output.clone()) + } + } + + fn run_to_termination(&self) -> Program { + iter::successors(Some(self.clone()), |p| Some(Program::next(&p))) + .find(|p| p.halted) + .unwrap() // successors doesn't terminate, so this will never be none. + } + + fn next(&self) -> Program { + //eprintln!("{:?}", self); + self.codes + .get(self.program_counter) + .map(|&opcode| match opcode % 100 { + 1 => self.add(opcode), + 2 => self.multiply(opcode), + 3 => self.input(opcode), + 4 => self.output(opcode), + 5 => self.jump_if_true(opcode), + 6 => self.jump_if_false(opcode), + 7 => self.less_than(opcode), + 8 => self.equals(opcode), + 99 => self.halt(), + _ => self.error(), + }) + .unwrap_or(self.error()) + } + + fn add(&self, mode: Intcode) -> Program { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => Program { + program_counter: self.program_counter + 4, + codes: self.codes.set(out as usize, in1 + in2).unwrap(), + ..self.clone() + }, + _ => self.error(), + } + } + + fn multiply(&self, mode: Intcode) -> Program { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => Program { + program_counter: self.program_counter + 4, + codes: self.codes.set(out as usize, in1 * in2).unwrap(), + ..self.clone() + }, + _ => self.error(), + } + } + + fn input(&self, _mode: Intcode) -> Program { + match self.get_immediate(1) { + Some(out) => Program { + program_counter: self.program_counter + 2, + codes: self + .codes + .set(out as usize, *self.input.first().unwrap()) + .unwrap(), + input: self.input.drop_first().unwrap(), + ..self.clone() + }, + _ => self.error(), + } + } + + fn output(&self, mode: Intcode) -> Program { + match self.get(1, mode) { + Some(print) => Program { + program_counter: self.program_counter + 2, + output: self.output.push_back(print), + ..self.clone() + }, + _ => self.error(), + } + } + + fn jump_if_true(&self, mode: Intcode) -> Program { + match (self.get(1, mode), self.get(2, mode)) { + (Some(pred), Some(to)) => Program { + program_counter: if pred != 0 { + to as usize + } else { + self.program_counter + 3 + }, + ..self.clone() + }, + _ => self.error(), + } + } + fn jump_if_false(&self, mode: Intcode) -> Program { + match (self.get(1, mode), self.get(2, mode)) { + (Some(pred), Some(to)) => Program { + program_counter: if pred == 0 { + to as usize + } else { + self.program_counter + 3 + }, + ..self.clone() + }, + _ => self.error(), + } + } + + fn less_than(&self, mode: Intcode) -> Program { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => Program { + program_counter: self.program_counter + 4, + codes: self + .codes + .set(out as usize, if in1 < in2 { 1 } else { 0 }) + .unwrap(), + ..self.clone() + }, + _ => self.error(), + } + } + + fn equals(&self, mode: Intcode) -> Program { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => Program { + program_counter: self.program_counter + 4, + codes: self + .codes + .set(out as usize, if in1 == in2 { 1 } else { 0 }) + .unwrap(), + ..self.clone() + }, + _ => self.error(), + } + } + + fn halt(&self) -> Program { + Program { + halted: true, + ..self.clone() + } + } + + fn error(&self) -> Program { + Program { + halted: true, + error: true, + ..self.clone() + } + } + + fn get(&self, pointer_offset: usize, mode: Intcode) -> Option { + match mode / (10 as Intcode).pow(pointer_offset as u32 + 1) % 10 { + 0 => self.get_position(pointer_offset), + 1 => self.get_immediate(pointer_offset), + _ => None, + } + } + + fn get_immediate(&self, pointer_offset: usize) -> Option { + self.codes + .get(self.program_counter + pointer_offset) + .cloned() + } + + fn get_position(&self, pointer_offset: usize) -> Option { + self.get_immediate(pointer_offset) + .and_then(|r| self.codes.get(r as usize)) + .cloned() + } +} + +#[derive(Debug, PartialEq)] +struct ProgramError; + +impl fmt::Display for ProgramError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Unknown error") + } +} +impl std::error::Error for ProgramError {} -- cgit v1.2.3 From 9438066faf52464f8834035721733d82cdf4e322 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Wed, 11 Dec 2019 00:23:51 +0200 Subject: Cleaned up error handling It still doesn't say anything about the errors, but maybe next time. --- src/bin/day_5.rs | 138 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 66 deletions(-) diff --git a/src/bin/day_5.rs b/src/bin/day_5.rs index a6de781..e7539e1 100644 --- a/src/bin/day_5.rs +++ b/src/bin/day_5.rs @@ -56,10 +56,10 @@ fn exit_on_failed_assertion(data: Result, message #[derive(Debug, Clone)] struct Program { - program_counter: usize, + instruction_pointer: usize, error: bool, halted: bool, - codes: Vector, + memory: Vector, input: List, output: Vector, } @@ -67,10 +67,10 @@ struct Program { impl FromIterator for Program { fn from_iter>(iter: I) -> Self { Program { - program_counter: 0, + instruction_pointer: 0, error: false, halted: false, - codes: iter.into_iter().collect(), + memory: iter.into_iter().collect(), input: List::new(), output: Vector::new(), } @@ -85,6 +85,47 @@ impl Program { } } + fn with_instruction_pointer(&self, instruction_pointer: usize) -> Program { + Program { + instruction_pointer, + ..self.clone() + } + } + + fn with_instruction_pointer_offset(&self, offset: usize) -> Program { + Program { + instruction_pointer: self.instruction_pointer + offset, + ..self.clone() + } + } + + fn with_memory_set(&self, address: usize, value: Intcode) -> Program { + self.memory + .set(address, value) + .map(|memory| Program { + memory, + ..self.clone() + }) + .unwrap_or(self.error()) + } + + fn with_input_consumed(&self) -> Program { + self.input + .drop_first() + .map(|input| Program { + input, + ..self.clone() + }) + .unwrap_or(self.error()) + } + + fn with_output(&self, print: Intcode) -> Program { + Program { + output: self.output.push_back(print), + ..self.clone() + } + } + fn execute(&self) -> Result, ProgramError> { self.run_to_termination().into_result() } @@ -105,8 +146,8 @@ impl Program { fn next(&self) -> Program { //eprintln!("{:?}", self); - self.codes - .get(self.program_counter) + self.memory + .get(self.instruction_pointer) .map(|&opcode| match opcode % 100 { 1 => self.add(opcode), 2 => self.multiply(opcode), @@ -124,103 +165,68 @@ impl Program { fn add(&self, mode: Intcode) -> Program { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => Program { - program_counter: self.program_counter + 4, - codes: self.codes.set(out as usize, in1 + in2).unwrap(), - ..self.clone() - }, + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, in1 + in2), _ => self.error(), } } fn multiply(&self, mode: Intcode) -> Program { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => Program { - program_counter: self.program_counter + 4, - codes: self.codes.set(out as usize, in1 * in2).unwrap(), - ..self.clone() - }, + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, in1 * in2), _ => self.error(), } } fn input(&self, _mode: Intcode) -> Program { - match self.get_immediate(1) { - Some(out) => Program { - program_counter: self.program_counter + 2, - codes: self - .codes - .set(out as usize, *self.input.first().unwrap()) - .unwrap(), - input: self.input.drop_first().unwrap(), - ..self.clone() - }, + match (self.input.first().cloned(), self.get_immediate(1)) { + (Some(input), Some(out)) => self + .with_instruction_pointer_offset(2) + .with_memory_set(out as usize, input) + .with_input_consumed(), _ => self.error(), } } fn output(&self, mode: Intcode) -> Program { match self.get(1, mode) { - Some(print) => Program { - program_counter: self.program_counter + 2, - output: self.output.push_back(print), - ..self.clone() - }, + Some(print) => self.with_instruction_pointer_offset(2).with_output(print), _ => self.error(), } } fn jump_if_true(&self, mode: Intcode) -> Program { match (self.get(1, mode), self.get(2, mode)) { - (Some(pred), Some(to)) => Program { - program_counter: if pred != 0 { - to as usize - } else { - self.program_counter + 3 - }, - ..self.clone() - }, + (Some(pred), Some(to)) if pred != 0 => self.with_instruction_pointer(to as usize), + (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), _ => self.error(), } } fn jump_if_false(&self, mode: Intcode) -> Program { match (self.get(1, mode), self.get(2, mode)) { - (Some(pred), Some(to)) => Program { - program_counter: if pred == 0 { - to as usize - } else { - self.program_counter + 3 - }, - ..self.clone() - }, + (Some(pred), Some(to)) if pred == 0 => self.with_instruction_pointer(to as usize), + (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), _ => self.error(), } } fn less_than(&self, mode: Intcode) -> Program { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => Program { - program_counter: self.program_counter + 4, - codes: self - .codes - .set(out as usize, if in1 < in2 { 1 } else { 0 }) - .unwrap(), - ..self.clone() - }, + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, if in1 < in2 { 1 } else { 0 }), _ => self.error(), } } fn equals(&self, mode: Intcode) -> Program { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => Program { - program_counter: self.program_counter + 4, - codes: self - .codes - .set(out as usize, if in1 == in2 { 1 } else { 0 }) - .unwrap(), - ..self.clone() - }, + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, if in1 == in2 { 1 } else { 0 }), _ => self.error(), } } @@ -249,14 +255,14 @@ impl Program { } fn get_immediate(&self, pointer_offset: usize) -> Option { - self.codes - .get(self.program_counter + pointer_offset) + self.memory + .get(self.instruction_pointer + pointer_offset) .cloned() } fn get_position(&self, pointer_offset: usize) -> Option { self.get_immediate(pointer_offset) - .and_then(|r| self.codes.get(r as usize)) + .and_then(|r| self.memory.get(r as usize)) .cloned() } } -- cgit v1.2.3 From 46eda1faf09a3b33d925ea1692d6b38029606c4c Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Wed, 11 Dec 2019 01:18:13 +0200 Subject: Input parsing for day 6 --- inputs/day_6.txt | 2306 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/day_5.rs | 8 +- src/bin/day_6.rs | 77 ++ 3 files changed, 2385 insertions(+), 6 deletions(-) create mode 100644 inputs/day_6.txt create mode 100644 src/bin/day_6.rs diff --git a/inputs/day_6.txt b/inputs/day_6.txt new file mode 100644 index 0000000..49d849c --- /dev/null +++ b/inputs/day_6.txt @@ -0,0 +1,2306 @@ +21X)BWV +YZJ)YLQ +FQS)PZW +R64)71F +ZH4)QVZ +LWB)H4Q +4HQ)PVJ +TZ5)VBV +LF1)FKZ +GKS)BGN +45B)2NS +14W)2JY +1XY)FJ8 +ZRC)WR9 +GCL)6PB +LP4)GQ8 +26V)HTK +3M8)1GJ +47Q)JYK +WDB)N2R +KH8)TGY +LFX)N2X +VSZ)7PC +M6W)4WL +HH9)8PC +L59)8Y8 +Q49)LWH +CJ5)XDG +K51)FGH +H31)2RJ +39M)Y4M +12C)VLF +PZW)7DW +MP2)19Q +R76)CHH +N6J)KBW +WR9)W25 +T99)ZF1 +1TS)8SM +8WW)YX7 +PW6)B2J +7KX)YM5 +HM6)GVX +DNB)2YP +6WC)2LW +BG5)SB6 +KK1)JTF +YDT)244 +GGQ)2DJ +GCP)Q8H +S1Y)J69 +LBV)DYG +ZKN)JBS +8XY)Y8Z +XMH)NHD +XVM)2LX +SYP)BC8 +PXH)YYG +F29)G9Y +BYX)4QS +8MY)S1D +N2Y)BZK +FRC)72W +S2K)YH5 +7JF)K65 +DJ9)K4L +P26)WXT +DW9)1DJ +NP4)3SB +XS7)CDL +6XH)4ZT +2DJ)GCP +2K4)VV1 +Q6P)NNN +HQW)ZR9 +9G2)FNB +H9N)5ZJ +13Z)GKD +9MW)37Y +VDY)BG9 +BL3)12C +LNN)JST +Z3V)T39 +XS3)WYG +8J5)QFQ +7DW)DXY +JMV)DM4 +VL3)V7Q +GZC)ZHV +3N6)R2H +FQ6)7LG +SR9)D66 +1M8)K2L +24N)M94 +JST)WM9 +7SB)99Q +58J)YN7 +WWH)5KS +C39)X9J +58S)KBP +TVF)VNG +TKC)Y34 +KKP)4S6 +XSP)939 +N6J)DZP +JXP)N6R +KNJ)7FS +N3V)LMJ +JVF)R94 +21C)R4Z +NYK)5GN +GVJ)Q6C +R69)NRS +GLS)C7D +T4J)46R +5GB)51S +9WD)7PN +HHX)KK2 +H2P)ZML +DWD)Q9F +FKZ)LC3 +Q9F)M8N +CRZ)LM1 +6DP)YML +NSR)L2X +PMX)Q7K +37R)1GF +L4G)P4W +17N)X6D +JTF)89B +JGJ)DVJ +VF9)GMW +NHD)DJ3 +TRY)F6S +J11)BVW +95X)XB5 +3XD)HPM +7BB)1LW +FJ8)TV4 +JV3)M9W +T7L)6SS +R48)LSB +F2P)9D2 +PTY)QBY +KXM)6G1 +N1H)Q2R +P27)SR9 +1S2)N3G +V7Q)642 +891)TW7 +B9Y)BRL +GW4)3XZ +QWM)G46 +WVK)S6N +N82)317 +8PG)S21 +NT3)1VX +QB5)Y3H +PTT)639 +G8M)WM8 +B36)LX9 +M9M)4P3 +3F9)Q3R +DND)TJL +VQB)6N3 +PJT)JTK +BBN)T4L +LYP)M3V +T9R)HH9 +XBR)3X5 +MX3)SWF +SF1)MXT +X67)6DQ +82Z)FQ4 +L64)FNG +CDG)5D9 +JKZ)XZ5 +MH1)1KD +5NW)ZH4 +P3T)76Z +2M4)CKW +54L)8P7 +JSH)5H5 +LGR)P2V +QNV)SJ7 +KPS)XMQ +F2H)49M +8NJ)KKP +XZ1)LRZ +RVK)J5Z +QT9)NGQ +1TK)P7X +39M)595 +DN9)HKY +HK1)ZRH +SH1)JV5 +B25)GQ6 +QZC)WYC +6CJ)F5D +5R1)HQ7 +FNT)P4J +4R6)P49 +LG4)QT9 +GWH)RY1 +1FX)ZK8 +HK4)G2N +4WL)GPR +SQT)KK1 +RT4)FCN +NRF)P84 +DQW)4L4 +52N)T4J +69D)2FV +RMV)J7N +S9J)1WM +B88)9GT +5M7)GXN +3XF)6FX +FL9)8VZ +X88)JZR +ZVZ)8J2 +Q83)94V +82Y)HT7 +7Y7)7X3 +KNK)R1W +469)PMG +D9Z)GD1 +Z62)WR1 +YDF)6B6 +5KS)6GW +57T)ML7 +GXC)R89 +S2N)99C +JFH)RP9 +KPH)R26 +DZX)93P +CWT)C2H +VKN)5M7 +VNG)SH1 +G2N)F6Q +NFV)FK3 +R65)TQL +Z6T)4NG +RQN)KPR +972)9TB +KZ1)6TY +8K2)HKL +KHJ)H1W +6N3)XTR +25Q)T49 +8HF)K9M +GQX)PHP +5ZJ)9S7 +C7D)VMJ +JXV)SJD +J17)64C +5XN)WN7 +PH9)WQH +43T)Q9V +Z5F)NZ8 +VHQ)D95 +244)7KX +6N7)JPH +HC8)HND +ZF1)39F +24X)ZPF +BWV)HQW +R3N)5R1 +QB9)6XY +KHW)KFZ +S2V)DRQ +S21)1RQ +C9V)TSD +Q1Y)LC2 +93Y)W5C +8ST)T4P +R5Z)CL4 +424)WNZ +R7M)5JS +4R6)H97 +ZXZ)S62 +FRH)SBJ +ZK8)N82 +6FX)MTK +Z5M)BRQ +YYP)FX8 +RZJ)DRK +V8G)TKQ +5L9)J1G +RZG)69H +R9G)X79 +WFS)ZJQ +4P8)GXC +TYW)S54 +R2H)QH7 +6HX)F2H +BBD)DC5 +DDB)6WC +2G3)4JN +FKC)K7V +XTK)8BD +Z7X)QGY +8CG)3F9 +F39)MM9 +F1L)1R7 +ZVH)JDC +BVW)PXM +PRV)BF7 +FX8)1XR +FB2)XN6 +R9L)Z1V +YDT)H52 +6Z5)XZ1 +QD2)Z7Y +TLS)6T3 +54C)DL7 +KPR)4TY +19N)415 +1QG)GNN +S6N)4MK +4L8)LD2 +5Z7)PRY +5C4)2MC +94B)DY3 +CVK)GTS +7N7)P27 +5MW)GGH +2HQ)JYL +L9J)HLP +5Y4)NGN +2BZ)GWN +HD8)CZS +HQ7)M9D +DC5)RK6 +66W)2VT +3D4)GHZ +T49)VTP +PL4)ZS9 +SJ7)TRC +NKT)G5Y +K1G)3GN +37V)4LG +KWL)VDZ +7XF)1P8 +64C)FX4 +DY4)J3F +RV8)8KF +DRQ)KQ7 +HND)2N7 +HQS)HMW +J24)9VX +7DK)3PM +467)VBK +Q6C)TZC +SZY)9TC +BMM)4S4 +HFH)2S6 +K5K)4QP +N6W)RZG +TKQ)489 +4R1)F22 +J1G)YDF +FVW)9WD +CV7)TMC +R6K)H31 +GDL)X14 +H1B)NKT +XTR)PL6 +BSC)SM7 +MLT)S7B +22S)R7T +X8Y)4WX +NR9)NK9 +FSM)J3S +WHF)VSG +ZBG)Q3D +RMY)7KM +XBX)1M8 +MHY)1C2 +GSS)X9G +86F)Y4W +VL6)6H9 +1VH)L3B +SF8)CDG +GTK)45F +49M)NLL +FN6)PN3 +KSC)R3Z +6TN)3QN +FNG)742 +X45)WWH +SF5)2WH +JSJ)B1H +95L)M8F +L59)C4Y +93P)M89 +K1C)6ZZ +21T)8M6 +X9M)7NX +WPK)LNG +393)F6N +M4L)JXP +VKN)X88 +NFK)ZVZ +LKV)C2V +SWX)TM8 +V7F)8ZN +3RW)FD8 +9SM)H27 +TP3)1YB +6MG)D8X +8S7)345 +9SV)X67 +25P)JDD +BFX)TNG +36J)VBH +HN7)WVK +ZR3)3NR +M3V)GPY +52M)MFV +MZB)CJ5 +MX3)XLQ +LCG)PHS +HZD)RNC +GWN)DWD +XBM)WP4 +2FV)YXW +ZTP)QD2 +R1G)JY6 +KY4)8CG +H54)RVK +5HG)WYQ +BVC)SK1 +948)P3T +SV8)5MW +V4D)YLT +69X)LNZ +BL3)Y97 +DXG)WLZ +VV1)SS3 +ZCD)VXB +X6D)XL2 +B9H)2NB +KHK)WPK +YLT)KFT +P49)CC5 +KBW)CRH +8KQ)LJ4 +8JJ)VTJ +TKM)428 +3SB)273 +GPY)R2Z +WTX)P6W +LB1)3PR +Y1R)DJM +25P)CY5 +SVB)PJM +56N)S2V +H82)8D5 +CYB)GP4 +HJ2)BSH +2J1)F1T +C4Y)PRM +TZC)PM5 +K55)NBJ +X43)LPP +WYG)3FW +WFG)N2Y +Q37)5L9 +WSF)KSH +V2H)S9J +HN2)DW9 +3LL)PFH +6X3)XVM +8XZ)991 +26L)WTX +Y97)5C5 +XXL)79Y +NK9)RR8 +L7W)83Q +8TX)45B +GMJ)1H4 +ZRW)58J +36X)PRS +8B2)HTL +8JZ)L94 +PRY)QTW +PL4)X8Y +89N)1RJ +DFJ)62K +5QZ)CN3 +RYQ)SL6 +1H4)PGZ +B1H)J88 +JCC)111 +V6W)GG7 +BZK)97X +49J)WVY +1WM)21X +TCN)KSC +RRD)26V +VC6)WPS +Y5S)YJS +DVR)2J8 +LJF)839 +64D)GZC +79Y)SZY +JHT)D6J +K4K)L59 +YHB)QWM +6H9)MRR +X79)M62 +LW7)GGB +469)TRQ +14K)951 +L9Y)K51 +W7C)Y73 +XD1)CYL +1XQ)HYK +Q19)PWG +F4M)KHW +SM1)J3Q +MV1)1X9 +NMV)3SM +8ZD)L61 +VWX)6R6 +S4Z)JK4 +9GT)R13 +F66)89X +DLT)K6R +H4C)NW9 +R3D)6Z5 +MKN)M5V +H4C)22S +BFM)J2V +KQW)G8D +V61)6HG +JX4)LH3 +PHS)P68 +V9M)56X +1Q6)Y8V +319)KX2 +M8F)881 +974)KSL +LRP)XXL +M3Y)Q39 +LC3)B9H +4T8)ZRW +KYB)T7L +DXJ)72V +SRP)D3M +BRN)NGD +43S)NJ1 +KWJ)VGZ +DNY)F2J +DKW)YT1 +6B4)6N5 +GRQ)RYT +4KV)WFG +6PG)T9R +Q3T)V2P +4M5)HLG +WKZ)9ZP +XTP)JMC +PVZ)JN1 +5F2)26L +76Z)R5P +FVW)NS1 +MWS)PXD +Z7Z)8S7 +CTH)7C2 +837)48K +3SM)HYY +J2B)1TS +Y8V)BS6 +YYD)3XH +4F7)BFM +6S1)95D +4KN)JV3 +GSZ)HVF +9CP)GPZ +BFN)LB1 +N72)741 +K6R)3WF +P4J)QQW +54G)469 +36T)GJ4 +HXM)X6W +MR9)M29 +XMQ)SP9 +71F)TJR +95X)DLT +1ZX)QVK +F1L)1SY +B7X)XDB +FJW)ZCR +43X)1XH +D5H)93V +FQH)5RJ +CLW)1RG +X4Y)X9M +CRH)DWH +XWX)GWZ +36J)TKC +YFN)YJ6 +15X)MBT +6T3)NDG +8SY)4R7 +XMG)HR5 +KSZ)WKZ +PM5)3K8 +BR4)J1T +F72)GV7 +317)P1W +CV7)SPK +H53)PMX +NDG)56N +N68)ZXZ +X3W)XGJ +JRJ)S7X +MKN)DBW +8CM)953 +M2K)3XL +95K)95X +58S)4HL +D95)L9Y +FRH)KQW +NLL)C3D +X1H)FM1 +R1M)GGQ +Y8Z)W1B +KLD)G1V +6CJ)R5X +5C5)HN7 +T7M)ZXT +SZF)B5W +RPW)6TG +3VP)2W9 +X2J)RXH +DWG)C9V +9FB)524 +1PZ)8ZD +ZKZ)6S1 +L36)ZKN +F1J)2D4 +LWC)6SW +SWF)Y4V +51L)MWS +KFZ)52N +GD1)HFH +LFK)L36 +KPZ)ZQ6 +3NT)W48 +2CD)G3D +345)JXV +2LW)SWX +9ZY)XTJ +VWR)576 +STH)NHY +L4X)M4L +ZML)RN7 +RDF)7PB +7FK)3KR +GVX)DCF +1WX)DD2 +971)H6W +H6H)BPX +BWQ)Z4J +JPL)3SV +QWJ)TR8 +376)H9P +Q3D)1YS +1N2)FQ6 +2LM)53K +VSG)6DP +KNM)8B7 +S7B)YXF +YHB)JHP +Y7N)CPB +M29)3FB +J37)C8B +MK3)WHL +MRG)TQ8 +BFM)DLH +H4Q)9HF +D81)R7M +LRQ)ZKZ +C1B)413 +BKC)PW6 +GP4)6MX +C39)JSH +BW8)TL2 +71Q)3YP +415)H2V +DBH)BR4 +JJ7)J2H +G52)87N +YV2)JN3 +7PR)Z3V +999)G8M +S7Y)JRJ +G3D)88H +SR3)NTR +JY5)FC8 +MYL)B7X +K7V)HM6 +FXY)L47 +NNN)GYH +8JJ)Y5S +3G5)37V +FLP)4B2 +839)83S +H27)CV7 +X4F)RXV +S3P)WMZ +LD2)SF8 +DYG)77S +LGR)2LM +7BX)G2K +KNF)9S5 +JBS)R45 +T6C)CGH +CNV)2BZ +356)1KP +P93)54J +VGZ)31Y +GNG)HDL +RHW)222 +4T4)4T8 +WVY)M5Z +KQ7)XMG +K7F)S2N +X6Z)Z9S +XYH)WFC +7BM)J2B +H9F)LKV +WDJ)HWH +MWM)83M +YM5)7J5 +Z62)8NR +99Q)TVF +VDP)C2N +9VX)B5T +YS6)KNF +35R)ZH5 +JN5)Y4H +MSN)XSP +776)CJ4 +3FB)HXT +HZV)6HY +Q6N)HXS +MBT)FTN +3JP)YJ2 +4DC)KSD +8PG)5QZ +YSP)CNV +THM)CST +3X5)BPC +ZG9)4KY +8M6)MZ5 +FDF)XNB +H4X)N72 +ZH5)J79 +KN7)ZXV +1GP)R76 +K5R)CLZ +W8G)XVF +YJQ)HB8 +BWC)TB6 +WFH)T6C +DPB)VYF +K8N)KWJ +C2V)HMF +H93)HF3 +TR8)MFW +RJ4)F66 +BS6)FVW +QFW)5B2 +ML7)FB2 +TGY)X9Z +PRM)ZV3 +4YX)4YV +36D)N6X +XLQ)TLS +WMZ)NRF +BCM)2CV +M74)CHT +JYL)LQ4 +RSN)KXR +KNK)3Y2 +89X)BJK +C2H)4YQ +YYQ)VMB +164)11H +WYQ)WSF +1RG)DRH +GKD)LLT +H53)T2F +X2Q)F82 +B5D)5F8 +JK1)4F7 +1YB)P26 +B6F)552 +RTD)883 +ZPF)DWG +JRV)DL1 +MLQ)S1Y +TX8)5QV +NDT)2MF +HFS)61F +HD8)TCN +8BL)F2X +4MK)R6Z +WVN)RMY +GGX)JCC +GQ8)J11 +H4V)5FJ +3JD)VNC +7KS)9SM +NTR)YV2 +4LG)JK1 +3XZ)GGX +SVZ)P96 +4WG)N3V +QY7)8N9 +XMP)LKL +T4P)RLM +J7C)JJZ +7PC)Y23 +LPP)M6T +F82)9KL +9XR)VT4 +SF1)4T3 +FW6)N66 +QBY)D49 +BCM)17Y +H1W)R6K +ZVN)7QK +BRH)7JF +LKL)39C +LV1)BJS +8PC)FN6 +CHB)TBS +ZLR)3XD +8BD)BSC +NVC)9FB +Z9L)HK1 +FT3)BWL +446)S8V +LM1)D8G +KH3)Q6P +J8C)WFH +YT1)SDH +CGZ)X3V +77B)V9M +2RJ)H4V +NHY)H47 +89B)HM7 +Z1V)58S +17Y)1Q7 +J3F)891 +WDG)VSZ +PJM)21T +3YL)74D +8XJ)15N +Z2X)VHH +N6R)R93 +5QV)8XY +KSD)RYF +6DQ)X8F +Z2Q)MZB +ZFG)972 +5LK)FT3 +D25)1CF +RMQ)2HQ +85N)HDY +952)WFS +T4J)B88 +2MC)JFH +BRL)D64 +GJ4)65N +ZC2)QLQ +69T)3WV +W4F)WMG +74D)NCN +3YY)19K +JKG)6CJ +S68)GGZ +6N6)H2P +3XL)ZVG +S1D)14K +GMK)DW3 +HJF)1D5 +9DP)P9D +18K)Z2Q +248)YD2 +DTK)MR3 +LH8)1GZ +7ZC)RZJ +YJ2)ZVN +JN1)1FX +3WV)289 +53D)GJX +883)FXW +79K)ZXD +DLH)9X5 +BRQ)KHK +2XW)R65 +RGD)GCY +RNC)TR9 +HYV)54C +SJF)BBD +T81)F2T +GZ2)KBQ +G2K)48L +PL6)B5D +R76)Z4Z +QVK)TDX +F6N)M6X +8XQ)3JP +HXD)WNB +CLZ)37R +K6R)SY1 +X9G)8CM +2W9)W4X +ZXV)JC5 +HKY)1Q4 +KV1)QZC +LMT)CLW +Y4M)P57 +1YS)SJF +NGV)N1R +VLF)RGD +FJ5)8WN +PWG)V4K +XDC)KY2 +3DJ)RV8 +1RJ)2GN +WXT)MP2 +R89)JLR +GGB)RDG +Z6L)GQX +ZJQ)TLG +3WF)FQH +5YP)5Z3 +C1B)CCD +SBW)BQB +41C)W4H +1P5)YYP +R5X)36J +DZL)KNW +P57)CN4 +C85)78L +6YB)S7R +CYB)LNN +881)Z5X +642)B5K +X9J)SQT +BJK)M39 +BMW)SHT +2NS)VKN +1C2)JHT +H46)ZGD +JY6)RF8 +V1D)82Y +Z4Z)FW6 +CRP)JRG +1VX)77V +M2F)MHH +B7X)JJV +H29)7JR +Z4C)N13 +HN2)PRV +FTN)5FY +8HS)Z4M +JTP)GLS +JST)8XZ +4GX)T2P +1GZ)V8W +5MW)RT4 +9G2)QPQ +X6C)NGV +GP8)8SY +J67)ZBL +R45)BWC +DDF)S37 +31R)PHR +V4K)2L6 +J69)SYP +DVF)R29 +DLS)1BQ +72W)JKH +JPV)FL9 +TSK)69T +93V)T9M +CST)WPW +37Y)BJ8 +JR2)V4Z +B7C)X1V +WN7)GCD +K65)TM5 +HFS)KYB +1XR)TX8 +7L2)NXY +57Z)M6W +WMG)5HG +F6S)3YF +FMB)N6Q +HS4)QNV +XN6)X2C +56X)Z5F +NJ1)3M8 +65K)S2S +MSJ)Z3P +3RW)YJQ +YRB)L4G +5DZ)5YP +TB6)TGV +PDM)H9F +MTR)B36 +GGH)2LS +4S6)4KV +SVB)MV1 +JQN)18K +SRN)ZFK +ZFX)HXD +YNR)GCL +8QM)GDK +17G)B9Y +JKZ)19N +MJD)5BH +NSR)24N +T48)CF2 +Q3R)3TZ +741)T7M +P2C)G9Q +V8G)17G +GCC)54L +53K)TC8 +ZGD)F7V +J5Z)Z7X +4YV)HZV +GPZ)69X +RYT)RTK +Z6T)7ZC +FMT)ZVJ +56X)7KS +M89)YDR +F6Q)V8G +Y4V)MY7 +1Q7)17N +YV7)HQS +YLQ)GJ2 +5WT)VQB +YN7)DR2 +MPX)JBC +LFL)DPB +TNG)5Q1 +LW7)HC8 +HBR)Q6N +9K2)DNB +GXN)MHW +SGZ)1HF +WFS)N4R +3GN)2K4 +5Y4)1MH +M9W)7PR +WCK)DMQ +COM)TKH +6XY)LTM +WQF)1S2 +Z6N)3BD +CF2)LFL +GDX)ZQ4 +PGZ)1VH +X5D)6CP +TDX)MKV +3XX)BHR +SPL)DXS +GM5)TZR +M8W)DBH +PFH)KGJ +W4H)MKN +SPK)LRQ +V4P)63V +5LQ)WDG +L2G)49J +HB2)6Q9 +YV4)NTM +H47)9MW +ZB8)Y8J +C3D)HTQ +9HF)9K2 +XDG)GDX +FMS)239 +JJP)PKV +6C1)BL3 +FNX)JX4 +SN2)237 +TSD)PNN +RY1)JL3 +TX5)B2R +BS5)HJK +TBS)JNC +1BQ)PR5 +NRS)FX1 +5GX)BKC +8Y8)FRH +GP1)KFR +H1W)ZLJ +FX1)WT6 +HJK)WFT +7Z4)GT9 +FD8)RGG +8VZ)5PJ +1LW)PTY +PTT)15X +QVZ)6LR +Q9V)WMP +BLW)4DX +554)35D +YML)DND +997)CTW +L2L)6WB +PR9)K5K +6TY)5Y4 +2RQ)DVF +5PL)NK7 +3WB)KJ7 +PXM)HN2 +NBJ)FMB +BGN)BRP +BTH)C2B +9X5)MLT +XGJ)KGD +TDC)SBW +56Q)K7F +HF3)Z2X +RP9)952 +PKV)K4K +222)95K +LX9)4WG +RYF)HB2 +5CL)C4P +J2H)6PG +CXP)5GB +38R)L7N +NJ1)YDZ +LBC)42B +6WB)NCK +524)YOU +D8X)YNZ +KY2)BRH +W5X)DZX +SP9)G1J +JKT)LGJ +J2V)PJT +6SS)R9G +8MF)2L8 +X4J)8JJ +T1P)DLS +NWC)76R +YXW)RMQ +Y64)9NF +XB5)52M +JKP)YC1 +FZ2)ZCD +Q3S)CWT +YCS)QDR +S3M)792 +Q7K)N5M +952)MYL +GPR)F37 +Y7G)TFK +V7H)2G3 +CHW)BVC +FSM)TRY +RS7)BFX +KF6)3RW +TGV)6BJ +3TP)CXP +DXS)BW8 +8QM)NT3 +R4Z)X43 +7X3)7N7 +JJZ)3WB +GWZ)K7Z +XQF)R1M +2L8)4YX +891)F1D +S73)KS9 +289)3TB +XJF)PDZ +C29)K7N +YH5)8F3 +9NF)8LD +YX7)1NW +ZLJ)ZGS +DWS)CY2 +Z4P)XBM +HKY)K55 +P6W)BWQ +P1H)L64 +54T)25P +W38)6KP +CNV)9S2 +7FS)75T +9SV)PQQ +H46)VL3 +3FW)W91 +JBW)T99 +J89)MLR +CJC)4B6 +NYK)189 +R2K)3CT +S54)BHJ +98D)HRL +F1T)GRQ +T9M)NZJ +5B2)FNX +PQJ)D89 +WG3)2W2 +ZS9)WW8 +FSG)5SS +DW4)ZFG +78L)49Z +NGQ)2TJ +M6X)GDP +KXR)95L +1WQ)FNT +BRP)L4X +J3F)5C4 +2NB)JJD +SZL)5PT +FNB)DN9 +LNZ)ZBG +Z4J)NQV +D6J)H54 +1CF)SZF +QQF)1N2 +FFS)VF9 +NK7)KRM +6HY)TDQ +C2Q)16T +JTK)ZLR +1KD)N3R +2XH)JKP +BJ8)QHR +G9Y)5F2 +4R7)HGM +JGH)XS7 +72G)LLM +QLQ)Q1Y +TJL)8JW +N8F)8SX +JY8)HZD +3W9)JPV +WK4)HBD +8X9)6XH +YYG)WJQ +HZL)NQZ +BLY)JJG +6CH)CR4 +GQ6)248 +DWH)5LK +LQM)Z7Q +SN2)4DC +BF7)BTH +Z9S)NG8 +F5D)HK4 +2S6)5NW +LTM)757 +FC8)89N +SBJ)4T4 +XLM)XQR +S29)TDC +1YK)RL3 +6J2)7NB +SK1)7CS +GBD)H77 +9KL)HJF +LJ4)VST +S9W)4KN +99C)Z6N +L58)M2K +5JS)LR8 +WR5)9XR +V6W)WK4 +9S7)FRC +TM8)C39 +F4Q)Y86 +BN1)MTR +BGG)GP8 +GJN)MV8 +TLG)XYH +83S)CHW +Z1H)GX4 +3TB)HHX +J3Q)JQL +5Q1)75N +W91)57T +DVJ)HBR +B6F)M9M +WMP)5XN +WXQ)B17 +83M)XMH +8N9)SAN +LVG)8ZV +L2J)7SB +FNT)KM7 +BPC)B9T +1TQ)K27 +JZR)RJ4 +L9S)H93 +189)36D +TZG)2Z4 +5LZ)HXM +SJD)Q3S +WJQ)D81 +GP8)GZ2 +1TP)ZNV +X2J)837 +DJM)KDJ +7GP)NYK +TQ8)446 +HZL)4L8 +29G)3VP +4LZ)XTK +KFX)6N6 +HPM)WWQ +X1V)KVV +Y64)V4C +5GN)54T +SJ1)QS3 +DM4)83W +KDT)ZB8 +DL7)DKC +TML)SPL +LC2)K1W +MHW)5Z7 +MXT)RQN +9KL)K9L +M3T)YRM +KFR)Q49 +1DJ)SN2 +F82)2J1 +PWN)5PX +YT1)V7F +T6S)T1F +B8L)WB2 +Q79)LKF +853)RTD +KBQ)356 +HTL)54G +43T)53D +B5W)PH9 +7KQ)8TX +T2Z)1WQ +8HY)29M +552)M74 +STR)6HX +FRV)HMM +45F)J7C +4Y9)HFS +GNN)WJ6 +HXT)JQ8 +PNN)51L +PHR)RK5 +MM8)H1B +N66)G85 +C4P)W7Z +991)FSM +7QK)SLP +GDP)71Q +5MC)MRG +F2X)HY1 +B9B)CWM +SVZ)HN8 +XDB)4P8 +BS3)VFP +VXM)KCL +9G6)831 +9Z8)FNJ +GX4)C2Q +WFB)MZ9 +63V)MX3 +V8W)82Z +RTK)319 +427)WY1 +4T3)VVN +T2P)4LC +CR4)FQS +K4L)DTK +HLP)WCK +4YQ)H9N +RK5)QFW +GT9)SRN +YXF)FXY +V74)L3W +MY7)2RQ +JLR)JNS +9S5)LPH +H54)J37 +8XR)BLY +QMC)T48 +4TY)1QG +Z4J)H82 +BZC)LKD +4CP)86F +Z24)L58 +1FN)X15 +5FJ)QWJ +K27)2CD +3Z9)3W9 +L6V)J1J +51V)HJ2 +WD5)Q99 +49Z)G6N +Y4V)DDF +MFV)3GH +B1T)9CM +X9Z)BG5 +2M6)1XQ +2J8)3G5 +VMB)13Z +51S)BMW +1MH)LFK +VBK)3D4 +SDM)8XR +7NX)S2K +52L)4NL +LRS)664 +JDD)43S +JJV)H6X +62K)7L2 +WR1)L3D +LN4)WXQ +S52)C85 +F22)9SV +LH3)8B2 +YBD)8MY +TGM)N6H +ZVJ)MSN +S2S)5HV +2MF)GP1 +9ZP)3ZK +1LW)H44 +QTW)T9P +GHZ)YV7 +W7Z)M3Y +5FK)NWC +97X)36T +G7X)K5R +GLP)XQF +WQH)ZM7 +8YP)KF6 +WNB)WG1 +W21)1TQ +VBH)XM4 +CY5)3N6 +G1V)K1G +L2X)L9S +2CV)3LL +BKC)LC8 +R5P)JDL +JL3)T5B +HDY)FRM +XL2)F29 +8Y8)N86 +C8B)FDF +L3W)Z9L +WJ6)6FW +5HV)157 +DW9)1WX +C2B)JR2 +6HK)7GP +N86)971 +GZ6)KHJ +V4Z)376 +WT6)F4Q +H97)FP5 +M4L)MCT +D8G)BCQ +XPG)NP5 +8CG)GBD +6SD)6X3 +54L)1TP +N1W)MJD +ZXT)VXM +QH7)JN5 +S7H)4M5 +QSC)44B +19K)QLJ +951)25C +PJZ)W21 +X8F)X4F +CZW)SV8 +ZYJ)F5C +XNR)KPH +658)47Q +D66)3GD +ZGK)D65 +4ZT)YBT +3NR)K3P +WMD)HRP +VGN)554 +2GN)WH3 +8SX)DXJ +Z4M)MR9 +R1V)VDY +1D1)CRZ +CC5)MH1 +2NS)PXH +SLP)1FN +PTB)LYC +V4D)Z5M +Z2N)X77 +DR4)7KQ +646)98D +9PN)F21 +PB8)728 +WXT)4S9 +3YP)TGM +6PG)776 +9KY)T7C +5SS)LV1 +8HR)53Z +972)FZ2 +XJ8)9PN +6PB)Q35 +ZCR)42N +NNP)YPG +SL6)XL4 +1CG)YZJ +QKG)5GX +L94)HD8 +ZVH)GVJ +R93)3YL +4GC)2XH +FNJ)ZL5 +2LR)YBD +YDW)HMN +S8V)YRB +YV2)HS4 +6B6)6WZ +SVG)LB5 +DMQ)VWX +72Y)997 +MHY)3YY +JX9)XHT +MTV)DSB +413)6SD +DSB)25Q +9HF)BRG +B5W)P93 +9TB)XTP +JN3)6W2 +TFK)MKW +T49)4NY +742)MSJ +8F6)ZKW +TRQ)3JD +F2T)R8H +LQ4)GMJ +B9T)H46 +T2F)ZC2 +VC6)TJF +YDZ)R48 +RGG)974 +DTK)H4C +DTF)QCP +7KM)Z4C +GTS)MLJ +296)424 +664)H86 +2YP)ZYJ +V18)VC6 +7CS)SQH +DZS)3X8 +QYT)8HS +62Y)SQW +D8X)YXX +N2X)D3B +P84)6J2 +JPH)DZL +WM9)KWM +TM5)GM5 +W4X)YYR +TNG)LRP +1KP)ZQX +MZ9)72Y +WJZ)MPF +NP5)SQ3 +D66)5QS +H7H)ZCB +16T)V74 +X15)1WS +8NR)Y7N +237)DYP +N4Y)CGZ +Z8K)BYX +8KF)N6W +RF8)NMV +WFC)7XF +449)DDB +D49)X1H +TM8)78Q +G6N)73R +HGM)GD7 +F21)Y1R +TRC)5HH +N14)S73 +ZXT)BS5 +NG8)4L5 +8ZN)Q79 +4HJ)Q3T +837)NDT +1R7)R2K +77S)6YB +S7R)1XY +2VT)KNJ +WQ4)64D +M5Z)PVZ +RQN)8V9 +VVN)K2K +V2B)N3K +B17)7BX +1W5)LMT +1YW)X2J +XJC)XJF +P4W)4J1 +PRS)Q4P +BMM)QB5 +L7N)H29 +4W5)GKS +8WN)KH8 +N4R)39M +4NY)14W +19Q)ZG9 +W6W)J8C +PWZ)4RW +8F3)JBW +BC8)F4N +QG8)VDP +YG1)GBY +KRM)WJZ +4HL)2TH +W1V)FMT +1BL)NC2 +RTN)R6C +QLJ)PLT +SQH)93Y +KM7)9G2 +5Z3)JY8 +WB2)YSP +3S1)4W5 +5BH)SXV +28Q)5Q7 +PDZ)XD1 +D79)WHF +6BJ)DQT +5F8)C29 +46R)XNR +NC2)2Y8 +T5B)863 +TJF)PDM +L47)5QW +F59)JX9 +RK6)QG8 +GD7)RWP +863)7DK +97R)LJF +6N7)X32 +WLZ)XDM +RXH)79K +WG1)NQW +BNR)1P5 +ZXV)QQF +ZJX)GSZ +X2C)L5L +NVC)L2G +T1F)FK2 +GGZ)KH3 +TZC)R9K +157)FRV +3CX)Z1J +NS1)BGG +MFW)36X +DW3)C53 +88H)LP4 +FX4)F4M +676)7BB +9TR)Q3H +P5H)Z1H +LB1)XBR +SWS)FLP +4S4)QMC +KNW)5LZ +3PR)TVL +JYK)46F +ZM7)Z6T +Q99)427 +5R1)MYP +3TZ)YHB +QPD)L6V +HB8)K7P +2W2)ZFX +BS3)GWH +953)S2C +1BC)WKC +S7X)9PL +1RQ)KLD +1XY)JRV +D37)SF5 +PXD)P2C +4L4)CVV +MYP)2VZ +WPW)SFQ +N6H)8D7 +8B7)9RM +297)Q93 +LNG)R64 +BXB)NSR +DKC)MTV +6C1)81V +75N)21C +XY7)THS +BRG)YY2 +F37)RMV +831)LYP +M1P)GZ6 +ZXD)NR9 +6G1)35R +H2V)51V +Q9F)RRD +FXW)3XX +ZV3)CDP +JC5)JGH +Y73)KFX +V6G)1W5 +7BB)DR7 +RN7)56M +3GV)8X9 +HMM)41C +JK4)V1D +MFV)2J4 +QQW)H62 +N1R)CCC +B5T)3GV +G8D)8QM +JNB)Z75 +8D7)ST5 +JXX)C1B +G5Y)Y92 +G46)DW4 +3CQ)R9L +FR9)Q83 +N6Q)JR4 +ZG2)S4Z +JDC)NCF +ZLX)2XW +JJD)QLN +YY2)FJ5 +Z3P)W7C +LSB)N68 +64D)8BL +PR9)J67 +N6X)M2F +SQ3)XZ7 +MKW)KVM +L61)PL4 +R2Z)2BF +HGM)KQK +222)RJQ +4LC)PY4 +54C)N14 +MLR)Z7Z +BBD)W1V +JK1)32M +SY1)3S1 +65N)3TK +1X9)4HQ +6F3)H6H +489)GFB +Y86)52L +HN7)R1G +48K)5MC +4P3)Z6L +CHT)8R9 +3M8)HKP +RK6)PP4 +X77)V4D +YDR)LCG +DZP)3CY +75T)TKM +ZFK)5LQ +6R6)8NV +TVL)RHW +HMN)BNR +PG2)VN1 +FVQ)SQ5 +1HF)W5X +WVY)TGX +VYF)2N1 +BJS)LTJ +72V)GCC +8NV)BS3 +ZL5)P1H +3KR)69D +CZS)8WW +4N2)72G +KK2)JXX +5Q7)KPZ +4QP)HYV +1SY)V7H +CN4)JTP +9TC)SVG +K7P)T6S +QFQ)999 +NGN)QKG +BHR)DR4 +TGX)XPG +DY3)YG1 +M5Z)PHZ +KBQ)HVY +9D2)N5J +GMF)4LZ +1P8)BFN +GBY)KY4 +49M)LWB +FNZ)FFS +JL3)V2H +LB5)7FK +PM5)1BL +PHZ)LH8 +NCF)YNR +HSK)W6W +5RJ)C95 +RPK)ZRK +Y34)54N +5QW)TZ5 +KGJ)43X +P2V)Q9T +NQZ)L7W +WP4)S29 +J3S)C9G +5C2)TX5 +3PM)PK2 +3GD)393 +CCD)3Z9 +QKQ)PB8 +FCN)LRS +FQ4)M3T +45B)B1T +NPJ)MK3 +KGD)JJP +F5Y)JKZ +C6D)HSK +TR9)7SS +2TX)H73 +NFV)X5D +C2V)43T +M6T)KPS +PK2)1CG +TP1)N4Y +1D5)D9Z +MTR)97R +3TK)X3W +R7T)3VC +PHP)1LV +5GB)2H5 +YC1)24X +S5H)W79 +FQS)JVF +DML)6F3 +Z75)LXP +DMJ)29G +54N)GSS +RWP)D79 +VBV)XWX +VST)CMS +GZ2)676 +N72)FP3 +792)ZJX +H73)J17 +M8N)WQ4 +H6X)L5G +3VC)LBC +YBT)YR2 +LYC)4GX +3VP)17F +F5Y)9ZY +8LD)BCM +7JR)X45 +MV8)FY7 +JN6)31R +MZ5)CVK +239)S7Y +DJ3)S7H +RVK)6HK +G85)WR5 +LKF)TZG +SQ5)NP4 +HN8)H53 +CTW)MCJ +8ZV)6YF +2RQ)SR3 +MRR)Z4P +WQ3)TYW +6SW)L2J +HFC)CTH +N5M)1TK +757)RDF +R5Z)MHY +NW9)V3P +K3P)PWN +GD7)GDL +B2J)FN2 +BRJ)GK8 +S62)3NT +9BH)38R +KQK)WXW +2LS)T8V +4J1)5WT +7J5)H3D +W1B)F72 +F4N)NFK +QCP)4HJ +DWH)V5B +87N)XY7 +F13)LWC +7VH)67W +PMG)DY4 +JMC)WQ3 +6HY)PTT +YJ8)DML +9CM)DM1 +54J)DNJ +1Q6)8ST +CKW)XS3 +ZKW)JPL +111)YFN +H6W)R5Z +THS)X4J +DTM)PWZ +ZH5)8PG +JR4)Z24 +NCN)8HF +3BD)B8L +76R)LN4 +N3K)97M +JJG)N1H +5JW)P48 +YJS)XMP +4RW)T2Z +D65)DNY +KWM)ZGK +5FY)9BK +Y8J)7DR +5PJ)1YW +24L)PTB +XTR)PJZ +LLM)QSC +R6Z)V6W +H62)PQJ +HT7)V18 +6CP)S3M +WXW)N6J +GJX)F5Y +Q35)QY7 +3K8)F59 +8SX)SWS +B2R)6N7 +R8H)CRP +CGH)HFC +NWC)QKQ +P9D)BLW +NK3)YLD +CDP)2M4 +Q39)QB9 +F2J)X7D +J79)QHD +VXM)948 +X7D)GLP +NP4)Q37 +69H)K1C +FF1)65K +P7X)YDW +HTK)B6F +273)CTT +D25)164 +QGY)DXG +G46)BMM +QPQ)SZL +HM7)G7X +VMJ)J24 +5QS)RD6 +KVV)4CP +6W2)8KQ +1JP)PR9 +4B2)SF1 +FX4)NNP +2N7)ZRC +JQ8)N1W +LKD)83V +345)CJC +HVF)QYT +Y4H)7VH +5LR)4MJ +S2C)FSG +V5B)BBN +5X5)SJ1 +MKC)NPJ +BWL)F39 +VDZ)Z27 +7GP)YB3 +8R9)R3N +SQW)GNG +3X8)V2B +D89)SM1 +Z4P)RSN +YB3)5LR +V4C)1JP +FGH)FF1 +GKS)R69 +M5V)H4X +3CY)KXM +G4S)D5H +12P)1YK +3Y2)R1V +KTZ)DQW +KD3)L2L +KSL)F13 +R3Z)JKT +G9Q)1D1 +2J4)5DZ +X3V)MM8 +Z7Y)1BC +G1J)G4S +W4X)LFX +YJ6)JMV +FP5)KN7 +PCQ)8HR +FN2)W8G +31P)WFB +YXX)CYB +NXY)77B +NCK)Z8K +VPX)3TG +CN3)JY5 +HXS)WQF +FK3)DZS +WFT)9DP +XZ5)F1L +639)T81 +R26)PCQ +2VZ)YYD +4S9)1PZ +HVY)V4P +K55)K8N +2Y8)WMD +69T)24L +MHH)SRP +WPS)YWV +9PL)NHB +D3B)KDT +SHT)GJN +42N)6MG +K9F)YDT +N2R)FVQ +F3Q)296 +YML)8XQ +6YF)B9B +R13)Y64 +DNJ)DKW +H44)ZTP +1Q4)5JW +RLM)BRJ +LMJ)8HY +CL4)LF1 +6GW)TMM +VTP)JWQ +TQL)G52 +3QN)VWR +BFN)VPX +T39)TSK +Z1J)S3R +F7V)XBX +VNC)LW7 +WM8)788 +HBD)K9F +JQL)JGJ +3SV)WVN +DM1)297 +VHQ)467 +PVJ)12P +3GH)2M6 +6MG)KD3 +1NW)4GC +VTJ)FKC +Q8H)P86 +5QW)BXB +ML7)V61 +94V)NK3 +XM4)TML +V2P)5Y3 +CR6)JKG +7LG)S9W +8TX)V6G +2JY)ZG2 +DVR)57Z +VN1)Z2R +ZC3)N2C +SB6)RPW +58W)1ZX +VFP)X6C +JQN)ZC3 +53Z)LQM +KWL)TP1 +HKP)4BW +S9T)Q19 +K2K)WD5 +WLM)YV4 +SFQ)4R1 +6KP)CTQ +V3P)XDC +CXM)MKC +31Y)Z62 +XHT)L7R +FK2)S52 +LVY)HFP +RJQ)KV1 +9S2)2LR +NZ8)DVR +JKH)PG2 +ZQX)3TP +81V)9CP +42B)WDJ +7PB)S68 +39C)6C1 +RR8)KSZ +XL4)RTN +3XH)RYQ +78Q)TP3 +GCD)5YQ +R29)LVG +Q3H)646 +TMM)ZLX +4B2)WDB +6N5)449 +3XL)NFV +CDL)6JS +TMC)B7C +R1W)ZWC +LH3)XJC +CHH)DFJ +1FN)MLQ +LMT)658 +HK8)BN1 +73R)1GP +ZQ6)6B4 +Z5X)D37 +YPG)GTK +8SM)VL6 +W5C)C6D +4BW)YS6 +DYP)2TX +R9K)BRN +KS9)L9J +XTJ)B25 +Y23)CHB +NHB)LG4 +L5L)7Z4 +DRK)9SL +ST5)NVC +2WH)DTM +1LV)SDM +788)256 +TW7)6TN +6FW)3CX +BG9)4Y9 +67W)JJ7 +2D4)FR9 +Z8K)F1J +LTJ)31P +R94)YJ8 +5PT)MPX +9SL)LGR +FKZ)9G6 +DR7)SGZ +SM7)9KY +TKH)8MF +VXB)4N2 +XQR)W38 +21F)HK8 +Y3H)XLM +DBW)M8W +11H)853 +1WS)66W +DW4)KNK +NQV)SVB +6ZZ)8YP +ZWC)5PL +PP4)3CQ +T8V)THM +J1J)HMK +CPB)Y7G +GYH)9BH +WPK)FMS +95D)FJW +HM7)CJJ +ZGS)LBV +HMK)BZC +2BF)DWS +LWC)85N +L3B)M1P +7C2)WG3 +3ZK)7BM +GDK)8XJ +LGJ)4R6 +DL1)JSJ +44B)6T9 +KFT)CXM +Q4P)STR +LBC)6ZD +GDK)STH +6MX)F2P +Y92)21F +6ZD)YYQ +HYK)58W +3YF)KNM +X9G)8K2 +QWN)JQN +17F)KTZ +CJ4)62Y +KQW)GMF +15N)S9T +G1V)GMK +M62)X6J +8V9)SVZ +WW8)DJ9 +FP3)28Q +PMX)F3Q +N3G)56Q +46F)ZN3 +D3M)S3P +D64)LVY +72Y)ZHM +LPH)WLM +HY1)HZL +L3D)QPD +Q9T)X6Z +6HG)3DJ +KBP)9TR +25C)9Z8 +ZR9)RYK +TJR)5C2 +56M)X4Y +TL2)5CL +939)ZVH +595)DTF +Z27)D25 +54T)MWM +ZBL)W4F +6JS)H7H +YWV)QWN +5D9)S5H +P96)KZ1 +TDQ)8JZ +NQW)VHQ +K9L)DMJ +H6W)8F6 +2TJ)8NJ +MCJ)T1P +M94)JNB +5ZJ)9BG +KCL)RS7 +X6J)ZGQ +PQQ)JN6 +S2K)5FK +K7N)X2Q +HTQ)GW4 +LTJ)RPK +DD2)8J5 +7NX)Z2N +6LR)R3D +YR2)7Y7 +JBS)CZW +ZRK)XJ8 +4L5)3XF +GJ2)FNZ +XTP)YCS +HRP)P5H +BRJ)J89 +RD6)ZR3 +YNZ)N8F +2N1)XGH +JDL)DLD +YLD)94B +ZNV)1Q6 +6TG)CR6 +GMW)KWL +TZR)698 +RDG)VGN +F1D)5X5 +3CT)6CH diff --git a/src/bin/day_5.rs b/src/bin/day_5.rs index e7539e1..a3cf869 100644 --- a/src/bin/day_5.rs +++ b/src/bin/day_5.rs @@ -11,17 +11,13 @@ use structopt::StructOpt; type Intcode = i32; #[derive(Debug, StructOpt)] -#[structopt(name = "Day 2: 1202 Program Alarm")] +#[structopt(name = "Day 5: Sunny with a Chance of Asteroids")] /// Executes an Intcode program /// /// The program is read from stdin as a series of comma-separated /// values. Newlines are ignored. /// -/// 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/5 for details. +/// See https://adventofcode.com/2019/day/5 for details. struct Opt { #[structopt(short = "i", long = "input")] input: Vec, diff --git a/src/bin/day_6.rs b/src/bin/day_6.rs new file mode 100644 index 0000000..a305a90 --- /dev/null +++ b/src/bin/day_6.rs @@ -0,0 +1,77 @@ +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 6: Universal Orbit Map")] +/// Counts the total number of direct and indirect orbits between planets. +/// +/// Input is read from stdin, one direct orbit per line, in the format +/// `A)B` (B is orbiting A). +/// +/// See https://adventofcode.com/2019/day/6 for details. +struct Opt {} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let orbits = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid orbit")); + + println!("{}", count_orbits(orbits)); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug)] +struct StrError { + str: String, +} + +impl fmt::Display for StrError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.str) + } +} +impl std::error::Error for StrError {} + +struct Orbit { + a: String, + b: String, +} + +impl FromStr for Orbit { + type Err = StrError; + + fn from_str(s: &str) -> Result { + match s.split(')').collect::>()[..] { + [a, b] => Ok(Orbit { + a: a.to_string(), + b: b.to_string(), + }), + _ => Err(StrError { + str: format!("{} is not a valid orbit description", s), + }), + } + } +} + +fn count_orbits(it: impl Iterator) -> usize { + // TODO + 0 +} -- cgit v1.2.3 From ad526abdd30e3495024b62e79f9fa0dc81cec613 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Wed, 11 Dec 2019 15:09:27 +0200 Subject: Day 6: Orbital maps --- src/bin/day_6.rs | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 182 insertions(+), 8 deletions(-) diff --git a/src/bin/day_6.rs b/src/bin/day_6.rs index a305a90..2af272c 100644 --- a/src/bin/day_6.rs +++ b/src/bin/day_6.rs @@ -1,31 +1,44 @@ +use rpds::vector::Vector; use std::fmt; use std::io; use std::io::prelude::*; +use std::iter::FromIterator; use std::process; use std::str::FromStr; use structopt::StructOpt; #[derive(Debug, StructOpt)] #[structopt(name = "Day 6: Universal Orbit Map")] -/// Counts the total number of direct and indirect orbits between planets. +/// Finds the minumum number of orbital transfers between two points. /// /// Input is read from stdin, one direct orbit per line, in the format /// `A)B` (B is orbiting A). /// /// See https://adventofcode.com/2019/day/6 for details. -struct Opt {} +struct Opt { + /// Debug checksum: Counts the total orbits + #[structopt(short = "d", long = "debug")] + debug: bool, +} fn main() { let stdin = io::stdin(); let opt = Opt::from_args(); - let orbits = stdin + let orbits: OrbitalMap = stdin .lock() .lines() .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid orbit")); + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid orbit")) + .collect(); + + // eprintln!("{:#?}", orbits); - println!("{}", count_orbits(orbits)); + if opt.debug { + println!("{}", orbits.total_orbits()); + } else { + println!("{}", orbits.orbital_transfers("YOU", "SAN")); + } } fn exit_on_failed_assertion(data: Result, message: &str) -> A { @@ -50,6 +63,7 @@ impl fmt::Display for StrError { } impl std::error::Error for StrError {} +#[derive(Debug, Clone)] struct Orbit { a: String, b: String, @@ -71,7 +85,167 @@ impl FromStr for Orbit { } } -fn count_orbits(it: impl Iterator) -> usize { - // TODO - 0 +#[derive(Clone, Debug)] +struct OrbitalMap { + id: String, + depth: usize, + orbiters: Vector, +} + +struct OrbitalMapBuilder { + orbiters: Vector, + inserted_orbits: Vector, + pending_orbits: Vector, +} + +impl FromIterator for OrbitalMap { + fn from_iter>(iter: T) -> Self { + iter.into_iter().collect::().build() + } +} + +impl FromIterator for OrbitalMapBuilder { + fn from_iter>(iter: T) -> Self { + OrbitalMapBuilder { + orbiters: Vector::new(), + inserted_orbits: Vector::new(), + pending_orbits: iter.into_iter().collect(), + } + } +} + +impl OrbitalMapBuilder { + fn build(self) -> OrbitalMap { + if self.pending_orbits.is_empty() { + OrbitalMap { + id: ROOT.into(), + depth: 0, + orbiters: self.orbiters, + } + } else { + self.pending_orbits + .into_iter() + .fold( + OrbitalMapBuilder { + pending_orbits: Vector::new(), + ..self + }, + |acc, next| acc.insert(&next), + ) + .build() + } + } + + fn insert(self, orbit: &Orbit) -> OrbitalMapBuilder { + if orbit.a == ROOT { + OrbitalMapBuilder { + orbiters: self.orbiters.push_back(OrbitalMap::new(orbit.b.clone(), 1)), + inserted_orbits: self.inserted_orbits.push_back(orbit.b.clone()), + ..self + } + } else if self.inserted_orbits.iter().any(|o| *o == orbit.a) { + OrbitalMapBuilder { + orbiters: self + .orbiters + .into_iter() + .map(|map| OrbitalMap::insert(map.clone(), orbit)) + .collect(), + inserted_orbits: self.inserted_orbits.push_back(orbit.b.clone()), + ..self + } + } else { + OrbitalMapBuilder { + pending_orbits: self.pending_orbits.push_back(orbit.clone()), + ..self + } + } + } +} + +const ROOT: &str = "COM"; + +impl OrbitalMap { + fn new(id: String, depth: usize) -> OrbitalMap { + OrbitalMap { + id, + depth, + orbiters: Vector::new(), + } + } + + fn insert(self, orbit: &Orbit) -> OrbitalMap { + if orbit.a == self.id { + if self.orbiters.iter().any(|o| o.id == orbit.b) { + self + } else { + OrbitalMap { + orbiters: self + .orbiters + .push_back(OrbitalMap::new(orbit.b.clone(), self.depth + 1)), + ..self + } + } + } else { + OrbitalMap { + orbiters: self + .orbiters + .into_iter() + .map(|map| OrbitalMap::insert(map.clone(), orbit)) + .collect(), + ..self + } + } + } + + fn count_orbits(&self) -> usize { + self.orbiters.len() + + self + .orbiters + .iter() + .map(|o| o.count_orbits()) + .sum::() + } + + fn total_orbits(&self) -> usize { + self.count_orbits() + + self + .orbiters + .iter() + .map(|o| o.total_orbits()) + .sum::() + } + + fn find_depth(&self, id: &str) -> usize { + if self.id == id { + self.depth + } else { + // only the actual one will return non-zero from this + self.orbiters.iter().map(|o| o.find_depth(id)).sum() + } + } + + fn contains(&self, id: &str) -> bool { + self.id == id || self.orbiters.iter().any(|o| o.contains(id)) + } + + fn find_common_ancestor(&self, a: &str, b: &str) -> Option { + if !self.contains(a) || !self.contains(b) { + None + } else { + self.orbiters + .iter() + .flat_map(|o| o.find_common_ancestor(a, b)) + .next() + .or(Some(self.clone())) + } + } + + fn orbital_transfers(&self, from: &str, to: &str) -> usize { + self.find_depth(from) + self.find_depth(to) + - 2 * self + .find_common_ancestor(from, to) + .map(|o| o.depth) + .unwrap_or(0) + - 2 + } } -- cgit v1.2.3 From 003a62f1c38344c5a647170bd2472c4eab39cf75 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Wed, 11 Dec 2019 23:02:42 +0200 Subject: Intcode program into lib! It's shared code now. --- Cargo.lock | 18 ++-- Cargo.toml | 2 +- src/bin/day_2.rs | 155 +++++------------------------------ src/bin/day_4.rs | 4 - src/bin/day_5.rs | 235 +--------------------------------------------------- src/lib.rs | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 281 insertions(+), 379 deletions(-) create mode 100644 src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 127971b..a8be1c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,15 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "advent-of-code-2019" +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aoc2019" version = "0.1.0" dependencies = [ "derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -10,14 +18,6 @@ dependencies = [ "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "archery" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 937d8e7..cef1cae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "advent-of-code-2019" +name = "aoc2019" version = "0.1.0" authors = ["Justin Wernick "] edition = "2018" diff --git a/src/bin/day_2.rs b/src/bin/day_2.rs index 172a89a..ce8fcaa 100644 --- a/src/bin/day_2.rs +++ b/src/bin/day_2.rs @@ -1,15 +1,9 @@ -use im::vector::Vector; -use std::fmt; +use aoc2019::*; use std::io; use std::io::prelude::*; -use std::iter; -use std::iter::FromIterator; -use std::iter::IntoIterator; use std::process; use structopt::StructOpt; -type Intcode = u32; - #[derive(Debug, StructOpt)] #[structopt(name = "Day 2: 1202 Program Alarm")] /// Executes an Intcode program @@ -36,7 +30,7 @@ fn main() { let stdin = io::stdin(); let opt = Opt::from_args(); - let program: Program = stdin + let program: IntcodeProgram = stdin .lock() .split(b',') .map(|x| exit_on_failed_assertion(x, "Error reading input")) @@ -47,14 +41,14 @@ fn main() { match (opt.noun, opt.verb, opt.output) { (Some(noun), Some(verb), _) => { let result = exit_on_failed_assertion( - program.set_input(noun, verb).execute(), + program.with_noun_verb_input(noun, verb).execute(), "Program errored", ); println!("{}", result); } (_, _, Some(output)) => { let (noun, verb) = - exit_on_failed_assertion(program.find_input(output), "Program errored"); + exit_on_failed_assertion(find_input(&program, output), "Program errored"); println!("({}, {})", noun, verb); } (None, None, None) => { @@ -78,127 +72,22 @@ fn exit_on_failed_assertion(data: Result, message } } -#[derive(Debug, Clone)] -struct Program { - program_counter: usize, - error: bool, - halted: bool, - codes: Vector, -} - -impl FromIterator for Program { - fn from_iter>(iter: I) -> Self { - Program { - program_counter: 0, - error: false, - halted: false, - codes: iter.into_iter().collect(), - } - } -} - -impl Program { - fn set_input(&self, noun: Intcode, verb: Intcode) -> Program { - Program { - codes: self.codes.update(1, noun).update(2, verb), - ..self.clone() - } - } - - fn find_input(&self, output: Intcode) -> Result<(Intcode, Intcode), ProgramError> { - (0..99) - .flat_map(|noun| (0..99).map(move |verb| (noun, verb))) - .map(|(noun, verb)| (noun, verb, self.set_input(noun, verb).execute())) - .find(|(_noun, _verb, out)| *out == Ok(output)) - .map(|(noun, verb, _out)| Ok((noun, verb))) - .unwrap_or(Err(ProgramError)) - } - - fn execute(&self) -> Result { - self.run_to_termination().into_result() - } - - fn into_result(&self) -> Result { - if self.error { - Err(ProgramError) - } else { - Ok(self.codes.head().unwrap().clone()) - } - } - - fn run_to_termination(&self) -> Program { - iter::successors(Some(self.clone()), |p| Some(Program::next(&p))) - .find(|p| p.halted) - .unwrap() // successors doesn't terminate, so this will never be none. - } - - fn next(&self) -> Program { - //eprintln!("{:?}", self); - match self.codes.get(self.program_counter) { - Some(1) => self.add(), - Some(2) => self.multiply(), - Some(99) => self.halt(), - Some(_) => self.error(), - None => self.error(), - } - } - - fn add(&self) -> Program { - match (self.get_deref(1), self.get_deref(2), self.get(3)) { - (Some(in1), Some(in2), Some(out)) => Program { - program_counter: self.program_counter + 4, - codes: self.codes.update(out as usize, in1 + in2), - ..self.clone() - }, - _ => self.error(), - } - } - - fn multiply(&self) -> Program { - match (self.get_deref(1), self.get_deref(2), self.get(3)) { - (Some(in1), Some(in2), Some(out)) => Program { - program_counter: self.program_counter + 4, - codes: self.codes.update(out as usize, in1 * in2), - ..self.clone() - }, - _ => self.error(), - } - } - - fn halt(&self) -> Program { - Program { - halted: true, - ..self.clone() - } - } - - fn error(&self) -> Program { - Program { - halted: true, - error: true, - ..self.clone() - } - } - - fn get(&self, pointer_offset: usize) -> Option { - self.codes - .get(self.program_counter + pointer_offset) - .cloned() - } - - fn get_deref(&self, pointer_offset: usize) -> Option { - self.get(pointer_offset) - .and_then(|r| self.codes.get(r as usize)) - .cloned() - } -} - -#[derive(Debug, PartialEq)] -struct ProgramError; - -impl fmt::Display for ProgramError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Unknown error") - } +fn find_input( + program: &IntcodeProgram, + output: Intcode, +) -> Result<(Intcode, Intcode), IntcodeProgramError> { + (0..99) + .flat_map(|noun| (0..99).map(move |verb| (noun, verb))) + .map(|(noun, verb)| { + ( + noun, + verb, + program + .with_noun_verb_input(noun, verb) + .execute_returning_memory_0(), + ) + }) + .find(|(_noun, _verb, out)| *out == Ok(Some(output))) + .map(|(noun, verb, _out)| Ok((noun, verb))) + .unwrap_or(Err(IntcodeProgramError)) } -impl std::error::Error for ProgramError {} diff --git a/src/bin/day_4.rs b/src/bin/day_4.rs index 3cb8d38..d7d6b69 100644 --- a/src/bin/day_4.rs +++ b/src/bin/day_4.rs @@ -1,6 +1,3 @@ -use std::io; -use std::io::prelude::*; - use structopt::StructOpt; #[derive(Debug, StructOpt)] @@ -17,7 +14,6 @@ struct Opt { } fn main() { - let stdin = io::stdin(); let opt = Opt::from_args(); println!( diff --git a/src/bin/day_5.rs b/src/bin/day_5.rs index a3cf869..07f7af8 100644 --- a/src/bin/day_5.rs +++ b/src/bin/day_5.rs @@ -1,15 +1,9 @@ -use rpds::{list::List, vector::Vector}; -use std::fmt; +use aoc2019::*; use std::io; use std::io::prelude::*; -use std::iter; -use std::iter::FromIterator; -use std::iter::IntoIterator; use std::process; use structopt::StructOpt; -type Intcode = i32; - #[derive(Debug, StructOpt)] #[structopt(name = "Day 5: Sunny with a Chance of Asteroids")] /// Executes an Intcode program @@ -27,13 +21,13 @@ fn main() { let stdin = io::stdin(); let opt = Opt::from_args(); - let program: Program = stdin + 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::() + .collect::() .with_input(opt.input.into_iter().collect()); let result = exit_on_failed_assertion(program.execute(), "Program errored"); @@ -49,226 +43,3 @@ fn exit_on_failed_assertion(data: Result, message } } } - -#[derive(Debug, Clone)] -struct Program { - instruction_pointer: usize, - error: bool, - halted: bool, - memory: Vector, - input: List, - output: Vector, -} - -impl FromIterator for Program { - fn from_iter>(iter: I) -> Self { - Program { - instruction_pointer: 0, - error: false, - halted: false, - memory: iter.into_iter().collect(), - input: List::new(), - output: Vector::new(), - } - } -} - -impl Program { - fn with_input(&self, input: List) -> Program { - Program { - input, - ..self.clone() - } - } - - fn with_instruction_pointer(&self, instruction_pointer: usize) -> Program { - Program { - instruction_pointer, - ..self.clone() - } - } - - fn with_instruction_pointer_offset(&self, offset: usize) -> Program { - Program { - instruction_pointer: self.instruction_pointer + offset, - ..self.clone() - } - } - - fn with_memory_set(&self, address: usize, value: Intcode) -> Program { - self.memory - .set(address, value) - .map(|memory| Program { - memory, - ..self.clone() - }) - .unwrap_or(self.error()) - } - - fn with_input_consumed(&self) -> Program { - self.input - .drop_first() - .map(|input| Program { - input, - ..self.clone() - }) - .unwrap_or(self.error()) - } - - fn with_output(&self, print: Intcode) -> Program { - Program { - output: self.output.push_back(print), - ..self.clone() - } - } - - fn execute(&self) -> Result, ProgramError> { - self.run_to_termination().into_result() - } - - fn into_result(&self) -> Result, ProgramError> { - if self.error { - Err(ProgramError) - } else { - Ok(self.output.clone()) - } - } - - fn run_to_termination(&self) -> Program { - iter::successors(Some(self.clone()), |p| Some(Program::next(&p))) - .find(|p| p.halted) - .unwrap() // successors doesn't terminate, so this will never be none. - } - - fn next(&self) -> Program { - //eprintln!("{:?}", self); - self.memory - .get(self.instruction_pointer) - .map(|&opcode| match opcode % 100 { - 1 => self.add(opcode), - 2 => self.multiply(opcode), - 3 => self.input(opcode), - 4 => self.output(opcode), - 5 => self.jump_if_true(opcode), - 6 => self.jump_if_false(opcode), - 7 => self.less_than(opcode), - 8 => self.equals(opcode), - 99 => self.halt(), - _ => self.error(), - }) - .unwrap_or(self.error()) - } - - fn add(&self, mode: Intcode) -> Program { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, in1 + in2), - _ => self.error(), - } - } - - fn multiply(&self, mode: Intcode) -> Program { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, in1 * in2), - _ => self.error(), - } - } - - fn input(&self, _mode: Intcode) -> Program { - match (self.input.first().cloned(), self.get_immediate(1)) { - (Some(input), Some(out)) => self - .with_instruction_pointer_offset(2) - .with_memory_set(out as usize, input) - .with_input_consumed(), - _ => self.error(), - } - } - - fn output(&self, mode: Intcode) -> Program { - match self.get(1, mode) { - Some(print) => self.with_instruction_pointer_offset(2).with_output(print), - _ => self.error(), - } - } - - fn jump_if_true(&self, mode: Intcode) -> Program { - match (self.get(1, mode), self.get(2, mode)) { - (Some(pred), Some(to)) if pred != 0 => self.with_instruction_pointer(to as usize), - (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), - _ => self.error(), - } - } - fn jump_if_false(&self, mode: Intcode) -> Program { - match (self.get(1, mode), self.get(2, mode)) { - (Some(pred), Some(to)) if pred == 0 => self.with_instruction_pointer(to as usize), - (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), - _ => self.error(), - } - } - - fn less_than(&self, mode: Intcode) -> Program { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, if in1 < in2 { 1 } else { 0 }), - _ => self.error(), - } - } - - fn equals(&self, mode: Intcode) -> Program { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, if in1 == in2 { 1 } else { 0 }), - _ => self.error(), - } - } - - fn halt(&self) -> Program { - Program { - halted: true, - ..self.clone() - } - } - - fn error(&self) -> Program { - Program { - halted: true, - error: true, - ..self.clone() - } - } - - fn get(&self, pointer_offset: usize, mode: Intcode) -> Option { - match mode / (10 as Intcode).pow(pointer_offset as u32 + 1) % 10 { - 0 => self.get_position(pointer_offset), - 1 => self.get_immediate(pointer_offset), - _ => None, - } - } - - fn get_immediate(&self, pointer_offset: usize) -> Option { - self.memory - .get(self.instruction_pointer + pointer_offset) - .cloned() - } - - fn get_position(&self, pointer_offset: usize) -> Option { - self.get_immediate(pointer_offset) - .and_then(|r| self.memory.get(r as usize)) - .cloned() - } -} - -#[derive(Debug, PartialEq)] -struct ProgramError; - -impl fmt::Display for ProgramError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Unknown error") - } -} -impl std::error::Error for ProgramError {} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..2591a54 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,246 @@ +use rpds::{list::List, vector::Vector}; +use std::fmt; +use std::iter; +use std::iter::FromIterator; +use std::iter::IntoIterator; + +pub type Intcode = i32; + +#[derive(Debug, Clone)] +pub struct IntcodeProgram { + instruction_pointer: usize, + error: bool, + halted: bool, + memory: Vector, + input: List, + output: Vector, +} + +impl FromIterator for IntcodeProgram { + fn from_iter>(iter: I) -> Self { + IntcodeProgram { + instruction_pointer: 0, + error: false, + halted: false, + memory: iter.into_iter().collect(), + input: List::new(), + output: Vector::new(), + } + } +} + +impl IntcodeProgram { + pub fn with_noun_verb_input(&self, noun: Intcode, verb: Intcode) -> IntcodeProgram { + self.with_memory_set(1, noun).with_memory_set(2, verb) + } + + pub fn with_input(&self, input: List) -> IntcodeProgram { + IntcodeProgram { + input, + ..self.clone() + } + } + + pub fn execute(&self) -> Result, IntcodeProgramError> { + self.run_to_termination().output_into_result() + } + + pub fn execute_returning_memory_0(&self) -> Result, IntcodeProgramError> { + self.run_to_termination().memory_0_into_result() + } + + fn with_instruction_pointer(&self, instruction_pointer: usize) -> IntcodeProgram { + IntcodeProgram { + instruction_pointer, + ..self.clone() + } + } + + fn with_instruction_pointer_offset(&self, offset: usize) -> IntcodeProgram { + IntcodeProgram { + instruction_pointer: self.instruction_pointer + offset, + ..self.clone() + } + } + + fn with_memory_set(&self, address: usize, value: Intcode) -> IntcodeProgram { + self.memory + .set(address, value) + .map(|memory| IntcodeProgram { + memory, + ..self.clone() + }) + .unwrap_or(self.error()) + } + + fn with_input_consumed(&self) -> IntcodeProgram { + self.input + .drop_first() + .map(|input| IntcodeProgram { + input, + ..self.clone() + }) + .unwrap_or(self.error()) + } + + fn with_output(&self, print: Intcode) -> IntcodeProgram { + IntcodeProgram { + output: self.output.push_back(print), + ..self.clone() + } + } + + fn output_into_result(&self) -> Result, IntcodeProgramError> { + if self.error { + Err(IntcodeProgramError) + } else { + Ok(self.output.clone()) + } + } + + fn memory_0_into_result(&self) -> Result, IntcodeProgramError> { + if self.error { + Err(IntcodeProgramError) + } else { + Ok(self.memory.get(0).cloned()) + } + } + + fn run_to_termination(&self) -> IntcodeProgram { + iter::successors(Some(self.clone()), |p| Some(IntcodeProgram::next(&p))) + .find(|p| p.halted) + .unwrap() // successors doesn't terminate, so this will never be none. + } + + fn next(&self) -> IntcodeProgram { + //eprintln!("{:?}", self); + self.memory + .get(self.instruction_pointer) + .map(|&opcode| match opcode % 100 { + 1 => self.add(opcode), + 2 => self.multiply(opcode), + 3 => self.input(opcode), + 4 => self.output(opcode), + 5 => self.jump_if_true(opcode), + 6 => self.jump_if_false(opcode), + 7 => self.less_than(opcode), + 8 => self.equals(opcode), + 99 => self.halt(), + _ => self.error(), + }) + .unwrap_or(self.error()) + } + + fn add(&self, mode: Intcode) -> IntcodeProgram { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, in1 + in2), + _ => self.error(), + } + } + + fn multiply(&self, mode: Intcode) -> IntcodeProgram { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, in1 * in2), + _ => self.error(), + } + } + + fn input(&self, _mode: Intcode) -> IntcodeProgram { + match (self.input.first().cloned(), self.get_immediate(1)) { + (Some(input), Some(out)) => self + .with_instruction_pointer_offset(2) + .with_memory_set(out as usize, input) + .with_input_consumed(), + _ => self.error(), + } + } + + fn output(&self, mode: Intcode) -> IntcodeProgram { + match self.get(1, mode) { + Some(print) => self.with_instruction_pointer_offset(2).with_output(print), + _ => self.error(), + } + } + + fn jump_if_true(&self, mode: Intcode) -> IntcodeProgram { + match (self.get(1, mode), self.get(2, mode)) { + (Some(pred), Some(to)) if pred != 0 => self.with_instruction_pointer(to as usize), + (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), + _ => self.error(), + } + } + fn jump_if_false(&self, mode: Intcode) -> IntcodeProgram { + match (self.get(1, mode), self.get(2, mode)) { + (Some(pred), Some(to)) if pred == 0 => self.with_instruction_pointer(to as usize), + (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), + _ => self.error(), + } + } + + fn less_than(&self, mode: Intcode) -> IntcodeProgram { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, if in1 < in2 { 1 } else { 0 }), + _ => self.error(), + } + } + + fn equals(&self, mode: Intcode) -> IntcodeProgram { + match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + (Some(in1), Some(in2), Some(out)) => self + .with_instruction_pointer_offset(4) + .with_memory_set(out as usize, if in1 == in2 { 1 } else { 0 }), + _ => self.error(), + } + } + + fn halt(&self) -> IntcodeProgram { + IntcodeProgram { + halted: true, + ..self.clone() + } + } + + fn error(&self) -> IntcodeProgram { + IntcodeProgram { + halted: true, + error: true, + ..self.clone() + } + } + + fn get(&self, pointer_offset: usize, mode: Intcode) -> Option { + match mode / (10 as Intcode).pow(pointer_offset as u32 + 1) % 10 { + 0 => self.get_position(pointer_offset), + 1 => self.get_immediate(pointer_offset), + _ => None, + } + } + + fn get_immediate(&self, pointer_offset: usize) -> Option { + self.memory + .get(self.instruction_pointer + pointer_offset) + .cloned() + } + + fn get_position(&self, pointer_offset: usize) -> Option { + self.get_immediate(pointer_offset) + .and_then(|r| self.memory.get(r as usize)) + .cloned() + } +} + +#[derive(Debug, PartialEq)] +pub struct IntcodeProgramError; + +impl fmt::Display for IntcodeProgramError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Unknown error") + } +} +impl std::error::Error for IntcodeProgramError {} -- cgit v1.2.3 From 22fc69709731ba039f321c48670584c50f48d9ab Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 12 Dec 2019 00:37:55 +0200 Subject: Day 7 part 1 (it's dirty and doesn't solve part 2 yet) --- Cargo.lock | 1 + Cargo.toml | 3 +- inputs/day_7.txt | 1 + src/bin/day_7.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 inputs/day_7.txt create mode 100644 src/bin/day_7.rs 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::(), "Invalid number")) + .collect::(); + + let result = exit_on_failed_assertion(find_max_power(&program), "Program errored"); + println!("{}", result); +} + +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_max_power(program: &IntcodeProgram) -> Result { + PhaseSetting::all() + .map(|phase| run_amplifiers(program, phase)) + .collect::, _>>() + .map(|powers| powers.into_iter().max().unwrap_or(0)) +} + +fn run_amplifiers( + program: &IntcodeProgram, + phase: PhaseSetting, +) -> Result { + 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 { + 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 { + (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))) + } +} -- cgit v1.2.3 From 66634e6213b81092880d0c9769d6bd52f09ec7a2 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Fri, 13 Dec 2019 00:33:46 +0200 Subject: Did the feedback loop for the amplifier circuit --- src/bin/day_7.rs | 150 ++++++++++++++++++++++++++++++++++++++++++------------- src/lib.rs | 62 +++++++++++++++++++---- 2 files changed, 167 insertions(+), 45 deletions(-) diff --git a/src/bin/day_7.rs b/src/bin/day_7.rs index d412734..0abf215 100644 --- a/src/bin/day_7.rs +++ b/src/bin/day_7.rs @@ -1,8 +1,10 @@ use aoc2019::*; use rpds::list; use rpds::list::List; +use rpds::vector::Vector; use std::io; use std::io::prelude::*; +use std::iter; use std::process; use structopt::StructOpt; @@ -28,7 +30,10 @@ fn main() { .map(|x| exit_on_failed_assertion(x.trim().parse::(), "Invalid number")) .collect::(); - let result = exit_on_failed_assertion(find_max_power(&program), "Program errored"); + let result = exit_on_failed_assertion( + find_max_power(&program, opt.feedback_loop_mode), + "Program errored", + ); println!("{}", result); } @@ -42,50 +47,127 @@ fn exit_on_failed_assertion(data: Result, message } } -fn find_max_power(program: &IntcodeProgram) -> Result { - PhaseSetting::all() - .map(|phase| run_amplifiers(program, phase)) - .collect::, _>>() - .map(|powers| powers.into_iter().max().unwrap_or(0)) -} - -fn run_amplifiers( - program: &IntcodeProgram, - phase: PhaseSetting, -) -> Result { - 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( +fn find_max_power( program: &IntcodeProgram, - phase: PhaseSetting, - n: usize, - input: Intcode, + feedback_loop_mode: bool, ) -> Result { - program - .with_input(list![phase.0[n], input]) - .execute() - .and_then(|output_vec| output_vec.get(0).cloned().ok_or(IntcodeProgramError)) + PhaseSetting::all(feedback_loop_mode) + .map(|phase| AmplifierArray::new(program, phase).execute()) + .collect::, _>>() + .map(|powers| powers.into_iter().max().unwrap_or(0)) } #[derive(Debug, Clone, Copy)] struct PhaseSetting([Intcode; 5]); impl PhaseSetting { - fn all() -> impl Iterator { - (0..=4) + fn all(feedback_loop_mode: bool) -> impl Iterator { + if feedback_loop_mode { + PhaseSetting::permute(5, 10) + } else { + PhaseSetting::permute(0, 5) + } + } + + fn permute(min: Intcode, max: Intcode) -> impl Iterator { + // This is an absolutely atrocious way to do the permutation, + // but luckily it's only 5 elements long. + (min..max) .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]))) + (min..max).flat_map(move |b| { + (min..max).flat_map(move |c| { + (min..max).flat_map(move |d| { + (min..max).map(move |e| PhaseSetting([a, b, c, d, e])) + }) }) }) }) - .filter(|phase| (0..=4).all(|x| phase.0.contains(&x))) + .filter(move |phase| (min..max).all(|x| phase.0.contains(&x))) + } +} + +#[derive(Debug, Clone)] +struct AmplifierArray { + amplifiers: Vector, +} + +impl AmplifierArray { + fn new(program: &IntcodeProgram, phase: PhaseSetting) -> AmplifierArray { + AmplifierArray { + amplifiers: (0..5) + .map(|n| AmplifierArray::new_amp(program, phase, n)) + .collect(), + } + } + + fn new_amp(program: &IntcodeProgram, phase: PhaseSetting, n: usize) -> IntcodeProgram { + if n == 0 { + program.with_input(list![phase.0[n], 0]) + } else { + program.with_input(list![phase.0[n]]) + } + } + + fn execute(&self) -> Result { + self.run_to_termination().output_into_result() + } + + fn run_to_termination(&self) -> AmplifierArray { + iter::successors(Some(self.clone()), |p| Some(p.next())) + .find(|p| p.is_terminated()) + .unwrap() // successors doesn't terminate, so this will never be none. + } + + fn output_into_result(&self) -> Result { + self.amplifiers + .first() + .and_then(|amp| amp.input.first().cloned()) + .ok_or(IntcodeProgramError) + } + + fn is_terminated(&self) -> bool { + self.amplifiers.last().map(|amp| amp.halted).unwrap_or(true) + } + + fn next(&self) -> AmplifierArray { + self.run_amplifiers().update_inputs() + } + + fn run_amplifiers(&self) -> AmplifierArray { + AmplifierArray { + amplifiers: self + .amplifiers + .iter() + .map(|amp| amp.run_to_termination_or_input()) + .collect(), + } + } + + fn update_inputs(&self) -> AmplifierArray { + AmplifierArray { + amplifiers: self + .amplifiers + .iter() + .fold( + ( + Vector::new(), + self.amplifiers + .last() + .map(|a| a.output.iter().cloned().collect::>()) + .unwrap_or(List::new()), + ), + |(amps, piped_input), next_amp| { + ( + amps.push_back( + next_amp + .with_additional_input(piped_input) + .with_cleared_output(), + ), + next_amp.output.iter().cloned().collect::>(), + ) + }, + ) + .0, + } } } diff --git a/src/lib.rs b/src/lib.rs index 2591a54..717505e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,11 +9,12 @@ pub type Intcode = i32; #[derive(Debug, Clone)] pub struct IntcodeProgram { instruction_pointer: usize, - error: bool, - halted: bool, + pub error: bool, + pub halted: bool, + pub awaiting_input: bool, memory: Vector, - input: List, - output: Vector, + pub input: List, + pub output: Vector, } impl FromIterator for IntcodeProgram { @@ -22,6 +23,7 @@ impl FromIterator for IntcodeProgram { instruction_pointer: 0, error: false, halted: false, + awaiting_input: false, memory: iter.into_iter().collect(), input: List::new(), output: Vector::new(), @@ -41,6 +43,20 @@ impl IntcodeProgram { } } + pub fn with_additional_input(&self, input: List) -> IntcodeProgram { + IntcodeProgram { + input: self.input.iter().chain(input.iter()).cloned().collect(), + ..self.clone() + } + } + + pub fn with_cleared_output(&self) -> IntcodeProgram { + IntcodeProgram { + output: Vector::new(), + ..self.clone() + } + } + pub fn execute(&self) -> Result, IntcodeProgramError> { self.run_to_termination().output_into_result() } @@ -49,6 +65,22 @@ impl IntcodeProgram { self.run_to_termination().memory_0_into_result() } + pub fn run_to_termination(&self) -> IntcodeProgram { + iter::successors(Some(self.clear_await_input()), |p| { + Some(IntcodeProgram::next(&p)) + }) + .find(|p| p.halted) + .unwrap() // successors doesn't terminate, so this will never be none. + } + + pub fn run_to_termination_or_input(&self) -> IntcodeProgram { + iter::successors(Some(self.clear_await_input()), |p| { + Some(IntcodeProgram::next(&p)) + }) + .find(|p| p.halted || p.awaiting_input) + .unwrap() + } + fn with_instruction_pointer(&self, instruction_pointer: usize) -> IntcodeProgram { IntcodeProgram { instruction_pointer, @@ -105,13 +137,6 @@ impl IntcodeProgram { Ok(self.memory.get(0).cloned()) } } - - fn run_to_termination(&self) -> IntcodeProgram { - iter::successors(Some(self.clone()), |p| Some(IntcodeProgram::next(&p))) - .find(|p| p.halted) - .unwrap() // successors doesn't terminate, so this will never be none. - } - fn next(&self) -> IntcodeProgram { //eprintln!("{:?}", self); self.memory @@ -155,6 +180,7 @@ impl IntcodeProgram { .with_instruction_pointer_offset(2) .with_memory_set(out as usize, input) .with_input_consumed(), + (None, Some(_out)) => self.await_input(), _ => self.error(), } } @@ -206,6 +232,20 @@ impl IntcodeProgram { } } + fn await_input(&self) -> IntcodeProgram { + IntcodeProgram { + awaiting_input: true, + ..self.clone() + } + } + + fn clear_await_input(&self) -> IntcodeProgram { + IntcodeProgram { + awaiting_input: false, + ..self.clone() + } + } + fn error(&self) -> IntcodeProgram { IntcodeProgram { halted: true, -- cgit v1.2.3 From 754a9a4e220b039770b12cb0803b0b0ad3133555 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Fri, 13 Dec 2019 21:43:18 +0200 Subject: Day 8, image processing --- inputs/day_8.txt | 1 + src/bin/day_8.rs | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 inputs/day_8.txt create mode 100644 src/bin/day_8.rs diff --git a/inputs/day_8.txt b/inputs/day_8.txt new file mode 100644 index 0000000..21110e8 --- /dev/null +++ b/inputs/day_8.txt @@ -0,0 +1 @@ +211202121222222222221222212222202022222222222122221220222222222222222222222202222222222222122121022222212222222222212212222222210222202212222222012222200222021222222222220222222222202222222222222022220221222222222222222222222222222222222222022022022222222222222222222212222222221222222202220222202222220202021222222222221222202222212222222222222122222220222222222222222222222222222222222222122220022222212222222222202222222222220222202212221222102222211202020222222222221222222222212222222222222022220221222222222222222222222212222222222222122022122222202222222222212202222222212222202212222222202222220222022222222222221222212222202022222222222222221220222222222222222222222212222222222222022122222222222222222222202202222222220222222202222222212222210002122222222222221222212222222022222222222122221221222222222222222212222202222222222222022220222222202222222222212222222222221222222222220222112222211012121222222222222222222222222221222222222122220222222222222222222212222212222222222222022120222222222222222222212202222222221222212202221222122222212122121222222222222222212222122022222222222222221220222222222222222212222212222220222222122021022222222222222222212202222222221222222202220222102222200212020222022222222222212222012221222222222122221221222222222222222212222202222222222222222121122222212222222222212212222222221222212222222222111222212022021222122222220222202222022022222222222122220221222222222222222202222222222222222222122120222222222222222222202212222222210222212212221222020222201222222222022222222222222222122222222222222022221220222222222222222202222212222222222222222222022222222222222222202222222222221222212202221222002222220202020222122222220222202222112221222222222022220222222222222222222222222212222220222222022120022222212222022222202202222222200222202202221222210222220022122222222222222222212222022021222222222222220221222222222222222202222202222221222222222020122222212220122222202212222222201222202212221222112222220002222222022222220222222222122121222222222022222221222222222222222212222202222201222222222120222222222221222222222202222222212222202222220222101222200212021222022222221222202222122222222222222222221220222222222222222222222212222210222222022022122222222220022222202202222222222222222222222222220222221022022222122222220222222222012020222220222122220221222222222222222212222212222212222222222220022222212222022222212222222222212222212212221222011222222012022222122222220222202222220122222222222122220221222222222222222222222212222221222222122020022222222222222222222222222202220222202212220222022222212102221222122222222222202222112021222222222022222220222222222222222222222222222202222222022120020222212221022222202202222212210222212202220222211222210102220222222222220222222222120122222222222022220220222222222222222222222222222202222222222222120222222220122222222202222202200222202222222222220222200012022222122222220222202222220122222222222122220222222222222222222202222212222220220222122122022222212222022222222222222202201222212212221222221222212122221222022222220222200222112022222222222222220020222222222222222202222202222220221222222020222222202221122222212212222212212222222212221222212222211012221222022222222222220222201121222220222022222021222222222222222212222222222200221222122220221222202220122222222202222222211222222202220222022222212002120222222222220222220222100222222221222022222122222222202222222212222212222221222222022121122222202222022222202202222212200222222202220222010222212102222222002222221222221222011022222222222022222120222222202222222222222212222210221222022221021222212220222222202212222212202222222202220222001222220012020222112222222222221222121122222220222122220020222222212222222212222212222220222222122022221222202220022222222202222222210222202202220222010222211022120222212222221222220222202120222221222122221122222222220222222202222202222210221222222221122222222220022222202212222202201222202212220222012222200212022222122222222222222222212222222222222122220121222222210222222202222212222201220222122121122222222222022222222222222212210222212212220222200222200012122222112222221222202222201220222222222222221221222222201222222212222222222210220222222122121222222221022222222222222212220222202212220222202222202012220222212222220222201222010121222220222222220020222222201222222212222212222220220222222122221222222221022222202202222202202222212222220222211222201112021222012222220222221222101121222220222222221121222222201222222212222202222022220222022221122222222222122222212222222222201222222222222222220222201202122222102222222222201222102220222222222122220222222222220222222222222202222211222222122120221222212221122222212202222202200222222222222222020222222222121222222222222222212222012021202222222022220021222222222222222202222222222200220222022221020222212220122222202222222222221222222212220212220222210122220222222222222222212222110222212220222222220021222222212222222222222212222001221222122020021222212222022222202202222212212222222202222212102222210022121222102222121222210222021121202221222122221022222222210222222222222202222001221222222121120212222220022222202212222202220222222212222212012222200022221222022222020222200222222122222221222022222122222222201222222202222202222110222222122221121222202221222222222202222222222222222202222212220222220202121222222222121222201222111221212221222022220120222222210222222202222212222202222222020021020202212222122222202212222202211222222202221212002222212122222222022222121222202222102121212221222022220022222202200222222212220222222211222222121221021222222221022222202222222222212222222202222212010222202102121222022222120222220222201021202222222022222222222222220222222212221212222200221222122221120222212221122222222222222202201222222212222212222222221222120222002222121222201222100021222221222222222120222212211222222222222202222001221222022020122210222221022222222212222222212222202222222212120222202022221222122202122222221222002221212222222022222222222202200222222212220222222111221222122221220210212221022222222202222212202222212212221222010222222102222222002220020222210222212120222222222022220022222202212222222222222212222002222222220121221210202221122222212212222222222222202202222202122222200222111222122220122222210222000020202221222022222221222222222222222202222212222211220222022220020212222220222222212212222222211222212212220202200222222102112222222222222222221222112021222221222222221222222222200222222202221222222212221022020220022220202222122222222202222210222222212202222202122222220112100222002200020222212222010120202220222022221020222212210222222202220202222011220220121121022022222221222222202212222222222222202222220222221222211012110222102221021222222222200220002222222022220121222212201222222202222212222212222221120220020121202222222222222202222222220222222212222202210222200022210222212220122222221222012220102220222222022221222212222222222202221212222021222022122222121012212222022222222222222200222222212212222212202222221102110222012212122222220222001222202221222222120021222212201222222212222222222011221120020221220111202220022222222202222201221222222222220202110222202012021222122220020222202222121220002222222122122122222222222222222212221212222220221122120020221110202222122222222212222212210222212112222222010222200112110222022222121222221222212020002220222222222121222202211222222212220202222222222220122120121011222221222222202202222222220222212102221222101222210222002222110221222202211222001021022222222022121220222212221222222222220222222012221121121021020121202220221222202212222001220222212112222202210222220212101222110211020222202222000220022222222122020222222222221222222222220222222022221122121121222002222221221222222202222210210222212212222202101222211102022222100220120212220222010020102220222222020222222222211222222202220222222221220121001022021110222221221222222222222011222222222022221202000222221022201222200221221010200222011220202220222022220220222212202222222222221222222212221220221220021210202221120222202012222112221222222022220202111222222102112222200220121110202222011020112221222222122101222212220222222202222202222101222222121122220001212221121222222202222220222222202112221222200212212112110222201201020101220222000220002221222022220011222212211222222202222202222012222122001122022210222220222222222022222222220222212102221222120202221202010222011201220010212222001221212220222122121100222222222222222212220212221001220221001120220221212221120222212002222010212222212222220202200212212112022222020220022001201222000020222222222122121002222202220222222212222202221200222220112120122211222222122222222212222012210222202212221212121212201202110222002200220211201222210022222220222122222010222222222222222222220212222122220222222122122200222221122222222012222221201222222112221212002212211022212222122211121222210222212222112222222022222211222220210222222222221222222102221221211022121110222222020222222012222201212222212202221212110222202102021222210211222210221222010020212021222022221021222200212222222222221202200111221121110122021020202221222222222202222022121222212012220212212212202212122222021220020120222222202122102220222122021211222201111222222222221212220101222022200022120002222222220222222002222022110222202202221222202222212202221222120220021210202222020122102020222022020102222220112022222202220202210100222122221122022202202222221222212012222110001222212202221212202212222212100222220211121101220222210021002122222022222222222212102222222202221222200002221020021022022002212222121222212112222100100212212112222202212222212002220220100211220102211222020021012120222022221222222211222022222202220212220102221021111020021201202220120222202222222012200212202102221212212202211022221222121212020221210222210100202222222122220212222201102022222222220212202000221222202222120212212221122222212102222111010222212122222202210212212002120221202221222002200222212020022221222022120000222210211122222202221212220012222022212020121120212222222222202112222111011202202022220202220212212002201220002212021002200222122222112221222122121222222210211222222222220222200111221020122122022121202220121222222022222220210212222022222222020222202022102221222202120112212222200112212020222122122111222212020222222202220212211101221222211221220120202220120222212102222120222222202102222222021202221122212222010210021122210222102120022220222122222210222202220122222202220222220001222020211220220020212220221022212222122010102212212222221202112222220002220221101212221021211222221200202021222222222012222221011222222222220222220222221120112221221012212220122222212022122122101222202022221212020212210022112221000220221102221222100120022221222022022001222210212022222222220222202220222222120121022002202221220222212012122200201202222202222222210212201012011221020221222212222222200220202122222022220102222222011222222212222222202012221221100221121212212222222122212112122222002202202112222222002212202212212221112220221111211222201000122121222122022020222201010222222202222212202221220122120120120120212221021222202012122021021212222112222212112210200122222220002212220112210222110021012022222222021021222212011122222222220202220110221020202121022212202221022022212212222101020222202202222222000222201202110221200222222010201212200221222022222222020000222201112222222220221212222012221120111220022102212221122122222112222012122222222122221202200222212122101221210210022001221222112122222122222122221111222212002222222210221212201120211021110120021201222222021022202022022101000222200022222212120220201212210221210222220222220212011221202220222222122000222210120022222220221202222021210020120120020221222221221122222122222202222222201022221210112212222122122220110202121112202222210022112022222122020122021210212222222011221222210010221222221022222121222221120122222122022012022202202012222222210200201002012221012221020200220202120211102222222222022110022202001122222112220212211120221222200221021020212220222122222112122201111202212102221220010200211002101221111211120121222212120102222022222222022000222212220022222021222212221012212122120021021100202222022222212012222002221222000002221212121201220222010222012210122002211202202201202020222222121101212202112122222212221102211011222120012221221210222221222122202122122212122202022102222202010221201002010221121210020102211222210220112021222122020221200210202222222200222122221200201222121122221112202222121022202022122001102222022112221220120222201212200221011200221212220202200211102020222022122212101221022022221122220112210220212220112222121012222222222222212012022201202212122212200200122210211122100222002210021201200222212202012021222222120112001220220122221102220012221201220221120002022011202221220022202212122210002202001202220212110222222002201221111222221220200212122022222220222222020120010211200022222212221212202110210222110000221120222220220222222102022122211222010222211221202202220112001222010211201201211222112002222220212222220112202221122222220101020022002211202221112210022212022220021120212202122122220222122001202222012201202102100221112210110120210212222111222222212022020111000222122022221202220002111220212121222222221020102222222222212222222222001222020022211221221200221012212220222202212101211222120010222121200022020200002210210222222102221022200220222020210212201101202221121021202122122220110212101100220220101202210202201220121200102211210212201122022020201022020000221202200122221011222012001022221022002211101122122221222120202202222222101212212201210220202211212102222222200200012220011212121100022222201122021212200201001122222022020012120011002222021201010021122221121022202122122110122222211021220200212202222222220221020200001011010202122210002020202022021012002202201222220011022110210112121221222112102000122221220220220012222102002202101112221211222210222222020022210210120112200222211111122021220122022002000211020022222010020022201021221121000100000202212221022021212112222202112212222222200221021200222102100121121221221010212202102200012220212120022212102222011022220220220211200121211220211001122222102221221020202202222010121212200100221202012222212112011222020210010010221212122200102022220221020002000212022122221202021122000112210021200010000210222220120121201122222021102212102111222201121202201202002020120200201212110202101010102022200121222211012221121122221000122021100210212222122211220212102221020122210202222110002212200011201200021201220022012110200222202010110002212220010120010022120110012200120022222122021212000212022122022010021101012221222020212102122120000212202002202202222222210012200102200200111220022112012202102021122021120011121200020122220001221102112201201020102122212202112220122122212222022110111222010201211210002212202112020020222212100211112122120200002020201020021202021200200022222010120111011000012120121101212002212222122121200022022212122202211001220201122201201012022011111200001112022002112002200220221121202120002212010122222010222121211010100220111112122101222222021021211212122121120212202000200210112220002211221002010102121110201000000011200112100002201220112102201101001200002222202202212002201221110202000102001202000200100102121000220100101111222110 diff --git a/src/bin/day_8.rs b/src/bin/day_8.rs new file mode 100644 index 0000000..0508e7c --- /dev/null +++ b/src/bin/day_8.rs @@ -0,0 +1,135 @@ +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 8: Space Image Format")] +/// Executes an Intcode program on 5 amplifiers, and finds the input that gives the max output +/// +/// See https://adventofcode.com/2019/day/8 for details. +struct Opt { + /// Rather than rendering the image, calculate and print its checksum + #[structopt(short = "c", long = "checksum")] + checksum_mode: bool, + #[structopt(short = "w", long = "width")] + width: u32, + #[structopt(short = "h", long = "height")] + height: u32, +} + +fn main() { + let opt = Opt::from_args(); + + let image: Image = { + let mut buffer = String::new(); + exit_on_failed_assertion( + io::stdin().read_to_string(&mut buffer), + "Error reading input", + ); + + Image::from_str(&buffer.trim(), opt.width, opt.height) + }; + + if opt.checksum_mode { + println!("{}", image.checksum()); + } else { + println!("{}", image); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug)] +struct Image { + width: u32, + height: u32, + layers: Vec, +} + +impl fmt::Display for Image { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.flatten() + .pixels + .chunks(self.width as usize) + .map(|line| { + line.iter() + .map(|c| write!(f, "{}", if *c == 0 { ' ' } else { '1' })) + .collect::() + .and_then(|_| writeln!(f)) + }) + .collect() + } +} + +impl Image { + fn from_str(s: &str, width: u32, height: u32) -> Image { + Image { + width, + height, + layers: s + .as_bytes() + .chunks((width * height) as usize) + .map(|chunk| ImageLayer::new(chunk)) + .collect(), + } + } + + fn checksum(&self) -> usize { + self.layers + .iter() + .min_by_key(|layer| layer.pixel_count(0)) + .map(|layer| layer.pixel_count(1) * layer.pixel_count(2)) + .unwrap_or(0) + } + + fn flatten(&self) -> ImageLayer { + self.layers + .iter() + .fold(ImageLayer::empty(self.width, self.height), |acc, next| { + ImageLayer { + pixels: acc + .pixels + .iter() + .zip(next.pixels.iter()) + .map(|(a, b)| if *a == 2 { *b } else { *a }) + .collect(), + } + }) + } +} + +#[derive(Debug)] +struct ImageLayer { + pixels: Vec, +} + +impl ImageLayer { + fn new(char_pixels: &[u8]) -> ImageLayer { + ImageLayer { + pixels: char_pixels + .iter() + .map(|c| c.overflowing_sub(b'0').0) + .collect(), + } + } + + fn empty(width: u32, height: u32) -> ImageLayer { + ImageLayer { + pixels: vec![2; (width * height) as usize], + } + } + + fn pixel_count(&self, value: u8) -> usize { + self.pixels.iter().filter(|p| **p == value).count() + } +} -- cgit v1.2.3 From 5c60610b768b98113ca8ca5e8f833fa42d5aa4cf Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sat, 14 Dec 2019 20:59:58 +0200 Subject: Intcode computer to use bigints and unlimited memory space! Also started a more complete error reporting scheme. --- Cargo.lock | 84 ++++++++++++++++++++++ Cargo.toml | 3 +- src/bin/day_2.rs | 17 +++-- src/bin/day_7.rs | 24 ++++--- src/lib.rs | 210 ++++++++++++++++++++++++++++++++++--------------------- 5 files changed, 238 insertions(+), 100 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30421cf..86f88f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,7 @@ 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)", + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -36,6 +37,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "1.2.1" @@ -99,6 +105,76 @@ name = "libc" version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-complex" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-error" version = "0.2.6" @@ -257,6 +333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d308d8fa3f687f7a7588fccc4812ed6914be09518232f00454693a7417273ad2" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" @@ -264,6 +341,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum im 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1f9b6540e530defef7f2df4ed330d45b739b10450548c74a9913f63ea1acc6b" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" +"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" diff --git a/Cargo.toml b/Cargo.toml index eb300fe..fc97025 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,5 @@ structopt = "0.3.5" derive_more = "0.99.2" im = "14.0.0" rpds = "0.7.0" -archery = "0.3.0" \ No newline at end of file +archery = "0.3.0" +num = "0.2" \ No newline at end of file diff --git a/src/bin/day_2.rs b/src/bin/day_2.rs index ce8fcaa..ba9e189 100644 --- a/src/bin/day_2.rs +++ b/src/bin/day_2.rs @@ -41,7 +41,9 @@ fn main() { 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(), + program + .with_noun_verb_input(noun, verb) + .execute_returning_memory_0(), "Program errored", ); println!("{}", result); @@ -52,7 +54,8 @@ fn main() { println!("({}, {})", noun, verb); } (None, None, None) => { - let result = exit_on_failed_assertion(program.execute(), "Program errored"); + let result = + exit_on_failed_assertion(program.execute_returning_memory_0(), "Program errored"); println!("{}", result); } _ => { @@ -77,17 +80,17 @@ fn find_input( output: Intcode, ) -> Result<(Intcode, Intcode), IntcodeProgramError> { (0..99) - .flat_map(|noun| (0..99).map(move |verb| (noun, verb))) + .flat_map(|noun| (0..99).map(move |verb| (Intcode::from(noun), Intcode::from(verb)))) .map(|(noun, verb)| { ( - noun, - verb, + noun.clone(), + verb.clone(), program .with_noun_verb_input(noun, verb) .execute_returning_memory_0(), ) }) - .find(|(_noun, _verb, out)| *out == Ok(Some(output))) + .find(|(_noun, _verb, out)| *out == Ok(output.clone())) .map(|(noun, verb, _out)| Ok((noun, verb))) - .unwrap_or(Err(IntcodeProgramError)) + .unwrap_or(Err(IntcodeProgramError::Unknown)) } diff --git a/src/bin/day_7.rs b/src/bin/day_7.rs index 0abf215..9b9177a 100644 --- a/src/bin/day_7.rs +++ b/src/bin/day_7.rs @@ -52,12 +52,12 @@ fn find_max_power( feedback_loop_mode: bool, ) -> Result { PhaseSetting::all(feedback_loop_mode) - .map(|phase| AmplifierArray::new(program, phase).execute()) + .map(|phase| AmplifierArray::new(program, &phase).execute()) .collect::, _>>() - .map(|powers| powers.into_iter().max().unwrap_or(0)) + .map(|powers| powers.into_iter().max().unwrap_or(Intcode::from(0))) } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone)] struct PhaseSetting([Intcode; 5]); impl PhaseSetting { @@ -69,7 +69,7 @@ impl PhaseSetting { } } - fn permute(min: Intcode, max: Intcode) -> impl Iterator { + fn permute(min: i32, max: i32) -> impl Iterator { // This is an absolutely atrocious way to do the permutation, // but luckily it's only 5 elements long. (min..max) @@ -77,12 +77,14 @@ impl PhaseSetting { (min..max).flat_map(move |b| { (min..max).flat_map(move |c| { (min..max).flat_map(move |d| { - (min..max).map(move |e| PhaseSetting([a, b, c, d, e])) + (min..max).map(move |e| { + PhaseSetting([a.into(), b.into(), c.into(), d.into(), e.into()]) + }) }) }) }) }) - .filter(move |phase| (min..max).all(|x| phase.0.contains(&x))) + .filter(move |phase| (min..max).all(|x| phase.0.contains(&x.into()))) } } @@ -92,7 +94,7 @@ struct AmplifierArray { } impl AmplifierArray { - fn new(program: &IntcodeProgram, phase: PhaseSetting) -> AmplifierArray { + fn new(program: &IntcodeProgram, phase: &PhaseSetting) -> AmplifierArray { AmplifierArray { amplifiers: (0..5) .map(|n| AmplifierArray::new_amp(program, phase, n)) @@ -100,11 +102,11 @@ impl AmplifierArray { } } - fn new_amp(program: &IntcodeProgram, phase: PhaseSetting, n: usize) -> IntcodeProgram { + fn new_amp(program: &IntcodeProgram, phase: &PhaseSetting, n: usize) -> IntcodeProgram { if n == 0 { - program.with_input(list![phase.0[n], 0]) + program.with_input(list![phase.0[n].clone(), Intcode::from(0)]) } else { - program.with_input(list![phase.0[n]]) + program.with_input(list![phase.0[n].clone()]) } } @@ -122,7 +124,7 @@ impl AmplifierArray { self.amplifiers .first() .and_then(|amp| amp.input.first().cloned()) - .ok_or(IntcodeProgramError) + .ok_or(IntcodeProgramError::Unknown) } fn is_terminated(&self) -> bool { diff --git a/src/lib.rs b/src/lib.rs index 717505e..5a5f9b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,21 @@ +use num::bigint::BigInt; +use num::traits::identities::Zero; +use rpds::RedBlackTreeMap; use rpds::{list::List, vector::Vector}; use std::fmt; use std::iter; use std::iter::FromIterator; use std::iter::IntoIterator; -pub type Intcode = i32; +pub type Intcode = BigInt; #[derive(Debug, Clone)] pub struct IntcodeProgram { - instruction_pointer: usize, - pub error: bool, + instruction_pointer: Intcode, + pub error: Option, pub halted: bool, pub awaiting_input: bool, - memory: Vector, + memory: RedBlackTreeMap, pub input: List, pub output: Vector, } @@ -20,11 +23,15 @@ pub struct IntcodeProgram { impl FromIterator for IntcodeProgram { fn from_iter>(iter: I) -> Self { IntcodeProgram { - instruction_pointer: 0, - error: false, + instruction_pointer: Intcode::from(0), + error: None, halted: false, awaiting_input: false, - memory: iter.into_iter().collect(), + memory: iter + .into_iter() + .enumerate() + .map(|(addr, val)| (Intcode::from(addr), val)) + .collect(), input: List::new(), output: Vector::new(), } @@ -33,7 +40,8 @@ impl FromIterator for IntcodeProgram { impl IntcodeProgram { pub fn with_noun_verb_input(&self, noun: Intcode, verb: Intcode) -> IntcodeProgram { - self.with_memory_set(1, noun).with_memory_set(2, verb) + self.with_memory_set(1.into(), noun) + .with_memory_set(2.into(), verb) } pub fn with_input(&self, input: List) -> IntcodeProgram { @@ -61,7 +69,7 @@ impl IntcodeProgram { self.run_to_termination().output_into_result() } - pub fn execute_returning_memory_0(&self) -> Result, IntcodeProgramError> { + pub fn execute_returning_memory_0(&self) -> Result { self.run_to_termination().memory_0_into_result() } @@ -81,7 +89,7 @@ impl IntcodeProgram { .unwrap() } - fn with_instruction_pointer(&self, instruction_pointer: usize) -> IntcodeProgram { + fn with_instruction_pointer(&self, instruction_pointer: Intcode) -> IntcodeProgram { IntcodeProgram { instruction_pointer, ..self.clone() @@ -90,19 +98,16 @@ impl IntcodeProgram { fn with_instruction_pointer_offset(&self, offset: usize) -> IntcodeProgram { IntcodeProgram { - instruction_pointer: self.instruction_pointer + offset, + instruction_pointer: self.instruction_pointer.clone() + offset, ..self.clone() } } - fn with_memory_set(&self, address: usize, value: Intcode) -> IntcodeProgram { - self.memory - .set(address, value) - .map(|memory| IntcodeProgram { - memory, - ..self.clone() - }) - .unwrap_or(self.error()) + fn with_memory_set(&self, address: Intcode, value: Intcode) -> IntcodeProgram { + IntcodeProgram { + memory: self.memory.insert(address, value), + ..self.clone() + } } fn with_input_consumed(&self) -> IntcodeProgram { @@ -112,7 +117,7 @@ impl IntcodeProgram { input, ..self.clone() }) - .unwrap_or(self.error()) + .unwrap_or(self.error(IntcodeProgramError::Unknown)) } fn with_output(&self, print: Intcode) -> IntcodeProgram { @@ -123,25 +128,26 @@ impl IntcodeProgram { } fn output_into_result(&self) -> Result, IntcodeProgramError> { - if self.error { - Err(IntcodeProgramError) - } else { - Ok(self.output.clone()) + match self.error { + Some(ref error) => Err(error.clone()), + None => Ok(self.output.clone()), } } - fn memory_0_into_result(&self) -> Result, IntcodeProgramError> { - if self.error { - Err(IntcodeProgramError) - } else { - Ok(self.memory.get(0).cloned()) + fn memory_0_into_result(&self) -> Result { + match self.error { + Some(ref error) => Err(error.clone()), + None => Ok(self + .memory + .get(&Intcode::from(0)) + .cloned() + .unwrap_or(Intcode::from(0))), } } fn next(&self) -> IntcodeProgram { - //eprintln!("{:?}", self); self.memory - .get(self.instruction_pointer) - .map(|&opcode| match opcode % 100 { + .get(&self.instruction_pointer) + .map(|opcode| match opcode.to_radix_le(100).1[0] { 1 => self.add(opcode), 2 => self.multiply(opcode), 3 => self.input(opcode), @@ -151,77 +157,79 @@ impl IntcodeProgram { 7 => self.less_than(opcode), 8 => self.equals(opcode), 99 => self.halt(), - _ => self.error(), + unknown => self.error(IntcodeProgramError::InvalidOpcode(unknown.clone())), }) - .unwrap_or(self.error()) + .unwrap_or(self.error(IntcodeProgramError::Unknown)) } - fn add(&self, mode: Intcode) -> IntcodeProgram { + fn add(&self, mode: &Intcode) -> IntcodeProgram { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self + (in1, in2, out) => self .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, in1 + in2), - _ => self.error(), + .with_memory_set(out, in1 + in2), } } - fn multiply(&self, mode: Intcode) -> IntcodeProgram { + fn multiply(&self, mode: &Intcode) -> IntcodeProgram { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self + (in1, in2, out) => self .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, in1 * in2), - _ => self.error(), + .with_memory_set(out, in1 * in2), } } - fn input(&self, _mode: Intcode) -> IntcodeProgram { + fn input(&self, _mode: &Intcode) -> IntcodeProgram { match (self.input.first().cloned(), self.get_immediate(1)) { - (Some(input), Some(out)) => self + (Some(input), out) => self .with_instruction_pointer_offset(2) - .with_memory_set(out as usize, input) + .with_memory_set(out, input) .with_input_consumed(), - (None, Some(_out)) => self.await_input(), - _ => self.error(), + (None, _out) => self.await_input(), } } - fn output(&self, mode: Intcode) -> IntcodeProgram { + fn output(&self, mode: &Intcode) -> IntcodeProgram { match self.get(1, mode) { - Some(print) => self.with_instruction_pointer_offset(2).with_output(print), - _ => self.error(), + print => self.with_instruction_pointer_offset(2).with_output(print), } } - fn jump_if_true(&self, mode: Intcode) -> IntcodeProgram { + fn jump_if_true(&self, mode: &Intcode) -> IntcodeProgram { match (self.get(1, mode), self.get(2, mode)) { - (Some(pred), Some(to)) if pred != 0 => self.with_instruction_pointer(to as usize), - (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), - _ => self.error(), + (ref pred, ref to) if !pred.is_zero() => self.with_instruction_pointer(to.clone()), + (_, _) => self.with_instruction_pointer_offset(3), } } - fn jump_if_false(&self, mode: Intcode) -> IntcodeProgram { + fn jump_if_false(&self, mode: &Intcode) -> IntcodeProgram { match (self.get(1, mode), self.get(2, mode)) { - (Some(pred), Some(to)) if pred == 0 => self.with_instruction_pointer(to as usize), - (Some(_), Some(_)) => self.with_instruction_pointer_offset(3), - _ => self.error(), + (ref pred, ref to) if pred.is_zero() => self.with_instruction_pointer(to.clone()), + (_, _) => self.with_instruction_pointer_offset(3), } } - fn less_than(&self, mode: Intcode) -> IntcodeProgram { + fn less_than(&self, mode: &Intcode) -> IntcodeProgram { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, if in1 < in2 { 1 } else { 0 }), - _ => self.error(), + (in1, in2, out) => self.with_instruction_pointer_offset(4).with_memory_set( + out, + if in1 < in2 { + Intcode::from(1) + } else { + Intcode::from(0) + }, + ), } } - fn equals(&self, mode: Intcode) -> IntcodeProgram { + fn equals(&self, mode: &Intcode) -> IntcodeProgram { match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { - (Some(in1), Some(in2), Some(out)) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out as usize, if in1 == in2 { 1 } else { 0 }), - _ => self.error(), + (in1, in2, out) => self.with_instruction_pointer_offset(4).with_memory_set( + out, + if in1 == in2 { + Intcode::from(1) + } else { + Intcode::from(0) + }, + ), } } @@ -246,41 +254,81 @@ impl IntcodeProgram { } } - fn error(&self) -> IntcodeProgram { + fn error(&self, error: IntcodeProgramError) -> IntcodeProgram { IntcodeProgram { halted: true, - error: true, + error: Some(error), ..self.clone() } } - fn get(&self, pointer_offset: usize, mode: Intcode) -> Option { - match mode / (10 as Intcode).pow(pointer_offset as u32 + 1) % 10 { + fn get(&self, pointer_offset: usize, mode: &Intcode) -> Intcode { + match mode + .to_radix_le(10) + .1 + .get(pointer_offset + 2) + .cloned() + .unwrap_or(0) + { 0 => self.get_position(pointer_offset), 1 => self.get_immediate(pointer_offset), - _ => None, + _ => Intcode::from(0), // TODO: Relative mode } } - fn get_immediate(&self, pointer_offset: usize) -> Option { + fn get_immediate(&self, pointer_offset: usize) -> Intcode { self.memory - .get(self.instruction_pointer + pointer_offset) + .get(&(self.instruction_pointer.clone() + pointer_offset)) .cloned() + .unwrap_or(Intcode::from(0)) } - fn get_position(&self, pointer_offset: usize) -> Option { - self.get_immediate(pointer_offset) - .and_then(|r| self.memory.get(r as usize)) + fn get_position(&self, pointer_offset: usize) -> Intcode { + self.memory + .get(&self.get_immediate(pointer_offset)) .cloned() + .unwrap_or(Intcode::from(0)) } } -#[derive(Debug, PartialEq)] -pub struct IntcodeProgramError; +#[derive(Debug, PartialEq, Clone)] +pub enum IntcodeProgramError { + InvalidOpcode(u8), + Unknown, +} impl fmt::Display for IntcodeProgramError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Unknown error") + use IntcodeProgramError::*; + + match self { + InvalidOpcode(i) => write!(f, "{} is not a valid opcode", i), + Unknown => write!(f, "Unknown error"), + } } } impl std::error::Error for IntcodeProgramError {} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn day_2_example_1() { + let program: IntcodeProgram = vec![1, 0, 0, 0, 99] + .into_iter() + .map(Intcode::from) + .collect::() + .run_to_termination(); + + assert_eq!(program.error, None); + assert_eq!( + program.memory, + vec![2, 0, 0, 0, 99] + .into_iter() + .enumerate() + .map(|(i, val)| (Intcode::from(i), Intcode::from(val))) + .collect::>() + ); + } +} -- cgit v1.2.3 From f6e829afa6a19225d505273eaaeee30ea4a4860b Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sat, 14 Dec 2019 23:52:56 +0200 Subject: Added relative mode support. Currently isn't working. --- inputs/day_9.txt | 1 + src/lib.rs | 132 ++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 inputs/day_9.txt diff --git a/inputs/day_9.txt b/inputs/day_9.txt new file mode 100644 index 0000000..6ec0b92 --- /dev/null +++ b/inputs/day_9.txt @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,23,1,1004,1102,1,26,1000,1102,897,1,1028,1101,27,0,1012,1102,33,1,1001,1102,32,1,1007,1101,39,0,1005,1101,0,29,1018,1101,0,0,1020,1101,1,0,1021,1101,0,21,1002,1102,1,35,1014,1101,0,36,1009,1102,1,38,1006,1102,1,251,1024,1102,28,1,1017,1102,37,1,1008,1102,1,329,1026,1102,25,1,1011,1102,31,1,1013,1102,892,1,1029,1102,242,1,1025,1102,1,881,1022,1102,22,1,1003,1102,874,1,1023,1101,20,0,1016,1101,24,0,1019,1101,0,326,1027,1101,0,34,1015,1102,1,30,1010,109,-2,2102,1,7,63,1008,63,36,63,1005,63,205,1001,64,1,64,1105,1,207,4,187,1002,64,2,64,109,9,21101,40,0,6,1008,1013,43,63,1005,63,227,1105,1,233,4,213,1001,64,1,64,1002,64,2,64,109,26,2105,1,-9,4,239,1001,64,1,64,1106,0,251,1002,64,2,64,109,-15,1205,2,263,1105,1,269,4,257,1001,64,1,64,1002,64,2,64,109,-9,2102,1,0,63,1008,63,36,63,1005,63,295,4,275,1001,64,1,64,1106,0,295,1002,64,2,64,109,-14,1207,10,38,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,28,2106,0,4,1106,0,335,4,323,1001,64,1,64,1002,64,2,64,109,-8,1206,6,351,1001,64,1,64,1106,0,353,4,341,1002,64,2,64,109,-1,2107,33,-7,63,1005,63,369,1106,0,375,4,359,1001,64,1,64,1002,64,2,64,109,-9,2108,26,-1,63,1005,63,395,1001,64,1,64,1106,0,397,4,381,1002,64,2,64,109,3,1201,-2,0,63,1008,63,38,63,1005,63,419,4,403,1105,1,423,1001,64,1,64,1002,64,2,64,109,-13,2101,0,9,63,1008,63,23,63,1005,63,445,4,429,1105,1,449,1001,64,1,64,1002,64,2,64,109,11,1208,1,32,63,1005,63,471,4,455,1001,64,1,64,1106,0,471,1002,64,2,64,109,17,21108,41,38,-4,1005,1019,487,1105,1,493,4,477,1001,64,1,64,1002,64,2,64,109,6,1206,-9,511,4,499,1001,64,1,64,1106,0,511,1002,64,2,64,109,-23,21102,42,1,8,1008,1014,42,63,1005,63,533,4,517,1106,0,537,1001,64,1,64,1002,64,2,64,109,-3,2107,36,5,63,1005,63,555,4,543,1106,0,559,1001,64,1,64,1002,64,2,64,109,-6,1202,5,1,63,1008,63,21,63,1005,63,581,4,565,1106,0,585,1001,64,1,64,1002,64,2,64,109,1,1208,10,40,63,1005,63,605,1001,64,1,64,1106,0,607,4,591,1002,64,2,64,109,7,1201,0,0,63,1008,63,42,63,1005,63,631,1001,64,1,64,1106,0,633,4,613,1002,64,2,64,109,1,21107,43,42,7,1005,1013,649,1105,1,655,4,639,1001,64,1,64,1002,64,2,64,109,7,21108,44,44,3,1005,1016,677,4,661,1001,64,1,64,1106,0,677,1002,64,2,64,109,-7,21102,45,1,9,1008,1015,44,63,1005,63,701,1001,64,1,64,1106,0,703,4,683,1002,64,2,64,109,13,21101,46,0,-7,1008,1012,46,63,1005,63,729,4,709,1001,64,1,64,1105,1,729,1002,64,2,64,109,-13,2101,0,3,63,1008,63,33,63,1005,63,753,1001,64,1,64,1106,0,755,4,735,1002,64,2,64,109,14,1205,1,773,4,761,1001,64,1,64,1105,1,773,1002,64,2,64,109,-23,1202,10,1,63,1008,63,30,63,1005,63,797,1001,64,1,64,1105,1,799,4,779,1002,64,2,64,109,13,2108,22,-7,63,1005,63,817,4,805,1106,0,821,1001,64,1,64,1002,64,2,64,109,-11,1207,5,24,63,1005,63,843,4,827,1001,64,1,64,1105,1,843,1002,64,2,64,109,11,21107,47,48,7,1005,1017,861,4,849,1106,0,865,1001,64,1,64,1002,64,2,64,109,15,2105,1,-2,1001,64,1,64,1106,0,883,4,871,1002,64,2,64,109,10,2106,0,-7,4,889,1106,0,901,1001,64,1,64,4,64,99,21102,1,27,1,21102,1,915,0,1105,1,922,21201,1,28510,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,22102,1,1,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,21202,-2,1,-2,109,-3,2106,0,0 diff --git a/src/lib.rs b/src/lib.rs index 5a5f9b3..57d0cb1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub type Intcode = BigInt; #[derive(Debug, Clone)] pub struct IntcodeProgram { instruction_pointer: Intcode, + relative_base: Intcode, pub error: Option, pub halted: bool, pub awaiting_input: bool, @@ -24,6 +25,7 @@ impl FromIterator for IntcodeProgram { fn from_iter>(iter: I) -> Self { IntcodeProgram { instruction_pointer: Intcode::from(0), + relative_base: Intcode::from(0), error: None, halted: false, awaiting_input: false, @@ -103,6 +105,13 @@ impl IntcodeProgram { } } + fn with_relative_base(&self, relative_base: Intcode) -> IntcodeProgram { + IntcodeProgram { + relative_base, + ..self.clone() + } + } + fn with_memory_set(&self, address: Intcode, value: Intcode) -> IntcodeProgram { IntcodeProgram { memory: self.memory.insert(address, value), @@ -156,6 +165,7 @@ impl IntcodeProgram { 6 => self.jump_if_false(opcode), 7 => self.less_than(opcode), 8 => self.equals(opcode), + 9 => self.set_relative_base(opcode), 99 => self.halt(), unknown => self.error(IntcodeProgramError::InvalidOpcode(unknown.clone())), }) @@ -163,7 +173,11 @@ impl IntcodeProgram { } fn add(&self, mode: &Intcode) -> IntcodeProgram { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + match ( + self.get(1, mode), + self.get(2, mode), + self.get_literal(3, mode), + ) { (in1, in2, out) => self .with_instruction_pointer_offset(4) .with_memory_set(out, in1 + in2), @@ -171,15 +185,19 @@ impl IntcodeProgram { } fn multiply(&self, mode: &Intcode) -> IntcodeProgram { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + match ( + self.get(1, mode), + self.get(2, mode), + self.get_literal(3, mode), + ) { (in1, in2, out) => self .with_instruction_pointer_offset(4) .with_memory_set(out, in1 * in2), } } - fn input(&self, _mode: &Intcode) -> IntcodeProgram { - match (self.input.first().cloned(), self.get_immediate(1)) { + fn input(&self, mode: &Intcode) -> IntcodeProgram { + match (self.input.first().cloned(), self.get_literal(1, mode)) { (Some(input), out) => self .with_instruction_pointer_offset(2) .with_memory_set(out, input) @@ -208,7 +226,11 @@ impl IntcodeProgram { } fn less_than(&self, mode: &Intcode) -> IntcodeProgram { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + match ( + self.get(1, mode), + self.get(2, mode), + self.get_literal(3, mode), + ) { (in1, in2, out) => self.with_instruction_pointer_offset(4).with_memory_set( out, if in1 < in2 { @@ -221,7 +243,11 @@ impl IntcodeProgram { } fn equals(&self, mode: &Intcode) -> IntcodeProgram { - match (self.get(1, mode), self.get(2, mode), self.get_immediate(3)) { + match ( + self.get(1, mode), + self.get(2, mode), + self.get_literal(3, mode), + ) { (in1, in2, out) => self.with_instruction_pointer_offset(4).with_memory_set( out, if in1 == in2 { @@ -233,6 +259,12 @@ impl IntcodeProgram { } } + fn set_relative_base(&self, mode: &Intcode) -> IntcodeProgram { + match self.get(1, mode) { + base_change => self.with_relative_base(self.relative_base.clone() + base_change), + } + } + fn halt(&self) -> IntcodeProgram { IntcodeProgram { halted: true, @@ -266,13 +298,29 @@ impl IntcodeProgram { match mode .to_radix_le(10) .1 - .get(pointer_offset + 2) + .get(pointer_offset + 1) .cloned() .unwrap_or(0) { 0 => self.get_position(pointer_offset), 1 => self.get_immediate(pointer_offset), - _ => Intcode::from(0), // TODO: Relative mode + 2 => self.get_relative(pointer_offset), + _ => Intcode::from(0), + } + } + + fn get_literal(&self, pointer_offset: usize, mode: &Intcode) -> Intcode { + match mode + .to_radix_le(10) + .1 + .get(pointer_offset + 1) + .cloned() + .unwrap_or(0) + { + 0 => self.get_immediate(pointer_offset), + 1 => self.get_immediate(pointer_offset), + 2 => self.get_immediate_relative(pointer_offset), + _ => Intcode::from(0), } } @@ -289,6 +337,17 @@ impl IntcodeProgram { .cloned() .unwrap_or(Intcode::from(0)) } + + fn get_relative(&self, pointer_offset: usize) -> Intcode { + self.memory + .get(&(self.get_immediate(pointer_offset) + self.relative_base.clone())) + .cloned() + .unwrap_or(Intcode::from(0)) + } + + fn get_immediate_relative(&self, pointer_offset: usize) -> Intcode { + self.get_immediate(pointer_offset) + self.relative_base.clone() + } } #[derive(Debug, PartialEq, Clone)] @@ -313,22 +372,53 @@ impl std::error::Error for IntcodeProgramError {} mod tests { use super::*; - #[test] - fn day_2_example_1() { - let program: IntcodeProgram = vec![1, 0, 0, 0, 99] + fn i32_vec_to_intcode_program(input: Vec) -> IntcodeProgram { + input.into_iter().map(Intcode::from).collect() + } + + fn i32_vec_to_intcode_memory(input: Vec) -> RedBlackTreeMap { + input .into_iter() - .map(Intcode::from) - .collect::() - .run_to_termination(); + .enumerate() + .map(|(i, val)| (Intcode::from(i), Intcode::from(val))) + .collect() + } + + fn test_example_program( + before_execution: Vec, + after_execution: Vec, + ) -> IntcodeProgram { + let program = i32_vec_to_intcode_program(before_execution).run_to_termination(); assert_eq!(program.error, None); - assert_eq!( - program.memory, - vec![2, 0, 0, 0, 99] - .into_iter() - .enumerate() - .map(|(i, val)| (Intcode::from(i), Intcode::from(val))) - .collect::>() + assert_eq!(program.memory, i32_vec_to_intcode_memory(after_execution)); + program + } + + #[test] + fn day_2_example_1() { + test_example_program(vec![1, 0, 0, 0, 99], vec![2, 0, 0, 0, 99]); + } + + #[test] + fn day_2_example_2() { + test_example_program(vec![2, 3, 0, 3, 99], vec![2, 3, 0, 6, 99]); + } + + #[test] + fn day_5_example_1() { + test_example_program(vec![1002, 4, 3, 4, 33], vec![1002, 4, 3, 4, 99]); + } + + #[test] + fn day_9_example_1() { + let program = test_example_program( + vec![ + 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, + ], + vec![ + 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, + ], ); } } -- cgit v1.2.3 From b8b6c411125f1f12cb4bbcde997141559b3ea797 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 15 Dec 2019 23:50:51 +0200 Subject: Debuggability and fixing the day 9 bug --- Cargo.toml | 5 ++++- src/lib.rs | 42 ++++++++++++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc97025..f3ec006 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,7 @@ derive_more = "0.99.2" im = "14.0.0" rpds = "0.7.0" archery = "0.3.0" -num = "0.2" \ No newline at end of file +num = "0.2" + +[profile.release] +debug = true diff --git a/src/lib.rs b/src/lib.rs index 57d0cb1..39966e6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ use std::iter::IntoIterator; pub type Intcode = BigInt; -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct IntcodeProgram { instruction_pointer: Intcode, relative_base: Intcode, @@ -40,6 +40,23 @@ impl FromIterator for IntcodeProgram { } } +impl fmt::Debug for IntcodeProgram { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!( + f, + "IntcodeProgram {{ \nins: {}, base: {}, error: {:?}, halted: {}, awaiting_input: {} \nmemory: {}, \ninput: {}, \n output: {} \n}}", + self.instruction_pointer, + self.relative_base, + self.error, + self.halted, + self.awaiting_input, + format!("{:?}", self.memory.iter().map(|(k, v)| format!("{} -> {}", k, v)).collect::>()), + format!("{:?}", self.input.iter().map(|n| format!("{}", n)).collect::>()), + format!("{:?}", self.output.iter().map(|n| format!("{}", n)).collect::>()), + ) + } +} + impl IntcodeProgram { pub fn with_noun_verb_input(&self, noun: Intcode, verb: Intcode) -> IntcodeProgram { self.with_memory_set(1.into(), noun) @@ -154,6 +171,7 @@ impl IntcodeProgram { } } fn next(&self) -> IntcodeProgram { + //dbg!(self); self.memory .get(&self.instruction_pointer) .map(|opcode| match opcode.to_radix_le(100).1[0] { @@ -261,7 +279,9 @@ impl IntcodeProgram { fn set_relative_base(&self, mode: &Intcode) -> IntcodeProgram { match self.get(1, mode) { - base_change => self.with_relative_base(self.relative_base.clone() + base_change), + base_change => self + .with_instruction_pointer_offset(2) + .with_relative_base(self.relative_base.clone() + base_change), } } @@ -384,6 +404,10 @@ mod tests { .collect() } + fn i32_vec_to_intcode_vec(input: Vec) -> Vector { + input.into_iter().map(Intcode::from).collect() + } + fn test_example_program( before_execution: Vec, after_execution: Vec, @@ -412,13 +436,11 @@ mod tests { #[test] fn day_9_example_1() { - let program = test_example_program( - vec![ - 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, - ], - vec![ - 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, - ], - ); + let quine = vec![ + 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, + ]; + let program = i32_vec_to_intcode_program(quine.clone()).run_to_termination(); + assert_eq!(program.error, None); + assert_eq!(program.output, i32_vec_to_intcode_vec(quine)); } } -- cgit v1.2.3 From 50c67c8cbe1cdccea28359eeea0280759931469b Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 16 Dec 2019 14:43:21 +0200 Subject: Day 10 and 11! Yay! --- inputs/day_10.txt | 24 +++++++ inputs/day_11.txt | 1 + src/bin/day_10.rs | 158 +++++++++++++++++++++++++++++++++++++++++ src/bin/day_11.rs | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/day_9.rs | 1 + src/lib.rs | 22 ++++++ 6 files changed, 411 insertions(+) create mode 100644 inputs/day_10.txt create mode 100644 inputs/day_11.txt create mode 100644 src/bin/day_10.rs create mode 100644 src/bin/day_11.rs create mode 100644 src/bin/day_9.rs diff --git a/inputs/day_10.txt b/inputs/day_10.txt new file mode 100644 index 0000000..51520ab --- /dev/null +++ b/inputs/day_10.txt @@ -0,0 +1,24 @@ +.###.#...#.#.##.#.####.. +.#....#####...#.######.. +#.#.###.###.#.....#.#### +##.###..##..####.#.####. +###########.#######.##.# +##########.#########.##. +.#.##.########.##...###. +###.#.##.#####.#.###.### +##.#####.##..###.#.##.#. +.#.#.#####.####.#..##### +.###.#####.#..#..##.#.## +########.##.#...######## +.####..##..#.###.###.#.# +....######.##.#.######.# +###.####.######.#....### +############.#.#.##.#### +##...##..####.####.#..## +.###.#########.###..#.## +#.##.#.#...##...#####..# +##.#..###############.## +##.###.#####.##.######.. +##.#####.#.#.##..####### +...#######.######...#### +#....#.#.#.####.#.#.#.## diff --git a/inputs/day_11.txt b/inputs/day_11.txt new file mode 100644 index 0000000..d6581e1 --- /dev/null +++ b/inputs/day_11.txt @@ -0,0 +1 @@ +3,8,1005,8,320,1106,0,11,0,0,0,104,1,104,0,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,29,2,1005,1,10,1006,0,11,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,57,1,8,15,10,1006,0,79,1,6,3,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,90,2,103,18,10,1006,0,3,2,105,14,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,123,2,9,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,1001,8,0,150,1,2,2,10,2,1009,6,10,1,1006,12,10,1006,0,81,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,187,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,209,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,231,1,1008,11,10,1,1001,4,10,2,1104,18,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,264,1,8,14,10,1006,0,36,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,293,1006,0,80,1006,0,68,101,1,9,9,1007,9,960,10,1005,10,15,99,109,642,104,0,104,1,21102,1,846914232732,1,21102,1,337,0,1105,1,441,21102,1,387512115980,1,21101,348,0,0,1106,0,441,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21102,209533824219,1,1,21102,1,395,0,1106,0,441,21101,0,21477985303,1,21102,406,1,0,1106,0,441,3,10,104,0,104,0,3,10,104,0,104,0,21101,868494234468,0,1,21101,429,0,0,1106,0,441,21102,838429471080,1,1,21102,1,440,0,1106,0,441,99,109,2,21201,-1,0,1,21101,0,40,2,21102,472,1,3,21101,0,462,0,1106,0,505,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,467,468,483,4,0,1001,467,1,467,108,4,467,10,1006,10,499,1102,1,0,467,109,-2,2106,0,0,0,109,4,2101,0,-1,504,1207,-3,0,10,1006,10,522,21101,0,0,-3,21202,-3,1,1,22101,0,-2,2,21102,1,1,3,21102,541,1,0,1106,0,546,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,569,2207,-4,-2,10,1006,10,569,22102,1,-4,-4,1105,1,637,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21102,588,1,0,1105,1,546,22101,0,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,607,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,629,21201,-1,0,1,21102,629,1,0,105,1,504,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0 diff --git a/src/bin/day_10.rs b/src/bin/day_10.rs new file mode 100644 index 0000000..f25c3d2 --- /dev/null +++ b/src/bin/day_10.rs @@ -0,0 +1,158 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 10: Monitoring Station")] +/// Finds the asteroid with the best view of the other asteroids. If +/// an n is provided, then it will print the nth asteroid destroyed by +/// a laser from the asteroid with the best view. Otherwise, it will +/// print the number of asteroids visible. +/// +/// Takes a map of asteroids in on stdin. +/// +/// See https://adventofcode.com/2019/day/10 for details. +struct Opt { + /// indexed from 0 + #[structopt(short = "n")] + n: Option, +} + +fn main() { + let opt = Opt::from_args(); + let stdin = io::stdin(); + let map: AsteroidMap = stdin + .lock() + .lines() + .map(|l| exit_on_failed_assertion(l, "Error reading input")) + .collect(); + + match opt.n { + Some(n) => println!("{:?}", map.nth_destroyed_asteroid(n)), + None => println!("{}", map.best_asteroid_line_of_sight_count()), + }; +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug)] +struct AsteroidMap { + asteroids: Vec, +} + +impl FromIterator for AsteroidMap { + fn from_iter>(iter: T) -> Self { + AsteroidMap { + asteroids: iter + .into_iter() + .enumerate() + .flat_map(move |(y, line)| { + line.chars() + .enumerate() + .map(move |(x, c)| (x, y, c)) + .collect::>() + }) + .filter(|(_x, _y, c)| *c == '#') + .map(|(x, y, _x)| Asteroid { + x: x as i32, + y: y as i32, + }) + .collect(), + } + } +} + +impl AsteroidMap { + fn best_asteroid_line_of_sight_count(&self) -> usize { + self.optimal_view_asteroid() + .map(|a| self.count_visible_from(&a)) + .unwrap_or(0) + } + + fn nth_destroyed_asteroid(&self, n: usize) -> Option { + self.optimal_view_asteroid() + .and_then(|source| self.nth_destroyed_asteroid_from(&source, n)) + } + + fn nth_destroyed_asteroid_from(&self, source: &Asteroid, n: usize) -> Option { + if self.asteroids.len() - 1 < n { + None + } else if self.count_visible_from(source) >= n { + sort_by_key( + self.asteroids + .iter() + .filter(|b| self.has_line_of_sight(source, b)), + |b| (source.angle_to(b) * 100000.) as i32, + ) + .nth(n) + .cloned() + } else { + self.remove_visible_to(source) + .nth_destroyed_asteroid_from(source, n - self.count_visible_from(source)) + } + } + + fn optimal_view_asteroid(&self) -> Option { + self.asteroids + .iter() + .max_by_key(|a| self.count_visible_from(a)) + .cloned() + } + + fn count_visible_from(&self, a: &Asteroid) -> usize { + self.asteroids + .iter() + .filter(|b| a != *b && self.has_line_of_sight(a, b)) + .count() + } + + fn remove_visible_to(&self, source: &Asteroid) -> AsteroidMap { + AsteroidMap { + asteroids: self + .asteroids + .iter() + .filter(|b| self.has_line_of_sight(source, b)) + .cloned() + .collect(), + } + } + + fn has_line_of_sight(&self, a: &Asteroid, b: &Asteroid) -> bool { + a != b + && !self.asteroids.iter().any(|c| { + a != c + && b != c + && a.angle_to(b) == a.angle_to(c) + && a.distance_squared(b) > a.distance_squared(c) + }) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct Asteroid { + x: i32, + y: i32, +} + +impl Asteroid { + fn angle_to(&self, other: &Asteroid) -> f32 { + ((self.x as f32 - other.x as f32).atan2(other.y as f32 - self.y as f32) + + std::f32::consts::PI) + % (2. * std::f32::consts::PI) + } + + fn distance_squared(&self, other: &Asteroid) -> i32 { + (self.x - other.x).pow(2) + (self.y - other.y).pow(2) + } +} diff --git a/src/bin/day_11.rs b/src/bin/day_11.rs new file mode 100644 index 0000000..da3e1fd --- /dev/null +++ b/src/bin/day_11.rs @@ -0,0 +1,205 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::RedBlackTreeMap; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 11: Space Police")] +/// Calculates how many blocks a painting robot would paint. +/// +/// Takes the program to run on the robot in on stdin. +/// +/// See https://adventofcode.com/2019/day/11 for details. +struct Opt { + /// debug mode prints the size of the painted area on a black background + #[structopt(short = "d", long = "debug")] + debug: bool, +} + +fn main() { + let opt = Opt::from_args(); + let stdin = io::stdin(); + 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::(); + + let finished_robot = exit_on_failed_assertion( + Robot::new(program, !opt.debug).execute(), + "Robot encountered an error", + ); + if opt.debug { + println!("{}", finished_robot.canvas.size()); + } else { + println!("{}", finished_robot); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug, Clone)] +struct Robot { + program: IntcodeProgram, + position: (i32, i32), + facing: Direction, + canvas: RedBlackTreeMap<(i32, i32), bool>, + background: bool, +} + +impl fmt::Display for Robot { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.min_white_y()..=self.max_white_y()) + .map(move |y| { + (self.min_white_x()..=self.max_white_x()) + .map(move |x| (x, y)) + .map(|coord| self.canvas.get(&coord).cloned().unwrap_or(self.background)) + .map(|c| write!(f, "{}", if c { '#' } else { ' ' })) + .collect::() + .and_then(|_| writeln!(f, "")) + }) + .collect() + } +} + +#[derive(Debug, Clone)] +enum Direction { + Up, + Down, + Left, + Right, +} + +impl Robot { + fn new(program: IntcodeProgram, background: bool) -> Robot { + Robot { + program: program.run_to_termination_or_input(), + position: (0, 0), + facing: Direction::Up, + canvas: RedBlackTreeMap::new(), + background, + } + } + + fn execute(&self) -> Result { + iter::successors(Some(self.clone()), |robot| Some(robot.next())) + .find(|robot| { + robot.program.error.is_some() + || (robot.program.halted && robot.program.output.is_empty()) + }) + .unwrap() // infinite iterator won't terminate unless this is Some + .as_result() + } + + fn as_result(&self) -> Result { + match self.program.error { + Some(ref error) => Err(error.clone()), + None => Ok(self.clone()), + } + } + + fn next(&self) -> Robot { + match ( + self.program.output.get(0).map(intcode_to_bool), + self.program.output.get(1).map(intcode_to_bool), + ) { + (Some(paint), Some(rot)) => Robot { + program: self + .program + .with_cleared_output() + .with_input(list![bool_to_intcode( + self.canvas + .get(&self.facing.rotate(rot).move_position(self.position)) + .cloned() + .unwrap_or(self.background), + )]) + .run_to_termination_or_input(), + position: self.facing.rotate(rot).move_position(self.position), + facing: self.facing.rotate(rot), + canvas: self.canvas.insert(self.position, paint), + background: self.background, + }, + _ => Robot { + program: self + .program + .with_input(list![bool_to_intcode( + self.canvas + .get(&self.position) + .cloned() + .unwrap_or(self.background), + )]) + .run_to_termination_or_input(), + ..self.clone() + }, + } + } + + fn min_white_x(&self) -> i32 { + self.white_blocks().map(|(x, _y)| x).min().unwrap_or(0) + } + fn min_white_y(&self) -> i32 { + self.white_blocks().map(|(_x, y)| y).min().unwrap_or(0) + } + fn max_white_x(&self) -> i32 { + self.white_blocks().map(|(x, _y)| x).max().unwrap_or(0) + } + fn max_white_y(&self) -> i32 { + self.white_blocks().map(|(_x, y)| y).max().unwrap_or(0) + } + + fn white_blocks<'a>(&'a self) -> impl 'a + Iterator { + self.canvas + .iter() + .filter(|(_, val)| **val) + .map(|(coord, _)| coord) + .cloned() + } +} + +impl Direction { + fn rotate(&self, clockwise: bool) -> Direction { + use Direction::*; + + if clockwise { + match self { + Up => Right, + Right => Down, + Down => Left, + Left => Up, + } + } else { + match self { + Up => Left, + Left => Down, + Down => Right, + Right => Up, + } + } + } + + fn move_position(&self, position: (i32, i32)) -> (i32, i32) { + use Direction::*; + match self { + Up => (position.0, position.1 + 1), + Down => (position.0, position.1 - 1), + Left => (position.0 - 1, position.1), + Right => (position.0 + 1, position.1), + } + } +} diff --git a/src/bin/day_9.rs b/src/bin/day_9.rs new file mode 100644 index 0000000..7f9b4aa --- /dev/null +++ b/src/bin/day_9.rs @@ -0,0 +1 @@ +// Run the day 5 binary for this diff --git a/src/lib.rs b/src/lib.rs index 39966e6..6be1aba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ use std::fmt; use std::iter; use std::iter::FromIterator; use std::iter::IntoIterator; +use std::iter::Iterator; pub type Intcode = BigInt; @@ -57,6 +58,18 @@ impl fmt::Debug for IntcodeProgram { } } +pub fn intcode_to_bool(i: &Intcode) -> bool { + *i != Intcode::from(0) +} + +pub fn bool_to_intcode(i: bool) -> Intcode { + if i { + Intcode::from(1) + } else { + Intcode::from(0) + } +} + impl IntcodeProgram { pub fn with_noun_verb_input(&self, noun: Intcode, verb: Intcode) -> IntcodeProgram { self.with_memory_set(1.into(), noun) @@ -444,3 +457,12 @@ mod tests { assert_eq!(program.output, i32_vec_to_intcode_vec(quine)); } } + +pub fn sort_by_key( + iter: impl IntoIterator, + f: impl FnMut(&T) -> K, +) -> impl Iterator { + let mut tmp: Vec = iter.into_iter().collect(); + tmp.sort_by_key(f); + tmp.into_iter() +} -- cgit v1.2.3 From 8f88266bd0890ae8e238ab108d16dba9fea86bfd Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 19 Dec 2019 22:38:15 +0200 Subject: Day 12 part 1 --- inputs/day_12.txt | 4 ++ src/bin/day_12.rs | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 inputs/day_12.txt create mode 100644 src/bin/day_12.rs diff --git a/inputs/day_12.txt b/inputs/day_12.txt new file mode 100644 index 0000000..7e72a58 --- /dev/null +++ b/inputs/day_12.txt @@ -0,0 +1,4 @@ + + + + diff --git a/src/bin/day_12.rs b/src/bin/day_12.rs new file mode 100644 index 0000000..678653b --- /dev/null +++ b/src/bin/day_12.rs @@ -0,0 +1,158 @@ +use rpds::vector::Vector; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::num::ParseIntError; +use std::ops; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 12: The N-Body Problem")] +/// Simulates N bodies, physically interacting +/// +/// See https://adventofcode.com/2019/day/12 for details. +struct Opt { + #[structopt(short = "n")] + n: usize, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let planets: Vec = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid planet")) + .collect(); + + println!("{}", energy(simulate_planets_n_iterations(planets, opt.n))); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn energy(planets: Vec) -> i32 { + planets.into_iter().map(|p| p.energy()).sum() +} + +fn simulate_planets_n_iterations(planets: Vec, n: usize) -> Vec { + iter::successors(Some((0, planets)), |(i, planets)| { + Some((i + 1, simulate_planets(planets.clone()))) + }) + .find(|(i, _)| *i == n) + .unwrap() + .1 +} + +fn simulate_planets(planets: Vec) -> Vec { + simulate_velocity(simulate_gravity(planets)) +} + +fn simulate_gravity(planets: Vec) -> Vec { + planets + .iter() + .map(|p| Planet { + pos: p.pos.clone(), + vel: planets + .iter() + .filter(|o| p != *o) + .map(|o| p.gravity_pull(o)) + .fold(p.vel, |acc, next| acc + next), + }) + .collect() +} + +fn simulate_velocity(planets: Vec) -> Vec { + planets + .into_iter() + .map(|p| Planet { + pos: p.pos + p.vel, + vel: p.vel, + }) + .collect() +} + +#[derive(Debug, Default, Clone, PartialEq)] +struct Planet { + pos: Vec3d, + vel: Vec3d, +} + +#[derive(Debug, Default, Clone, Copy, PartialEq)] +struct Vec3d { + x: i32, + y: i32, + z: i32, +} + +impl FromStr for Planet { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result { + s.replace(|c| "<>xyz= ".contains(c), "") + .split(',') + .map(|i| i.parse::()) + .collect::, _>>() + .and_then(|v| match &v[..] { + [x, y, z] => Ok(Planet { + pos: Vec3d { + x: *x, + y: *y, + z: *z, + }, + vel: Vec3d::default(), + }), + _ => "wrong number of fields" + .parse::() + .map(|x| Planet::default()), + }) + } +} + +impl Planet { + fn gravity_pull(&self, other: &Planet) -> Vec3d { + Vec3d { + x: gravity(self.pos.x, other.pos.x), + y: gravity(self.pos.y, other.pos.y), + z: gravity(self.pos.z, other.pos.z), + } + } + + fn energy(&self) -> i32 { + (self.pos.x.abs() + self.pos.y.abs() + self.pos.z.abs()) + * (self.vel.x.abs() + self.vel.y.abs() + self.vel.z.abs()) + } +} + +fn gravity(this: i32, that: i32) -> i32 { + if that > this { + 1 + } else if this > that { + -1 + } else { + 0 + } +} + +impl ops::Add for Vec3d { + type Output = Vec3d; + fn add(self, rhs: Vec3d) -> Self::Output { + Vec3d { + x: self.x + rhs.x, + y: self.y + rhs.y, + z: self.z + rhs.z, + } + } +} -- cgit v1.2.3 From 4316344e335cd69714799ed204d2448d81877b7d Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Fri, 20 Dec 2019 23:56:10 +0200 Subject: Day 12 part 2 --- src/bin/day_12.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/src/bin/day_12.rs b/src/bin/day_12.rs index 678653b..fa0db20 100644 --- a/src/bin/day_12.rs +++ b/src/bin/day_12.rs @@ -16,7 +16,7 @@ use structopt::StructOpt; /// See https://adventofcode.com/2019/day/12 for details. struct Opt { #[structopt(short = "n")] - n: usize, + n: Option, } fn main() { @@ -30,7 +30,10 @@ fn main() { .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid planet")) .collect(); - println!("{}", energy(simulate_planets_n_iterations(planets, opt.n))); + match opt.n { + Some(n) => println!("{}", energy(simulate_planets_n_iterations(planets, n))), + None => println!("{}", simulate_planets_to_duplicate(planets)), + }; } fn exit_on_failed_assertion(data: Result, message: &str) -> A { @@ -47,13 +50,47 @@ fn energy(planets: Vec) -> i32 { planets.into_iter().map(|p| p.energy()).sum() } -fn simulate_planets_n_iterations(planets: Vec, n: usize) -> Vec { - iter::successors(Some((0, planets)), |(i, planets)| { +fn simulate_planets_n_iterations(planets: Vec, n: u64) -> Vec { + simulate_planets_iter(planets) + .find(|(i, _)| *i == n) + .unwrap() + .1 +} + +fn simulate_planets_to_duplicate(planets: Vec) -> u64 { + lowest_common_multiple( + simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_x(o)), + simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_y(o)), + simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_z(o)), + ) +} + +fn simulate_planets_to_duplicate_1d( + planets: Vec, + eq: impl FnMut((&Planet, &Planet)) -> bool + Copy, +) -> u64 { + simulate_planets_iter(planets.clone()) + .skip(1) + .find(|(_i, ps)| ps.iter().zip(planets.iter()).all(eq)) + .unwrap() + .0 +} + +fn lowest_common_multiple(x: u64, y: u64, z: u64) -> u64 { + (1..) + .map(|i| x * i) + .find(|mx| multiples(y, *mx) && multiples(z, *mx)) + .unwrap() +} + +fn multiples(x: u64, target: u64) -> bool { + target % x == 0 +} + +fn simulate_planets_iter(planets: Vec) -> impl Iterator)> { + iter::successors(Some((0, planets.clone())), |(i, planets)| { Some((i + 1, simulate_planets(planets.clone()))) }) - .find(|(i, _)| *i == n) - .unwrap() - .1 } fn simulate_planets(planets: Vec) -> Vec { @@ -68,7 +105,7 @@ fn simulate_gravity(planets: Vec) -> Vec { vel: planets .iter() .filter(|o| p != *o) - .map(|o| p.gravity_pull(o)) + .map(|o| p.acc(o)) .fold(p.vel, |acc, next| acc + next), }) .collect() @@ -116,13 +153,13 @@ impl FromStr for Planet { }), _ => "wrong number of fields" .parse::() - .map(|x| Planet::default()), + .map(|_x| Planet::default()), }) } } impl Planet { - fn gravity_pull(&self, other: &Planet) -> Vec3d { + fn acc(&self, other: &Planet) -> Vec3d { Vec3d { x: gravity(self.pos.x, other.pos.x), y: gravity(self.pos.y, other.pos.y), @@ -134,6 +171,18 @@ impl Planet { (self.pos.x.abs() + self.pos.y.abs() + self.pos.z.abs()) * (self.vel.x.abs() + self.vel.y.abs() + self.vel.z.abs()) } + + fn equal_x(&self, other: &Planet) -> bool { + self.pos.x == other.pos.x && self.vel.x == other.vel.x + } + + fn equal_y(&self, other: &Planet) -> bool { + self.pos.y == other.pos.y && self.vel.y == other.vel.y + } + + fn equal_z(&self, other: &Planet) -> bool { + self.pos.z == other.pos.z && self.vel.z == other.vel.z + } } fn gravity(this: i32, that: i32) -> i32 { -- cgit v1.2.3 From 47eabec40889d650834a244cb1951eca14c3e5ad Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sat, 21 Dec 2019 11:57:34 +0200 Subject: Day 13 part 1 --- inputs/day_13.txt | 1 + src/bin/day_13.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 inputs/day_13.txt create mode 100644 src/bin/day_13.rs diff --git a/inputs/day_13.txt b/inputs/day_13.txt new file mode 100644 index 0000000..c600ec1 --- /dev/null +++ b/inputs/day_13.txt @@ -0,0 +1 @@ +1,380,379,385,1008,2689,888873,381,1005,381,12,99,109,2690,1102,0,1,383,1101,0,0,382,21001,382,0,1,20102,1,383,2,21101,0,37,0,1105,1,578,4,382,4,383,204,1,1001,382,1,382,1007,382,41,381,1005,381,22,1001,383,1,383,1007,383,25,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1101,-1,0,384,1106,0,119,1007,392,39,381,1006,381,161,1102,1,1,384,20101,0,392,1,21101,23,0,2,21102,0,1,3,21102,138,1,0,1105,1,549,1,392,384,392,21001,392,0,1,21101,23,0,2,21101,3,0,3,21102,1,161,0,1105,1,549,1101,0,0,384,20001,388,390,1,20101,0,389,2,21101,0,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,20101,0,389,2,21101,205,0,0,1105,1,393,1002,390,-1,390,1102,1,1,384,21001,388,0,1,20001,389,391,2,21101,228,0,0,1105,1,578,1206,1,261,1208,1,2,381,1006,381,253,20101,0,388,1,20001,389,391,2,21101,253,0,0,1106,0,393,1002,391,-1,391,1101,0,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21101,279,0,0,1106,0,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,0,304,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1101,0,1,384,1005,384,161,20102,1,388,1,20101,0,389,2,21101,0,0,3,21101,0,338,0,1106,0,549,1,388,390,388,1,389,391,389,21001,388,0,1,21002,389,1,2,21102,4,1,3,21101,0,365,0,1105,1,549,1007,389,24,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,230,18,20,1,1,20,109,3,21201,-2,0,1,22101,0,-1,2,21101,0,0,3,21102,1,414,0,1106,0,549,22102,1,-2,1,22102,1,-1,2,21101,0,429,0,1105,1,601,2102,1,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,22102,1,-3,-7,109,-8,2106,0,0,109,4,1202,-2,41,566,201,-3,566,566,101,639,566,566,2101,0,-1,0,204,-3,204,-2,204,-1,109,-4,2105,1,0,109,3,1202,-1,41,594,201,-2,594,594,101,639,594,594,20102,1,0,-2,109,-3,2106,0,0,109,3,22102,25,-2,1,22201,1,-1,1,21101,0,521,2,21102,1,1011,3,21102,1,1025,4,21102,630,1,0,1106,0,456,21201,1,1664,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,2,2,0,2,0,2,0,2,0,0,2,2,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,2,0,1,1,0,0,0,0,2,0,0,2,0,2,2,2,2,0,2,0,0,0,2,2,0,0,2,2,2,2,0,0,0,0,0,2,0,0,0,0,2,2,0,1,1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,2,2,0,2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2,2,2,0,0,1,1,0,0,2,2,2,0,0,0,2,0,0,0,0,0,2,2,0,0,2,0,2,0,0,0,2,2,0,0,0,2,0,0,0,2,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,2,0,0,2,0,0,0,0,2,0,0,2,0,2,0,2,0,2,0,0,1,1,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0,0,2,2,0,0,0,2,2,0,0,2,0,0,0,2,2,2,2,2,0,2,0,1,1,0,0,0,0,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,2,2,2,0,0,0,0,0,2,0,0,2,0,0,1,1,0,2,0,0,2,0,0,0,0,2,0,0,0,0,2,2,0,2,0,0,0,0,2,0,0,0,0,0,2,0,2,0,0,2,0,0,2,0,0,1,1,0,2,2,2,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,2,0,0,2,0,2,0,2,2,0,2,2,0,2,0,2,0,0,1,1,0,0,2,0,0,2,0,2,0,0,2,0,0,2,0,0,0,2,0,0,0,0,2,0,0,2,0,0,2,2,0,2,0,0,0,0,2,2,0,1,1,0,0,2,2,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,2,2,2,0,0,2,0,2,0,2,2,0,0,2,0,2,0,0,1,1,0,0,2,2,2,0,0,2,2,0,2,2,2,0,0,0,2,2,2,0,2,0,0,0,0,0,2,0,0,2,0,2,0,0,0,0,0,0,0,1,1,0,2,0,0,0,2,2,0,2,0,0,2,0,2,2,2,0,0,2,2,0,2,0,0,0,0,0,0,2,2,0,2,2,0,2,0,0,2,0,1,1,0,0,2,0,0,2,2,0,0,0,0,0,2,2,0,2,2,2,0,2,0,2,2,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,1,1,0,2,0,2,0,2,2,2,2,0,0,0,2,0,0,0,2,2,0,0,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,2,0,0,0,1,1,0,0,0,0,2,0,0,2,0,0,2,2,0,2,0,0,0,2,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,0,2,0,1,1,0,2,0,0,0,2,0,0,0,2,2,0,2,0,0,2,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,0,0,2,0,0,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,34,58,37,19,14,62,51,10,28,52,86,20,39,30,61,36,77,73,19,11,17,74,7,54,40,59,20,92,18,13,85,72,83,58,18,68,10,22,94,22,25,40,67,96,55,96,42,16,80,80,96,35,19,79,81,63,91,5,72,68,80,93,79,36,91,47,71,82,45,29,51,36,10,62,57,29,17,16,4,88,75,81,70,77,32,2,38,37,35,86,41,35,61,71,72,22,14,33,12,10,10,56,30,3,90,71,24,62,69,31,47,2,18,77,43,20,64,85,50,43,43,73,16,23,98,4,23,53,82,15,88,1,39,78,43,57,65,8,45,79,17,44,32,76,31,3,25,71,45,16,42,61,89,21,93,4,98,66,68,5,13,19,48,65,29,5,24,59,29,49,57,39,21,96,10,8,25,82,17,42,46,49,83,4,81,32,14,7,76,62,31,74,55,19,39,63,89,41,38,28,34,34,88,7,77,43,87,10,47,85,39,31,88,69,40,72,51,49,64,46,64,14,66,95,95,58,38,88,82,35,6,58,3,21,33,58,9,95,43,52,13,22,22,10,11,47,35,33,31,58,93,83,13,14,55,71,88,42,73,83,91,84,62,78,80,15,26,50,8,15,6,91,89,3,12,53,47,47,82,67,12,77,6,63,88,94,53,19,97,36,34,59,91,27,37,45,44,31,8,58,16,7,74,76,83,17,28,42,85,19,1,61,73,84,37,15,43,52,80,48,51,98,70,77,28,55,78,85,64,32,22,82,69,7,82,55,78,24,5,89,55,4,34,28,71,76,81,90,96,2,2,77,41,32,24,60,10,11,26,64,66,19,11,77,11,82,81,1,52,2,79,43,47,87,63,73,3,81,69,66,53,4,83,88,13,5,62,94,55,58,4,93,96,58,40,69,64,56,80,71,85,44,45,24,80,59,53,15,85,92,89,95,69,77,53,27,72,3,54,49,9,35,10,85,43,86,9,42,69,29,64,96,17,72,47,24,2,13,40,45,62,19,41,85,28,68,73,20,52,56,19,57,1,36,64,18,26,41,94,81,45,35,29,32,28,87,86,53,71,54,67,68,47,53,17,40,61,58,74,2,51,43,23,62,54,13,80,67,88,94,1,62,85,7,12,87,51,4,69,25,57,6,79,94,15,75,93,46,19,28,84,72,84,59,60,59,59,14,11,30,57,53,75,83,72,61,65,50,26,49,23,40,82,11,67,8,55,13,22,41,32,33,89,37,69,11,24,24,8,21,89,11,46,89,88,59,3,7,43,85,74,92,72,60,85,82,33,82,71,14,21,41,4,78,88,4,22,81,30,92,17,9,62,69,84,47,6,86,49,94,11,96,21,1,5,1,45,19,60,59,17,85,67,42,21,11,79,39,27,72,54,19,69,50,52,78,78,6,16,96,86,37,58,79,9,45,10,73,29,53,75,63,50,66,6,69,8,74,68,88,9,88,87,50,34,45,12,43,43,58,14,29,32,77,77,97,45,29,41,94,21,91,52,22,74,44,48,11,20,68,9,51,7,85,93,74,59,16,34,60,12,3,18,17,4,71,44,49,79,68,54,96,74,21,74,60,59,16,77,65,97,84,54,52,37,95,9,3,41,9,72,82,82,95,31,71,56,50,59,93,57,79,16,9,74,72,47,1,9,5,55,63,64,80,40,93,54,11,57,26,76,19,85,41,80,90,92,27,61,24,83,93,96,95,28,68,80,11,60,65,36,2,46,75,59,52,11,36,74,62,52,6,23,85,93,61,36,26,70,2,13,97,52,92,96,87,63,63,31,2,50,25,34,79,46,4,48,51,74,96,74,7,43,82,84,50,59,53,13,51,8,81,36,93,10,31,10,50,76,69,33,3,71,1,1,65,68,57,69,15,64,81,59,38,38,89,79,80,52,44,59,26,96,21,38,38,79,2,96,2,92,73,49,14,71,74,66,94,98,63,28,59,26,30,67,1,61,84,92,47,24,27,41,57,95,89,6,96,48,43,7,82,42,5,27,15,32,89,53,3,35,63,84,97,92,77,50,38,73,10,50,89,95,96,77,61,51,90,22,75,41,77,1,14,72,68,91,10,80,28,25,10,86,54,10,87,55,40,79,16,35,8,82,51,70,84,12,72,74,4,88,71,69,83,9,55,10,57,9,3,40,74,72,61,75,64,54,32,61,26,53,48,45,22,6,83,21,21,9,4,7,65,98,78,17,54,35,95,79,36,53,59,84,53,14,20,94,12,31,54,86,39,95,82,38,8,22,58,50,27,32,53,79,49,71,76,18,64,75,64,88,58,88,27,62,31,54,11,59,11,3,42,66,85,41,888873 diff --git a/src/bin/day_13.rs b/src/bin/day_13.rs new file mode 100644 index 0000000..a7d6128 --- /dev/null +++ b/src/bin/day_13.rs @@ -0,0 +1,70 @@ +use aoc2019::*; +use rpds::vector::Vector; +use rpds::RedBlackTreeMap; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 13: Care Package")] +/// Executes an Intcode game +/// +/// The program is read from stdin as a series of comma-separated +/// values. Newlines are ignored. +/// +/// See https://adventofcode.com/2019/day/13 for details. +struct Opt { + #[structopt(short = "i", long = "input")] + input: Vec, +} + +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::() + .with_input(opt.input.into_iter().collect()); + + let result = exit_on_failed_assertion(program.execute(), "Program errored"); + + println!("{}", count_blocks(result)); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn render_screen(output: Vector) -> RedBlackTreeMap<(Intcode, Intcode), Intcode> { + (0..output.len() / 3) + .map(|i| i * 3) + .map(|i| { + ( + output[i].clone(), + output[i + 1].clone(), + output[i + 2].clone(), + ) + }) + .fold(RedBlackTreeMap::new(), |acc, (x, y, tile)| { + acc.insert((x, y), tile) + }) +} + +fn count_blocks(output: Vector) -> usize { + render_screen(output) + .values() + .filter(|val| **val == Intcode::from(2)) + .count() +} -- cgit v1.2.3 From 97087f6e1ab5a9260ab1a6a8d9791dba09bf9de8 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 22 Dec 2019 00:14:40 +0200 Subject: Day 13: Pong AI done --- src/bin/day_13.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++---------- src/lib.rs | 4 ++ 2 files changed, 105 insertions(+), 22 deletions(-) diff --git a/src/bin/day_13.rs b/src/bin/day_13.rs index a7d6128..ac1c478 100644 --- a/src/bin/day_13.rs +++ b/src/bin/day_13.rs @@ -1,8 +1,12 @@ use aoc2019::*; +use rpds::list; +use rpds::list::List; use rpds::vector::Vector; use rpds::RedBlackTreeMap; +use std::cmp::Ordering; use std::io; use std::io::prelude::*; +use std::iter; use std::process; use structopt::StructOpt; @@ -15,8 +19,8 @@ use structopt::StructOpt; /// /// See https://adventofcode.com/2019/day/13 for details. struct Opt { - #[structopt(short = "i", long = "input")] - input: Vec, + #[structopt(short = "q", long = "quarters")] + quarters: Option, } fn main() { @@ -29,12 +33,18 @@ fn main() { .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::() - .with_input(opt.input.into_iter().collect()); + .collect::(); - let result = exit_on_failed_assertion(program.execute(), "Program errored"); - - println!("{}", count_blocks(result)); + match opt.quarters { + Some(quarters) => { + let result = score_on_won_game(program.with_mem_0(quarters)); + println!("{}", result); + } + None => { + let result = exit_on_failed_assertion(program.execute(), "Program errored"); + println!("{}", count_blocks(&result)); + } + } } fn exit_on_failed_assertion(data: Result, message: &str) -> A { @@ -47,24 +57,93 @@ fn exit_on_failed_assertion(data: Result, message } } -fn render_screen(output: Vector) -> RedBlackTreeMap<(Intcode, Intcode), Intcode> { - (0..output.len() / 3) - .map(|i| i * 3) - .map(|i| { - ( - output[i].clone(), - output[i + 1].clone(), - output[i + 2].clone(), - ) - }) - .fold(RedBlackTreeMap::new(), |acc, (x, y, tile)| { - acc.insert((x, y), tile) - }) +#[derive(Default, Clone)] +struct Screen { + screen: RedBlackTreeMap<(Intcode, Intcode), Intcode>, + previous_ball: (Intcode, Intcode), + ball: (Intcode, Intcode), + paddle: (Intcode, Intcode), + score: Intcode, } -fn count_blocks(output: Vector) -> usize { - render_screen(output) +impl Screen { + fn render(output: &Vector) -> Screen { + (0..output.len() / 3) + .map(|i| i * 3) + .map(|i| { + ( + output[i].clone(), + output[i + 1].clone(), + output[i + 2].clone(), + ) + }) + .fold(Screen::default(), |acc, (x, y, tile)| { + if x == Intcode::from(-1) && y == Intcode::from(0) { + Screen { score: tile, ..acc } + } else if tile == Intcode::from(4) { + Screen { + ball: (x, y), + previous_ball: acc.ball, + ..acc + } + } else if tile == Intcode::from(3) { + Screen { + paddle: (x.clone(), y.clone()), + screen: acc.screen.insert((x, y), tile), + ..acc + } + } else if tile == Intcode::from(0) { + Screen { + screen: acc.screen.remove(&(x, y)), + ..acc + } + } else { + Screen { + screen: acc.screen.insert((x, y), tile), + ..acc + } + } + }) + } + + fn paddle_required_direction(&self) -> Intcode { + match self.paddle.0.cmp(&self.ball.0) { + Ordering::Less => Intcode::from(1), + Ordering::Equal => Intcode::from(0), + Ordering::Greater => Intcode::from(-1), + } + } +} + +fn count_blocks(output: &Vector) -> usize { + Screen::render(output) + .screen .values() .filter(|val| **val == Intcode::from(2)) .count() } + +fn score_on_won_game(program: IntcodeProgram) -> Intcode { + Screen::render( + &iter::successors(Some(program.run_to_termination_or_input()), |program| { + Some(next_game_state(program.clone())) + }) + .take_while(|program| !program.halted) + .find(|program| count_blocks(&program.output) == 0) + .unwrap() + .output, + ) + .score +} + +fn next_game_state(program: IntcodeProgram) -> IntcodeProgram { + program_with_next_input(program.run_to_termination_or_input()) +} + +fn program_with_next_input(program: IntcodeProgram) -> IntcodeProgram { + program.with_input(list![next_input(&program.output)]) +} + +fn next_input(output: &Vector) -> Intcode { + Screen::render(output).paddle_required_direction() +} diff --git a/src/lib.rs b/src/lib.rs index 6be1aba..5df59f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,6 +71,10 @@ pub fn bool_to_intcode(i: bool) -> Intcode { } impl IntcodeProgram { + pub fn with_mem_0(&self, val: Intcode) -> IntcodeProgram { + self.with_memory_set(0.into(), val) + } + pub fn with_noun_verb_input(&self, noun: Intcode, verb: Intcode) -> IntcodeProgram { self.with_memory_set(1.into(), noun) .with_memory_set(2.into(), verb) -- cgit v1.2.3 From 19bc2a98dcececcdad39dabd513caa80f8a8f023 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 22 Dec 2019 16:43:12 +0200 Subject: Day 14, refueling --- inputs/day_14.txt | 59 +++++++++++++++ src/bin/day_14.rs | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+) create mode 100644 inputs/day_14.txt create mode 100644 src/bin/day_14.rs diff --git a/inputs/day_14.txt b/inputs/day_14.txt new file mode 100644 index 0000000..dac9757 --- /dev/null +++ b/inputs/day_14.txt @@ -0,0 +1,59 @@ +2 RWPCH => 9 PVTL +1 FHFH => 4 BLPJK +146 ORE => 5 VJNBT +8 KDFNZ, 1 ZJGH, 1 GSCG => 5 LKPQG +11 NWDZ, 2 WBQR, 1 VRQR => 2 BMJR +3 GSCG => 4 KQDVM +5 QVNKN, 6 RPWKC => 3 BCNV +10 QMBM, 4 RBXB, 2 VRQR => 1 JHXBM +15 RPWKC => 6 MGCQ +1 QWKRZ => 4 FHFH +10 RWPCH => 6 MZKG +11 JFKGV, 5 QVNKN, 1 CTVK => 4 VQDT +1 SXKT => 5 RPWKC +1 VQDT, 25 ZVMCB => 2 RBXB +6 LGLNV, 4 XSNKB => 3 WBQR +199 ORE => 2 SXKT +1 XSNKB, 6 CWBNX, 1 HPKB, 5 PVTL, 1 JNKH, 9 SXKT, 3 KQDVM => 3 ZKTX +7 FDSX => 6 WJDF +7 JLRM => 4 CWBNX +167 ORE => 5 PQZXH +13 JHXBM, 2 NWDZ, 4 RFLX, 12 VRQR, 10 FJRFG, 14 PVTL, 2 JLRM => 6 DGFG +12 HPKB, 3 WHVXC => 9 ZJGH +1 JLRM, 2 ZJGH, 2 QVNKN => 9 FJRFG +129 ORE => 7 KZFPJ +2 QMBM => 1 RWPCH +7 VJMWM => 4 JHDW +7 PQZXH, 7 SXKT => 9 BJVQM +1 VJMWM, 4 JHDW, 1 MQXF => 7 FDSX +1 RPWKC => 7 WHVXC +1 ZJGH => 1 ZVMCB +1 RWPCH => 3 MPKR +187 ORE => 8 VJMWM +15 CTVK => 5 GSCG +2 XSNKB, 15 ZVMCB, 3 KDFNZ => 2 RFLX +18 QVNKN => 8 XLFZJ +4 CWBNX => 8 ZSCX +2 ZJGH, 1 JLRM, 1 MGCQ => 9 NPRST +13 BJVQM, 2 BCNV => 2 QWKRZ +2 QWKRZ, 2 BLPJK, 5 XSNKB => 2 VRQR +13 HPKB, 3 VQDT => 9 JLRM +2 SXKT, 1 VJNBT, 5 VLWQB => 6 CTVK +2 MPKR, 2 LMNCH, 24 VRQR => 8 DZFNW +2 VQDT => 1 KDFNZ +1 CTVK, 6 FDSX => 6 QVNKN +3 CTVK, 1 QVNKN => 4 HPKB +3 NPRST, 1 KGSDJ, 1 CTVK => 2 QMBM +4 KZFPJ, 1 PQZXH => 5 VLWQB +2 VQDT => 7 KGSDJ +3 MPKR => 2 JNKH +1 KQDVM => 5 XQBS +3 ZKGMX, 1 XQBS, 11 MZKG, 11 NPRST, 1 DZFNW, 5 VQDT, 2 FHFH => 6 JQNF +2 FJRFG, 17 BMJR, 3 BJVQM, 55 JQNF, 8 DGFG, 13 ZJGH, 29 ZKTX => 1 FUEL +27 KZFPJ, 5 VJNBT => 5 MQXF +11 FDSX, 1 WHVXC, 1 WJDF => 4 ZKGMX +1 ZVMCB => 4 NWDZ +1 XLFZJ => 6 LGLNV +13 ZSCX, 4 XLFZJ => 8 LMNCH +1 RPWKC, 1 FDSX, 2 BJVQM => 8 JFKGV +1 WJDF, 1 LKPQG => 4 XSNKB diff --git a/src/bin/day_14.rs b/src/bin/day_14.rs new file mode 100644 index 0000000..0532f5f --- /dev/null +++ b/src/bin/day_14.rs @@ -0,0 +1,221 @@ +use rpds::map::red_black_tree_map::RedBlackTreeMap; +use rpds::rbt_map; +use rpds::vector::Vector; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 14: Space Stoichiometry")] +/// Finds how much ore you need to produce one fuel. +/// +/// Recipes are passed in on stdin, one per line. +/// +/// See https://adventofcode.com/2019/day/14 for details. +struct Opt { + #[structopt(long = "available-ore")] + available_ore: Option, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let recipes = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid recipe")) + .collect::>(); + + match opt.available_ore { + Some(ore) => println!("{}", max_fuel_production(ore, &recipes)), + None => println!("{}", Desires::new(1).min_ore_required(&recipes)), + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn max_fuel_production(ore_max: i64, recipes: &[Recipe]) -> i64 { + binary_search_max_fuel_production( + ore_max / Desires::new(1).min_ore_required(&recipes), + 2 * ore_max / Desires::new(1).min_ore_required(&recipes), + ore_max, + recipes, + ) +} + +fn binary_search_max_fuel_production( + fuel_min: i64, + fuel_max: i64, + ore_max: i64, + recipes: &[Recipe], +) -> i64 { + if fuel_max - fuel_min <= 1 { + fuel_min + } else if Desires::new((fuel_min + fuel_max) / 2).min_ore_required(recipes) <= ore_max { + binary_search_max_fuel_production((fuel_min + fuel_max) / 2, fuel_max, ore_max, recipes) + } else { + binary_search_max_fuel_production(fuel_min, (fuel_min + fuel_max) / 2, ore_max, recipes) + } +} + +#[derive(Debug, Clone)] +struct Recipe { + ingredients: Vector, + output: Chemical, +} + +#[derive(Default, Debug, Clone)] +struct Chemical { + name: String, + quantity: i64, +} + +impl FromStr for Recipe { + type Err = ParseErr; + fn from_str(s: &str) -> Result { + // 2 XSNKB, 15 ZVMCB, 3 KDFNZ => 2 RFLX + s.replace(" => ", "=") + .replace(", ", ",") + .split(|c| c == ',' || c == '=') + .map(|chem| chem.parse::()) + .collect::, ParseErr>>() + .map(|chemicals| Recipe { + ingredients: chemicals + .drop_last() + .expect("Assertion failed: line did not have any chemicals"), + output: chemicals + .last() + .cloned() + .expect("Assertion failed: line did not have any chemicals"), + }) + } +} + +impl Recipe { + fn required_scale(&self, desired_quantity: i64) -> i64 { + (desired_quantity + self.output.quantity - 1) / self.output.quantity + } +} + +impl FromStr for Chemical { + type Err = ParseErr; + fn from_str(s: &str) -> Result { + // 1 FUEL + match s.split(' ').collect::>()[..] { + [quantity, name] => quantity + .parse::() + .map_err(|_| ParseErr) + .map(|q| Chemical { + name: name.to_string(), + quantity: q, + }), + _ => Err(ParseErr), + } + } +} + +impl Chemical { + fn scale(&self, scale: i64) -> Chemical { + Chemical { + name: self.name.clone(), + quantity: self.quantity * scale, + } + } +} + +#[derive(Debug, Clone, Copy)] +struct ParseErr; + +impl fmt::Display for ParseErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Error parsing input") + } +} + +impl std::error::Error for ParseErr {} + +#[derive(Debug, Clone)] +struct Desires { + chemicals: RedBlackTreeMap, +} + +impl Desires { + fn new(fuel: i64) -> Desires { + Desires { + chemicals: rbt_map!["FUEL".to_string() => fuel, "ORE".to_string() => 0], + } + } + + fn min_ore_required(&self, recipes: &[Recipe]) -> i64 { + iter::successors(Some(self.clone()), |prev| Some(prev.next(recipes))) + .find(|desires| desires.is_only_ore()) + .unwrap() + .chemicals + .get("ORE") + .cloned() + .unwrap() + } + + fn is_only_ore(&self) -> bool { + !self + .chemicals + .iter() + .any(|(name, quantity)| *quantity > 0 && name != "ORE") + } + + fn next(&self, recipes: &[Recipe]) -> Desires { + self.chemicals + .iter() + .find(|(name, quantity)| **quantity > 0 && *name != "ORE") + .map(|(mixing, quantity)| { + self.with_mixed_recipe( + recipes + .iter() + .find(|recipe| recipe.output.name == *mixing) + .expect("Required chemical without a recipe"), + *quantity, + ) + }) + .unwrap_or(self.clone()) + } + + fn with_mixed_recipe(&self, recipe: &Recipe, desired_quantity: i64) -> Desires { + recipe.ingredients.iter().fold( + self.with_chemical( + recipe + .output + .scale(-1 * recipe.required_scale(desired_quantity)), + ), + |acc, next_ingredient| { + acc.with_chemical(next_ingredient.scale(recipe.required_scale(desired_quantity))) + }, + ) + } + + fn with_chemical(&self, chemical: Chemical) -> Desires { + Desires { + chemicals: match self.chemicals.get(&chemical.name) { + Some(existing_quantity) => self + .chemicals + .insert(chemical.name.clone(), existing_quantity + chemical.quantity), + None => self + .chemicals + .insert(chemical.name.clone(), chemical.quantity), + }, + } + } +} -- cgit v1.2.3 From 5855df0f0d28531bd00709dfb8e2ee7303c22da0 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 23 Dec 2019 00:51:37 +0200 Subject: Day 15 - getting progressively messier... --- inputs/day_15.txt | 1 + src/bin/day_15.rs | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 inputs/day_15.txt create mode 100644 src/bin/day_15.rs diff --git a/inputs/day_15.txt b/inputs/day_15.txt new file mode 100644 index 0000000..ca5836c --- /dev/null +++ b/inputs/day_15.txt @@ -0,0 +1 @@ +3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1002,1034,1,1039,102,1,1036,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,1001,1035,0,1040,1002,1038,1,1043,101,0,1037,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,102,1,1035,1040,1001,1038,0,1043,101,0,1037,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,1,1032,1006,1032,165,1008,1040,9,1032,1006,1032,165,1102,1,2,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1102,1,1,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,35,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,102,1,1039,1034,1002,1040,1,1035,1002,1041,1,1036,102,1,1043,1038,101,0,1042,1037,4,1044,1105,1,0,1,5,41,19,22,1,39,81,29,20,15,82,33,18,45,30,32,55,28,26,70,13,56,32,28,18,3,59,90,11,95,15,85,8,61,25,59,24,34,1,85,5,25,54,57,18,20,54,80,91,28,65,36,12,44,36,13,92,24,56,13,39,69,29,79,10,41,27,23,25,72,20,3,61,15,51,11,12,12,48,10,45,13,29,49,90,30,17,9,41,21,18,7,30,48,17,83,71,4,10,31,10,96,81,77,9,50,39,21,36,33,72,12,3,23,79,18,4,75,17,58,64,8,7,97,60,72,72,1,94,55,42,2,94,2,21,88,19,82,57,96,19,25,27,41,62,15,40,23,61,86,27,73,61,13,46,52,81,12,34,23,73,23,59,1,30,47,9,99,10,37,17,28,98,5,92,73,8,63,4,86,76,79,7,30,68,28,91,12,12,98,74,4,22,44,10,23,45,37,16,90,76,23,74,75,12,21,38,14,15,76,28,49,71,7,6,6,71,53,33,12,87,15,92,66,21,38,13,53,92,34,49,25,6,67,21,27,89,24,61,25,30,41,30,99,28,19,41,90,51,74,14,33,54,48,10,14,42,2,67,76,10,21,2,67,43,27,69,11,16,78,7,36,9,24,48,63,81,53,29,94,34,25,99,66,47,17,97,33,52,11,62,22,52,30,23,89,95,15,13,50,48,26,10,6,69,78,13,6,94,1,28,67,10,70,16,50,19,24,15,79,50,27,3,19,62,4,31,83,20,17,83,67,5,80,26,36,62,87,3,10,80,22,65,60,10,78,4,20,60,30,11,7,83,10,13,72,81,37,22,14,55,63,51,27,32,77,52,20,50,16,48,2,55,10,53,26,84,6,87,43,37,26,3,85,62,25,78,50,16,10,37,22,54,5,80,24,7,32,49,18,27,12,41,70,82,20,34,91,15,98,77,22,6,79,3,8,54,17,32,4,44,2,97,14,15,65,30,97,14,79,75,11,77,5,61,37,20,91,20,45,74,19,40,2,41,89,12,34,44,18,62,57,17,68,22,96,7,59,63,2,60,70,2,26,75,26,3,53,19,80,16,97,7,34,58,52,66,24,75,25,30,75,42,13,12,89,13,3,84,92,1,75,30,54,43,2,56,15,1,15,84,99,6,98,42,17,29,1,18,26,70,71,29,91,23,21,87,66,18,38,32,18,81,65,2,58,99,12,4,84,24,32,88,30,67,49,29,59,64,18,70,10,24,56,5,27,97,50,4,28,85,65,16,67,83,15,16,61,18,86,8,36,25,36,29,97,45,19,81,41,29,45,30,69,26,57,93,27,72,34,30,99,61,2,48,16,12,76,98,28,14,32,32,90,48,10,30,57,23,39,2,8,39,33,13,88,34,31,74,15,60,8,47,60,31,5,79,1,98,86,33,3,99,33,62,11,96,25,22,38,98,84,3,56,70,49,3,8,56,87,4,29,59,65,26,34,77,7,14,78,26,25,70,49,3,31,45,92,24,95,17,4,9,4,96,64,92,27,67,4,99,6,44,7,16,86,2,75,1,6,68,81,4,1,44,49,7,92,8,40,36,25,81,13,56,99,10,2,30,72,6,43,30,12,43,93,19,20,23,95,10,19,66,63,28,96,40,50,8,15,56,38,13,93,42,71,12,18,87,8,4,21,85,9,2,66,77,10,80,26,61,9,43,20,88,10,39,67,55,31,49,17,58,26,80,20,84,54,49,5,73,11,52,15,63,7,62,24,57,92,61,25,87,56,37,31,38,14,99,0,0,21,21,1,10,1,0,0,0,0,0,0 diff --git a/src/bin/day_15.rs b/src/bin/day_15.rs new file mode 100644 index 0000000..b2205bb --- /dev/null +++ b/src/bin/day_15.rs @@ -0,0 +1,183 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::rbt_set; +use rpds::set::red_black_tree_set::RedBlackTreeSet; +use rpds::vector; +use rpds::vector::Vector; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 15: Oxygen System")] +/// Executes an Intcode robot that's searching a map. Prints the +/// time taken for oxygen to propagate to the whole area. +/// +/// See https://adventofcode.com/2019/day/15 for details. +struct Opt { + /// Run in 'find' mode, find the oxygen tank but don't see how long it takes the oxygen to propagate + #[structopt(short = "f")] + find: 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::(), "Invalid number")) + .collect::(); + + if opt.find { + println!("{}", shortest_distance(program)); + } else { + println!("{}", max_depth_from_oxygen(program)); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn shortest_distance(program: IntcodeProgram) -> usize { + iter::successors( + Some(( + rbt_set![(0, 0)], + vector![((0, 0), program.run_to_termination_or_input())], + )), + |(visited, programs)| { + Some(next_depth_states( + visited.clone(), + next_program_states(programs, visited), + )) + }, + ) + .enumerate() + .find(|(_i, (_visited, programs))| { + programs + .iter() + .any(|(_location, program)| program.output == vector![2.into()]) + }) + .unwrap() + .0 +} + +fn max_depth_from_oxygen(program: IntcodeProgram) -> usize { + max_depth( + iter::successors( + Some(( + rbt_set![(0, 0)], + vector![((0, 0), program.run_to_termination_or_input())], + )), + |(visited, programs)| { + Some(next_depth_states( + visited.clone(), + next_program_states(programs, visited), + )) + }, + ) + .find(|(_visited, programs)| { + programs + .iter() + .any(|(_location, program)| program.output == vector![2.into()]) + }) + .unwrap() + .1 + .iter() + .find(|(_location, program)| program.output == vector![2.into()]) + .cloned() + .unwrap() + .1, + ) +} + +fn max_depth(program: IntcodeProgram) -> usize { + iter::successors( + Some(( + rbt_set![(0, 0)], + vector![((0, 0), program.run_to_termination_or_input())], + )), + |(visited, programs)| { + Some(next_depth_states( + visited.clone(), + next_program_states(programs, visited), + )) + }, + ) + .take_while(|(_visited, programs)| programs.len() > 0) + .count() + - 1 +} + +fn inputs() -> [((i32, i32), Intcode); 4] { + [ + ((0, 1), Intcode::from(1)), + ((0, -1), Intcode::from(2)), + ((1, 0), Intcode::from(3)), + ((-1, 0), Intcode::from(4)), + ] +} + +fn next_program_states( + programs: &Vector<((i32, i32), IntcodeProgram)>, + visited: &RedBlackTreeSet<(i32, i32)>, +) -> Vector<((i32, i32), IntcodeProgram)> { + let inputs = inputs(); + programs + .iter() + .flat_map(|(location, program)| { + inputs.iter().map(move |(vec, input)| { + ( + (location.0 + vec.0, location.1 + vec.1), + program + .with_cleared_output() + .with_input(list![input.clone()]) + .run_to_termination_or_input(), + ) + }) + }) + .filter(|(location, program)| { + !visited.contains(location) && program.output != vector![0.into()] + }) + .collect() +} + +fn next_depth_states( + previous_visited: RedBlackTreeSet<(i32, i32)>, + programs: Vector<((i32, i32), IntcodeProgram)>, +) -> ( + RedBlackTreeSet<(i32, i32)>, + Vector<((i32, i32), IntcodeProgram)>, +) { + ( + programs + .iter() + .fold(previous_visited, |acc, (next, _)| acc.insert(*next)), + dedup_locations(programs), + ) +} + +fn dedup_locations( + programs: Vector<((i32, i32), IntcodeProgram)>, +) -> Vector<((i32, i32), IntcodeProgram)> { + programs.iter().fold(Vector::new(), |acc, next| { + if acc.iter().any(|(loc, _)| *loc == next.0) { + acc + } else { + acc.push_back(next.clone()) + } + }) +} -- cgit v1.2.3 From 8039de357a6e8e0e5d4c303ba56b18c57521e60e Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 24 Dec 2019 00:16:53 +0200 Subject: Day 16: Horendously expensive computation... --- Cargo.lock | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + inputs/day_16.txt | 1 + src/bin/day_16.rs | 112 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 259 insertions(+) create mode 100644 inputs/day_16.txt create mode 100644 src/bin/day_16.rs diff --git a/Cargo.lock b/Cargo.lock index 86f88f1..16321a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,7 @@ dependencies = [ "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)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -55,6 +56,11 @@ dependencies = [ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "clap" version = "2.33.0" @@ -69,6 +75,46 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-deque" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive_more" version = "0.99.2" @@ -79,6 +125,11 @@ dependencies = [ "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "heck" version = "0.3.1" @@ -87,6 +138,14 @@ dependencies = [ "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hermit-abi" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "im" version = "14.0.0" @@ -100,11 +159,24 @@ dependencies = [ "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memoffset" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num" version = "0.2.0" @@ -175,6 +247,15 @@ dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num_cpus" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-error" version = "0.2.6" @@ -214,6 +295,28 @@ dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rayon" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rpds" version = "0.7.0" @@ -222,6 +325,32 @@ dependencies = [ "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "sized-chunks" version = "0.5.0" @@ -336,11 +465,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" +"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" "checksum im 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1f9b6540e530defef7f2df4ed330d45b739b10450548c74a9913f63ea1acc6b" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" @@ -348,12 +486,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" +"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" "checksum rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1196a0a2f52d343bd32179834273eaac7d8739f7e3f8b700227d2fa06b9a423b" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62db64dd92b3b54314b1e216c274634ca2b3fe8da8b3873be670cb1ac4dad30f" "checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" diff --git a/Cargo.toml b/Cargo.toml index f3ec006..0b84c43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ im = "14.0.0" rpds = "0.7.0" archery = "0.3.0" num = "0.2" +rayon = "1.3.0" [profile.release] debug = true diff --git a/inputs/day_16.txt b/inputs/day_16.txt new file mode 100644 index 0000000..357965c --- /dev/null +++ b/inputs/day_16.txt @@ -0,0 +1 @@ +59723517898690342336085619027921111260000667417052529433894092649779685557557996383085708903241535436786723718804155370155263736632861535632645335233170435646844328735934063129720822438983948765830873108060969395372667944081201020154126736565212455403582565814037568332106043336657972906297306993727714730061029321153984390658949013821918352341503629705587666779681013358053312990709423156110291835794179056432958537796855287734217125615700199928915524410743382078079059706420865085147514027374485354815106354367548002650415494525590292210440827027951624280115914909910917047084328588833201558964370296841789611989343040407348115608623432403085634084 diff --git a/src/bin/day_16.rs b/src/bin/day_16.rs new file mode 100644 index 0000000..aa53127 --- /dev/null +++ b/src/bin/day_16.rs @@ -0,0 +1,112 @@ +use rayon::prelude::*; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::num::ParseIntError; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 16: Flawed Frequency Transmission")] +/// Performs the flawed frequency transform of a number. +/// +/// See https://adventofcode.com/2019/day/16 for details. +struct Opt { + /// the offset after which you start reading output + #[structopt(short = "o", long = "offset", default_value = "0")] + offset: usize, + input_repeats: usize, + fft_repeats: usize, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(parse(&x), "Input was not a valid recipe")) + .for_each(|input| { + println!( + "{}", + transform(input, opt.input_repeats, opt.fft_repeats, opt.offset) + .into_iter() + .map(|c| c.to_string()) + .collect::() + ); + }); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn parse(s: &str) -> Result, ParseIntError> { + s.chars().map(|c| c.to_string().parse::()).collect() +} + +fn transform(input: Vec, input_repeats: usize, fft_repeats: usize, offset: usize) -> Vec { + iter::successors( + Some( + input + .iter() + .cycle() + .take(input.len() * input_repeats) + .cloned() + .collect::>(), + ), + |input| Some(next_phase(input, offset)), + ) + .nth(fft_repeats) + .unwrap() + .into_iter() + .skip(offset) + .take(8) + .collect() +} + +fn next_phase(input: &Vec, offset: usize) -> Vec { + if offset > input.len() / 2 { + (0..input.len()) + .into_par_iter() + .map(|digit| { + if digit < offset { + 0 + } else { + input.iter().skip(digit).sum::().abs() % 10 + } + }) + .collect() + } else { + (0..input.len()) + .into_par_iter() + .map(|digit| { + input + .iter() + .zip(pattern(digit)) + .map(|(x, y)| x * y) + .sum::() + .abs() + % 10 + }) + .collect() + } +} + +fn pattern(digit: usize) -> impl Iterator { + iter::repeat(0) + .take(digit + 1) + .chain(iter::repeat(1).take(digit + 1)) + .chain(iter::repeat(0).take(digit + 1)) + .chain(iter::repeat(-1).take(digit + 1)) + .cycle() + .skip(1) +} -- cgit v1.2.3 From 65d0a677dfed91d8d08bf6961e8c418a1468566d Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 24 Dec 2019 23:54:53 +0200 Subject: Day 17: The vacuum robot --- inputs/day_17.txt | 1 + src/bin/day_17.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 inputs/day_17.txt create mode 100644 src/bin/day_17.rs diff --git a/inputs/day_17.txt b/inputs/day_17.txt new file mode 100644 index 0000000..49131d4 --- /dev/null +++ b/inputs/day_17.txt @@ -0,0 +1 @@ +1,330,331,332,109,3974,1102,1182,1,15,1101,1475,0,24,1001,0,0,570,1006,570,36,101,0,571,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,15,1,15,1008,15,1475,570,1006,570,14,21102,1,58,0,1105,1,786,1006,332,62,99,21101,333,0,1,21102,73,1,0,1105,1,579,1102,0,1,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,1002,574,1,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21102,340,1,1,1105,1,177,21101,0,477,1,1106,0,177,21102,1,514,1,21101,0,176,0,1106,0,579,99,21102,184,1,0,1105,1,579,4,574,104,10,99,1007,573,22,570,1006,570,165,1002,572,1,1182,21101,0,375,1,21101,0,211,0,1105,1,579,21101,1182,11,1,21102,1,222,0,1106,0,979,21102,1,388,1,21102,1,233,0,1106,0,579,21101,1182,22,1,21101,0,244,0,1105,1,979,21101,0,401,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21102,1,266,0,1106,0,979,21102,414,1,1,21102,277,1,0,1105,1,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21102,1182,1,1,21102,1,313,0,1106,0,622,1005,575,327,1101,1,0,575,21101,327,0,0,1105,1,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,50,26,0,109,4,1201,-3,0,587,20102,1,0,-1,22101,1,-3,-3,21102,0,1,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1106,0,597,109,-4,2106,0,0,109,5,2101,0,-4,630,20101,0,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,653,20101,0,0,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21102,702,1,0,1106,0,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21102,731,1,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21101,756,0,0,1105,1,786,1106,0,774,21202,-1,-11,1,22101,1182,1,1,21102,774,1,0,1105,1,622,21201,-3,1,-3,1106,0,640,109,-5,2105,1,0,109,7,1005,575,802,20102,1,576,-6,20101,0,577,-5,1105,1,814,21101,0,0,-1,21101,0,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,51,-3,22201,-6,-3,-3,22101,1475,-3,-3,2102,1,-3,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1105,1,924,1205,-2,873,21102,1,35,-4,1106,0,924,1202,-3,1,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1101,0,2,0,2101,0,-3,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21002,0,1,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,51,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,49,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1102,1,1,575,21101,973,0,0,1105,1,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,0,1,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1105,1,1041,21102,1,-4,-2,1106,0,1041,21101,0,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,2102,1,-2,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,2102,1,-2,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1106,0,989,21101,0,439,1,1105,1,1150,21101,477,0,1,1106,0,1150,21102,1,514,1,21102,1,1149,0,1105,1,579,99,21101,1157,0,0,1106,0,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,2101,0,-5,1176,2102,1,-4,0,109,-6,2106,0,0,32,5,46,1,3,1,46,1,3,1,46,1,3,1,46,1,3,1,46,1,3,1,40,11,40,1,5,1,44,1,5,1,44,1,5,1,44,1,5,1,44,1,5,1,40,11,40,1,3,1,46,1,3,1,46,1,3,1,46,1,3,9,38,1,11,1,26,1,11,1,11,1,26,1,11,1,11,1,26,1,11,5,7,1,26,1,15,1,7,1,26,1,15,1,7,1,26,1,15,1,7,1,26,1,11,7,5,1,26,1,11,1,3,1,1,1,5,1,26,1,9,13,1,1,3,13,10,1,9,1,1,1,3,1,1,1,3,1,1,1,3,1,22,5,5,1,1,13,3,1,26,1,5,1,5,1,1,1,3,1,5,1,26,1,5,1,5,7,5,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,11,26,1,5,1,34,11,5,1,34,1,15,1,34,1,5,9,1,9,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,22,11,7,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,5,13,11,22 diff --git a/src/bin/day_17.rs b/src/bin/day_17.rs new file mode 100644 index 0000000..9f5d3b8 --- /dev/null +++ b/src/bin/day_17.rs @@ -0,0 +1,85 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::rbt_set; +use rpds::set::red_black_tree_set::RedBlackTreeSet; +use rpds::vector; +use rpds::vector::Vector; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 17: Set and Forget")] +/// Pilots a vacuum robot around on a scaffold. What could go wrong? +/// +/// See https://adventofcode.com/2019/day/17 for details. +struct Opt { + /// Draw the map and exit + #[structopt(short = "d")] + draw_map: 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::(), "Invalid number")) + .collect::(); + + let result = exit_on_failed_assertion( + if opt.draw_map { + program.execute() + } else { + // L,12,L,8,R,10,R,10,L,6,L,4,L,12,L,12,L,8,R,10,R,10,L,6,L,4,L,12,R,10,L,8,L,4,R,10,L,6,L,4,L,12,L,12,L,8,R,10,R,10,R,10,L,8,L,4,R,10,L,6,L,4,L,12,R,10,L,8,L,4,R,10 + // | | || + + let input = vec![ + "A,B,A,B,C,B,A,C,B,C\n", + "L,12,L,8,R,10,R,10\n", + "L,6,L,4,L,12\n", + "R,10,L,8,L,4,R,10\n", + "y\n", + ]; + program + .with_mem_0(Intcode::from(2)) + .with_input( + input + .iter() + .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) + .collect(), + ) + .execute() + }, + "Program failed", + ); + + println!( + "{}", + result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", result.last().unwrap()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} -- cgit v1.2.3 From 60528e663297142ff5adbd83bb2d41df5581251e Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 26 Dec 2019 00:48:20 +0200 Subject: Day 18: part 1 --- inputs/day_18.txt | 81 +++++++++++++++++++++++ src/bin/day_18.rs | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 inputs/day_18.txt create mode 100644 src/bin/day_18.rs diff --git a/inputs/day_18.txt b/inputs/day_18.txt new file mode 100644 index 0000000..3cb4307 --- /dev/null +++ b/inputs/day_18.txt @@ -0,0 +1,81 @@ +################################################################################# +#.............#.....#.................#.#.....#...#.......#...................#a# +#.#####.#######.#.###.#########.#####.#.#.###Y###.#.#####.#.#####.###########.#.# +#.#...#.#.....#.#..c#.........#...#.#...#...#.#...#.#.#...#.#.#...#...#...#.....# +#.#.###.#.###.#.###.#.###########.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.####### +#.#...#...#.#...#.#...#...........#.#...#.#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.....# +#.#.#.#####.#####.#####.###.#######.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.###.# +#.#.#.............#.#...#.#.#..e..#.....#.#...........#...#.#...#...#...#.....#.# +#.#########.#####.#.#.###.#.#.###.#####.#.###############.#T#.#.###############.# +#...#..k....#.....#.#.Z.#...#...#.....#.#.........#.#.....#.#.#.....#.L.....#...# +###.#.#.#######.###.###.#######.#####.#.#########.#.#.###.#.#.###.#.###.###.#.### +#...#.#.#.....#.#...#...#.....#.....#.#.#...#...#.#.#.#...#.#.#...#...#.#...#...# +#.###.#.#.###.#.#.###.###.###.#####.#.#.#.#.#.#.#.#.#.###.#.###.#####.#.#.#####.# +#.#...#.#.#...#.#...#.....#.#.....#.#.#.#.#...#...#.#...#.#.#...#.#...#.#.#.....# +#.###.#.#.#.###.###.#######.#.#####.#.#.#.#########.###.###.#.###.#.###.#.#.###.# +#...#.#.#.#...#...#.........#.#.....#.#.#.............#.......#...#.#...#.#...#.# +###.#.###.###.###.###.#.#####.#.#####.###############.#########.#.#.###.#.###.#.# +#.....#...#...#.J...#.#.#.....#.....#...#...........#.#...#...#.#.......#...#.#.# +#######.###.#######.#.###.#####.#######.#########.#.#.###.#.#.#########.#####.#.# +#.......#.#...#...#...#...#...#.#.......#.....O.#.#.#.#...#.#.......#...#.....#s# +#.#######.###.#.#.#####.###.#.#.#.#######.#####.#.#.#.#.###.#####.#.#.###.#####.# +#...#...#...#...#...#.#.#...#...#.......#.....#.#.#.#.#...#.#...#.#.#...#...#...# +###.#.#.#.#########.#.#.#.#######.#####.#.#####.#.###.###.#.###.###.#.#####.#.### +#.#...#.#.........#...#...#....d#.....#.#.#.....#.#...#...#.#.#...#.#.#.....#.#.# +#.#####.#######.#######.###.###.#####.#.#.#.#####.#.###.#.#.#.###.#.#.#.#####.#.# +#...#.#.......#.......#...#.#...#.....#.#.#.....#.......#.#.....#.#.#.#.#.......# +#.#.#.#######.#.#.#####.###.#.#####.###.#.#####.#############.###.#.#.#.#######.# +#.#...#.....#.#.#...#...#...#.....#...#.#.#...#.#...........#.#...#.#.#.#...#.#.# +#.###.###.#.#.#.###.#.###.#######.#####.#.###.#.#.#########.#.#.###.#.#.#.#.#.#.# +#...#.....#.#.#...#...#...#.......#.....#...#.#.#.....#...#...#...#.#.#...#.#...# +#.#.#######.#.###.#####.###.#######.#######.#.#.#####.###.#######.#.#####.#.#.### +#.#.#.....#.#.#.#.#.#...#.#.#...#...#...#...#.#.....#...#.....#...#.....#.#.#w#.# +#.#.#.###.#.#.#.#.#.#.###.#.#.#.###.#.#.#.###.#.###.###.#.###.#.###.###.###.#.#.# +#.#.#.#.#.#.#.#.#.#.#.#m..#...#...#...#.#.#...#...#...#.#...#.#.#.....#.#...#.#.# +###.#.#.#.###W#.#.#.#.#.#########.#####.#.#.#.###.#####.###.#.#.#######.#.###.#.# +#...#...#.#...#.....#.#.......#...#...#.#.#.#.#.#.....#.....#.#.........#.#.#...# +#.###.###.#.###.#####.#.###.###.###.#.#.#.#.#.#.#####.#######.###########.#.###.# +#.#...#...#.#...#.S...#...#.....#...#.#.#...#.....#.#.........#...#...#...#.....# +#.#.###.###.#####.#######.#######.###.#.#########.#.###########.#.#.#.#.###.##### +#.....#...........#.......F.......#..................f..........#...#...#.......# +#######################################.@.####################################### +#.....#.#...........#.....#.........................#...#.....#.M.......#.....#.# +###P#.#.#.#######.###.###.#.#######.###.#.#########.#.#.#.###.###.#####.###.#.#.# +#...#...#...#.#...#.....#.#.#.......#...#...#.........#...#.......#...#.....#.#.# +#.#.#######.#.#.###.#####.#.#.#######.#####.###############.#########.#######.#.# +#.#.#.....#.#.#.#...#...#.#.#.#.........#...#.......#...#.....#.....#.#.......#.# +#.###.###.#.#.#.#.###.#.#.#.#.###########.###.#####.#.#.#######.###.#.#.#######.# +#...#.#.#.#...#.#.#...#...#.#...........#...#...#.#...#.......#.#.#.#.#.........# +#.#.#.#.#.#.###.#.#.#####.#######.#####.###.###.#.###########.#.#.#.#.#.#######.# +#.#.#...#...#...#.#r#.....#.....#.....#.#...#.#.#.......#...#.....#.#...#.....#.# +#.#.###.#####.###.#.#######.###.#####.#.#.#.#.#.###.#####.#.#######.#.###.###.#.# +#.#...#.#...#...#.#.........#...#...#.#.#.#...#...#.#.....#.#......p#...#.#.#.#.# +###.#.#.#.#.###.#.###########.###.#.#.#.#.###.###.#.#.#####.#.###.#######.#.#.### +#...#.#.#.#...#.......#.....#.#...#...#.#...#.#...#.....#...#.#...#.K...#.#.#...# +#.#####.#.###.#######.#.###Q#.#.#######.###.#.#.#####.###.###.#.###.###.#.#.###.# +#.....#...#...#.#...#.#.#.#...#...#.....#...#.#.....#.#...#...#.#...#.#..j#.#...# +#.###.#####.###.#.#.###.#.#########.###.#.#########.###.#.#.###.#.###.#####.#.### +#...#.#.....#...#.#.B...#...#...#...#...#.#.......#.....#.#...#.#...........#.R.# +#.###.#.#######.#.#######.#.#.#.#.###.###.#.#.###.#######.###.###.#############.# +#.#...#.......#.#n....#...#.#.#...#...#.#...#...#.....#...#.#.....#..u..#.....#.# +###.#.#######.#.#####.#.###.#.#####.###.#.#####.###.###.###.###.###.###.#.###.#.# +#...#.#...#...#.....#.#.#...#...#.#...#.#...#...#...#...#...#.#.#...#...#.#...#.# +#.#####.#.#.###.#.#####.#.###.#.#.###.#.#####.#######.#####.#.###.###.###.###.#.# +#...#...#.#.#...#.......#.#...#.#...#...#.....#.......#.....#.U...#.#...#...#...# +#.#.#.###.#.#.#########.#.#####.###.###.#.#.###.#######.###########.###X#.#.###.# +#.#..l#...#.#...#.......#.....#...#...#.#.#o#...#.#.....#...#......x....#.#.#...# +#.#####C###.#.###.###########.###.#.###.#.###.###.#.###.#.#.#I#############.#.### +#.....#...#.#.#...#...#.....#.#...#.#...#.#...#.....#...#.#...#v......G.#...#..q# +###.#####.#.###.###.#.#.###.#.#.###.#.###.#.###.#####.#.#.#####.#######.#.#####.# +#.#y#...#.#...#.#...#.#...#.#...#...#...#.#.#...#.....#.#..i..#...#.....#...#...# +#.#.#.#.#.###.#.#.###.#.#.#.#####.#.###.#.#.###.#.###########H#.#.#.#####.#.#.### +#...#.#.#...#.#.....#.#.#.#.#...#.#.....#.#...#.#...........#.#.#.#g..#...#.#...# +#.###.#.###A#.#######.#.#.#.#.###.#######.###.#.#########.#.#.#.#.###.#####.###.# +#.#...#.....#.........#.#.#.#.#...#.....#...#.#.......#...#.#.#.#.#.#.#...#...#.# +###.#####################.#.#.#.#####.###.#.#.#########.###.#.###.#.#.#.#.###.#.# +#...#.......#.............#..t#.#...#...#.#.#.#.......#.#...#...#.#.#.N.#.....#.# +#.###.#####.#.#########.#######.#.#D#.#.#.#.#.#.#####.#.#.#####.#.#.###########.# +#.#...#...#..z#.#.......#.....#...#.#.#.#.#.#...#...#...#.#.#..h#.#.....#......b# +#.#.###.#.#####.#.#######.###.#####.###.#.#.#####.#.#####.#.#.###.#.###.#.####### +#.......#.......#...........#...........#.#.....E.#.........#...V.#...#.........# +################################################################################# diff --git a/src/bin/day_18.rs b/src/bin/day_18.rs new file mode 100644 index 0000000..71886a2 --- /dev/null +++ b/src/bin/day_18.rs @@ -0,0 +1,194 @@ +use rpds::rbt_set; +use rpds::vector; +use rpds::vector::Vector; +use rpds::RedBlackTreeSet; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 18: Many-Worlds Interpretation")] +/// Finds the shortest path through a maze with keys +/// +/// See https://adventofcode.com/2019/day/18 for details. +struct Opt {} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let maze: Maze = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .collect(); + + println!("{}", maze.shortest_route()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +struct Maze { + blocks: Vec>, + start: Location, + keys: RedBlackTreeSet, +} + +impl FromIterator for Maze { + fn from_iter>(iter: T) -> Self { + Maze::from_blocks( + iter.into_iter() + .map(|line| line.chars().collect()) + .collect(), + ) + } +} + +impl Maze { + fn from_blocks(blocks: Vec>) -> Maze { + Maze { + start: blocks + .iter() + .enumerate() + .filter_map(|(y, line)| { + line.iter() + .enumerate() + .find(|(x, ch)| **ch == '@') + .map(|(x, _ch)| Location { + x, + y, + keys: RedBlackTreeSet::new(), + }) + }) + .next() + .unwrap_or(Location::default()), + keys: blocks + .iter() + .flat_map(|line| line.iter()) + .filter(|c| c.is_lowercase() && c.is_alphabetic()) + .cloned() + .collect(), + blocks, + } + } + + fn block_at(&self, location: &Location) -> Option { + self.blocks + .get(location.y) + .and_then(|line| line.get(location.x)) + .cloned() + } + + fn shortest_route(&self) -> usize { + iter::successors( + Some((rbt_set![self.start.clone()], vector![self.start.clone()])), + |(explored, locations)| { + Some(Maze::next_depth_states( + explored.clone(), + self.next_locations(locations, explored), + )) + }, + ) + // .inspect(|(explored, locations)| eprintln!("{:?}", explored.size())) + .take_while(|(_explored, locations)| locations.len() > 0) + .enumerate() + .find(|(_i, (_explored, locations))| { + locations.iter().any(|location| location.keys == self.keys) + }) + .unwrap() + .0 + } + + fn next_depth_states( + explored: RedBlackTreeSet, + locations: Vector, + ) -> (RedBlackTreeSet, Vector) { + ( + locations + .iter() + .fold(explored, |acc, next| acc.insert(next.clone())), + Maze::dedup_locations(locations), + ) + } + + fn dedup_locations(locations: Vector) -> Vector { + locations.iter().fold(Vector::new(), |acc, next| { + if acc.iter().any(|loc| loc == next) { + acc + } else { + acc.push_back(next.clone()) + } + }) + } + + fn next_locations( + &self, + locations: &Vector, + explored: &RedBlackTreeSet, + ) -> Vector { + locations + .iter() + .flat_map(|current| { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .iter() + .map(move |(dx, dy)| current.next(*dx, *dy)) + .map(move |location| { + self.block_at(&location) + .map(|c| location.with_key(c)) + .unwrap_or(location) + }) + }) + .filter(|location| self.is_open(location)) + .filter(|location| !explored.contains(location)) + .collect() + } + + fn is_open(&self, location: &Location) -> bool { + self.block_at(location) + .map(|c| Maze::char_is_open(c, &location.keys)) + .unwrap_or(false) + } + + fn char_is_open(c: char, keys: &RedBlackTreeSet) -> bool { + c != '#' + && (!c.is_uppercase() || !c.is_alphabetic() || keys.contains(&c.to_ascii_lowercase())) + } +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct Location { + x: usize, + y: usize, + keys: RedBlackTreeSet, +} + +impl Location { + fn next(&self, dx: isize, dy: isize) -> Location { + Location { + x: (self.x as isize + dx) as usize, + y: (self.y as isize + dy) as usize, + ..self.clone() + } + } + fn with_key(&self, c: char) -> Location { + if c.is_lowercase() && c.is_alphabetic() { + Location { + keys: self.keys.insert(c), + ..self.clone() + } + } else { + self.clone() + } + } +} -- cgit v1.2.3 From 7b994344a3fe38fa0e59109070be169ceeda06e1 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 26 Dec 2019 14:23:22 +0200 Subject: Day 18 part 2. This needed some optimization --- inputs/day_18_2.txt | 81 ++++++++++++++ readme.org | 6 +- src/bin/day_18.rs | 315 ++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 330 insertions(+), 72 deletions(-) create mode 100644 inputs/day_18_2.txt diff --git a/inputs/day_18_2.txt b/inputs/day_18_2.txt new file mode 100644 index 0000000..8fda759 --- /dev/null +++ b/inputs/day_18_2.txt @@ -0,0 +1,81 @@ +################################################################################# +#.............#.....#.................#.#.....#...#.......#...................#a# +#.#####.#######.#.###.#########.#####.#.#.###Y###.#.#####.#.#####.###########.#.# +#.#...#.#.....#.#..c#.........#...#.#...#...#.#...#.#.#...#.#.#...#...#...#.....# +#.#.###.#.###.#.###.#.###########.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.####### +#.#...#...#.#...#.#...#...........#.#...#.#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.....# +#.#.#.#####.#####.#####.###.#######.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.###.# +#.#.#.............#.#...#.#.#..e..#.....#.#...........#...#.#...#...#...#.....#.# +#.#########.#####.#.#.###.#.#.###.#####.#.###############.#T#.#.###############.# +#...#..k....#.....#.#.Z.#...#...#.....#.#.........#.#.....#.#.#.....#.L.....#...# +###.#.#.#######.###.###.#######.#####.#.#########.#.#.###.#.#.###.#.###.###.#.### +#...#.#.#.....#.#...#...#.....#.....#.#.#...#...#.#.#.#...#.#.#...#...#.#...#...# +#.###.#.#.###.#.#.###.###.###.#####.#.#.#.#.#.#.#.#.#.###.#.###.#####.#.#.#####.# +#.#...#.#.#...#.#...#.....#.#.....#.#.#.#.#...#...#.#...#.#.#...#.#...#.#.#.....# +#.###.#.#.#.###.###.#######.#.#####.#.#.#.#########.###.###.#.###.#.###.#.#.###.# +#...#.#.#.#...#...#.........#.#.....#.#.#.............#.......#...#.#...#.#...#.# +###.#.###.###.###.###.#.#####.#.#####.###############.#########.#.#.###.#.###.#.# +#.....#...#...#.J...#.#.#.....#.....#...#...........#.#...#...#.#.......#...#.#.# +#######.###.#######.#.###.#####.#######.#########.#.#.###.#.#.#########.#####.#.# +#.......#.#...#...#...#...#...#.#.......#.....O.#.#.#.#...#.#.......#...#.....#s# +#.#######.###.#.#.#####.###.#.#.#.#######.#####.#.#.#.#.###.#####.#.#.###.#####.# +#...#...#...#...#...#.#.#...#...#.......#.....#.#.#.#.#...#.#...#.#.#...#...#...# +###.#.#.#.#########.#.#.#.#######.#####.#.#####.#.###.###.#.###.###.#.#####.#.### +#.#...#.#.........#...#...#....d#.....#.#.#.....#.#...#...#.#.#...#.#.#.....#.#.# +#.#####.#######.#######.###.###.#####.#.#.#.#####.#.###.#.#.#.###.#.#.#.#####.#.# +#...#.#.......#.......#...#.#...#.....#.#.#.....#.......#.#.....#.#.#.#.#.......# +#.#.#.#######.#.#.#####.###.#.#####.###.#.#####.#############.###.#.#.#.#######.# +#.#...#.....#.#.#...#...#...#.....#...#.#.#...#.#...........#.#...#.#.#.#...#.#.# +#.###.###.#.#.#.###.#.###.#######.#####.#.###.#.#.#########.#.#.###.#.#.#.#.#.#.# +#...#.....#.#.#...#...#...#.......#.....#...#.#.#.....#...#...#...#.#.#...#.#...# +#.#.#######.#.###.#####.###.#######.#######.#.#.#####.###.#######.#.#####.#.#.### +#.#.#.....#.#.#.#.#.#...#.#.#...#...#...#...#.#.....#...#.....#...#.....#.#.#w#.# +#.#.#.###.#.#.#.#.#.#.###.#.#.#.###.#.#.#.###.#.###.###.#.###.#.###.###.###.#.#.# +#.#.#.#.#.#.#.#.#.#.#.#m..#...#...#...#.#.#...#...#...#.#...#.#.#.....#.#...#.#.# +###.#.#.#.###W#.#.#.#.#.#########.#####.#.#.#.###.#####.###.#.#.#######.#.###.#.# +#...#...#.#...#.....#.#.......#...#...#.#.#.#.#.#.....#.....#.#.........#.#.#...# +#.###.###.#.###.#####.#.###.###.###.#.#.#.#.#.#.#####.#######.###########.#.###.# +#.#...#...#.#...#.S...#...#.....#...#.#.#...#.....#.#.........#...#...#...#.....# +#.#.###.###.#####.#######.#######.###.#.#########.#.###########.#.#.#.#.###.##### +#.....#...........#.......F.......#....@#@...........f..........#...#...#.......# +################################################################################# +#.....#.#...........#.....#............@#@..........#...#.....#.M.......#.....#.# +###P#.#.#.#######.###.###.#.#######.###.#.#########.#.#.#.###.###.#####.###.#.#.# +#...#...#...#.#...#.....#.#.#.......#...#...#.........#...#.......#...#.....#.#.# +#.#.#######.#.#.###.#####.#.#.#######.#####.###############.#########.#######.#.# +#.#.#.....#.#.#.#...#...#.#.#.#.........#...#.......#...#.....#.....#.#.......#.# +#.###.###.#.#.#.#.###.#.#.#.#.###########.###.#####.#.#.#######.###.#.#.#######.# +#...#.#.#.#...#.#.#...#...#.#...........#...#...#.#...#.......#.#.#.#.#.........# +#.#.#.#.#.#.###.#.#.#####.#######.#####.###.###.#.###########.#.#.#.#.#.#######.# +#.#.#...#...#...#.#r#.....#.....#.....#.#...#.#.#.......#...#.....#.#...#.....#.# +#.#.###.#####.###.#.#######.###.#####.#.#.#.#.#.###.#####.#.#######.#.###.###.#.# +#.#...#.#...#...#.#.........#...#...#.#.#.#...#...#.#.....#.#......p#...#.#.#.#.# +###.#.#.#.#.###.#.###########.###.#.#.#.#.###.###.#.#.#####.#.###.#######.#.#.### +#...#.#.#.#...#.......#.....#.#...#...#.#...#.#...#.....#...#.#...#.K...#.#.#...# +#.#####.#.###.#######.#.###Q#.#.#######.###.#.#.#####.###.###.#.###.###.#.#.###.# +#.....#...#...#.#...#.#.#.#...#...#.....#...#.#.....#.#...#...#.#...#.#..j#.#...# +#.###.#####.###.#.#.###.#.#########.###.#.#########.###.#.#.###.#.###.#####.#.### +#...#.#.....#...#.#.B...#...#...#...#...#.#.......#.....#.#...#.#...........#.R.# +#.###.#.#######.#.#######.#.#.#.#.###.###.#.#.###.#######.###.###.#############.# +#.#...#.......#.#n....#...#.#.#...#...#.#...#...#.....#...#.#.....#..u..#.....#.# +###.#.#######.#.#####.#.###.#.#####.###.#.#####.###.###.###.###.###.###.#.###.#.# +#...#.#...#...#.....#.#.#...#...#.#...#.#...#...#...#...#...#.#.#...#...#.#...#.# +#.#####.#.#.###.#.#####.#.###.#.#.###.#.#####.#######.#####.#.###.###.###.###.#.# +#...#...#.#.#...#.......#.#...#.#...#...#.....#.......#.....#.U...#.#...#...#...# +#.#.#.###.#.#.#########.#.#####.###.###.#.#.###.#######.###########.###X#.#.###.# +#.#..l#...#.#...#.......#.....#...#...#.#.#o#...#.#.....#...#......x....#.#.#...# +#.#####C###.#.###.###########.###.#.###.#.###.###.#.###.#.#.#I#############.#.### +#.....#...#.#.#...#...#.....#.#...#.#...#.#...#.....#...#.#...#v......G.#...#..q# +###.#####.#.###.###.#.#.###.#.#.###.#.###.#.###.#####.#.#.#####.#######.#.#####.# +#.#y#...#.#...#.#...#.#...#.#...#...#...#.#.#...#.....#.#..i..#...#.....#...#...# +#.#.#.#.#.###.#.#.###.#.#.#.#####.#.###.#.#.###.#.###########H#.#.#.#####.#.#.### +#...#.#.#...#.#.....#.#.#.#.#...#.#.....#.#...#.#...........#.#.#.#g..#...#.#...# +#.###.#.###A#.#######.#.#.#.#.###.#######.###.#.#########.#.#.#.#.###.#####.###.# +#.#...#.....#.........#.#.#.#.#...#.....#...#.#.......#...#.#.#.#.#.#.#...#...#.# +###.#####################.#.#.#.#####.###.#.#.#########.###.#.###.#.#.#.#.###.#.# +#...#.......#.............#..t#.#...#...#.#.#.#.......#.#...#...#.#.#.N.#.....#.# +#.###.#####.#.#########.#######.#.#D#.#.#.#.#.#.#####.#.#.#####.#.#.###########.# +#.#...#...#..z#.#.......#.....#...#.#.#.#.#.#...#...#...#.#.#..h#.#.....#......b# +#.#.###.#.#####.#.#######.###.#####.###.#.#.#####.#.#####.#.#.###.#.###.#.####### +#.......#.......#...........#...........#.#.....E.#.........#...V.#...#.........# +################################################################################# diff --git a/readme.org b/readme.org index 936550a..e189346 100644 --- a/readme.org +++ b/readme.org @@ -18,4 +18,8 @@ program should only be pure expressions. - Using "new type" structs can be a pain. derive_more crate made most of that pain go away. - With immutable types, 'reset the machine to try again' type - constraints were handled for free. + constraints were handled for free. This made many later puzzles easier. +- The 'no statement' constraint meant that some functions ended up + nested in a way that makes it harder to name and read. +- The persistent data structures don't integrate with Rayon iterators. +- Easier to test subsets, but harder to inspect and audit runtime behaviour. diff --git a/src/bin/day_18.rs b/src/bin/day_18.rs index 71886a2..8714e4f 100644 --- a/src/bin/day_18.rs +++ b/src/bin/day_18.rs @@ -1,6 +1,8 @@ +use rayon::prelude::*; use rpds::rbt_set; use rpds::vector; use rpds::vector::Vector; +use rpds::RedBlackTreeMap; use rpds::RedBlackTreeSet; use std::io; use std::io::prelude::*; @@ -18,7 +20,7 @@ struct Opt {} fn main() { let stdin = io::stdin(); - let opt = Opt::from_args(); + let _opt = Opt::from_args(); let maze: Maze = stdin .lock() @@ -41,8 +43,8 @@ fn exit_on_failed_assertion(data: Result, message struct Maze { blocks: Vec>, - start: Location, - keys: RedBlackTreeSet, + start: BoardState, + keys: KeySet, } impl FromIterator for Maze { @@ -58,27 +60,23 @@ impl FromIterator for Maze { impl Maze { fn from_blocks(blocks: Vec>) -> Maze { Maze { - start: blocks - .iter() - .enumerate() - .filter_map(|(y, line)| { - line.iter() - .enumerate() - .find(|(x, ch)| **ch == '@') - .map(|(x, _ch)| Location { - x, - y, - keys: RedBlackTreeSet::new(), - }) - }) - .next() - .unwrap_or(Location::default()), + start: BoardState { + robots: blocks + .iter() + .enumerate() + .flat_map(|(y, line)| { + line.iter() + .enumerate() + .filter(|(_x, ch)| **ch == '@') + .map(move |(x, _ch)| Location { x, y }) + }) + .collect(), + keys: KeySet::default(), + }, keys: blocks .iter() .flat_map(|line| line.iter()) - .filter(|c| c.is_lowercase() && c.is_alphabetic()) - .cloned() - .collect(), + .fold(KeySet::default(), |acc, next| acc.add_key(*next)), blocks, } } @@ -92,7 +90,10 @@ impl Maze { fn shortest_route(&self) -> usize { iter::successors( - Some((rbt_set![self.start.clone()], vector![self.start.clone()])), + Some(( + ExploredStates::default().insert(&self.start), + rbt_set![self.start.clone()], + )), |(explored, locations)| { Some(Maze::next_depth_states( explored.clone(), @@ -100,69 +101,138 @@ impl Maze { )) }, ) - // .inspect(|(explored, locations)| eprintln!("{:?}", explored.size())) - .take_while(|(_explored, locations)| locations.len() > 0) + // .inspect(|(explored, states)| eprintln!("{:?}", states)) + .take_while(|(_explored, states)| states.size() > 0) .enumerate() - .find(|(_i, (_explored, locations))| { - locations.iter().any(|location| location.keys == self.keys) - }) + .find(|(_i, (_explored, states))| states.iter().any(|state| state.keys == self.keys)) .unwrap() .0 } fn next_depth_states( - explored: RedBlackTreeSet, - locations: Vector, - ) -> (RedBlackTreeSet, Vector) { + explored: ExploredStates, + locations: RedBlackTreeSet, + ) -> (ExploredStates, RedBlackTreeSet) { ( locations .iter() - .fold(explored, |acc, next| acc.insert(next.clone())), - Maze::dedup_locations(locations), + .fold(explored, |acc, next| acc.insert(next)), + locations, ) } - fn dedup_locations(locations: Vector) -> Vector { - locations.iter().fold(Vector::new(), |acc, next| { - if acc.iter().any(|loc| loc == next) { - acc - } else { - acc.push_back(next.clone()) - } - }) - } - fn next_locations( &self, - locations: &Vector, - explored: &RedBlackTreeSet, - ) -> Vector { + locations: &RedBlackTreeSet, + explored: &ExploredStates, + ) -> RedBlackTreeSet { locations .iter() .flat_map(|current| { - [(-1, 0), (1, 0), (0, -1), (0, 1)] - .iter() - .map(move |(dx, dy)| current.next(*dx, *dy)) - .map(move |location| { - self.block_at(&location) - .map(|c| location.with_key(c)) - .unwrap_or(location) - }) + (0..current.robots.len()).flat_map(move |i_robot| { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .iter() + .map(move |(dx, dy)| current.next(i_robot, *dx, *dy)) + .map(move |(state, new_location)| { + self.block_at(&new_location) + .map(|c| state.with_key(c)) + .unwrap_or(state) + }) + }) }) - .filter(|location| self.is_open(location)) - .filter(|location| !explored.contains(location)) + .filter(|state| self.is_open(state)) + .filter(|state| !explored.contains(state)) .collect() } - fn is_open(&self, location: &Location) -> bool { - self.block_at(location) - .map(|c| Maze::char_is_open(c, &location.keys)) - .unwrap_or(false) + fn is_open(&self, state: &BoardState) -> bool { + state.robots.iter().all(|location| { + self.block_at(location) + .map(|c| Maze::char_is_open(c, state.keys)) + .unwrap_or(false) + }) + } + + fn char_is_open(c: char, keys: KeySet) -> bool { + c != '#' && !keys.door_is_locked(c) + } +} + +#[derive(Default, Debug, Clone)] +struct ExploredStates { + for_key: RedBlackTreeMap, +} + +#[derive(Default, Debug, Clone)] +struct ExploredStatesForKey { + robots: Vector>, +} + +impl ExploredStates { + fn insert(&self, new: &BoardState) -> ExploredStates { + ExploredStates { + for_key: self.for_key.insert( + new.keys.clone(), + self.for_key + .get(&new.keys) + .map(|current| ExploredStatesForKey { + robots: current + .robots + .iter() + .zip(new.robots.iter()) + .map(|(current_explored, robot)| current_explored.insert(robot.clone())) + .collect(), + }) + .unwrap_or_else(|| ExploredStatesForKey { + robots: new + .robots + .iter() + .map(|robot| RedBlackTreeSet::new().insert(robot.clone())) + .collect(), + }), + ), + } + } + + fn contains(&self, state: &BoardState) -> bool { + self.for_key + .get(&state.keys) + .filter(|for_key| { + state + .robots + .iter() + .zip(for_key.robots.iter()) + .all(|(r_state, r_explored)| r_explored.contains(r_state)) + }) + .is_some() + } +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct BoardState { + robots: Vector, + keys: KeySet, +} + +impl BoardState { + fn next(&self, i_robot: usize, dx: isize, dy: isize) -> (BoardState, Location) { + ( + BoardState { + robots: self + .robots + .set(i_robot, self.robots[i_robot].next(dx, dy)) + .unwrap(), + ..self.clone() + }, + self.robots[i_robot].next(dx, dy), + ) } - fn char_is_open(c: char, keys: &RedBlackTreeSet) -> bool { - c != '#' - && (!c.is_uppercase() || !c.is_alphabetic() || keys.contains(&c.to_ascii_lowercase())) + fn with_key(&self, c: char) -> BoardState { + BoardState { + keys: self.keys.add_key(c), + ..self.clone() + } } } @@ -170,7 +240,6 @@ impl Maze { struct Location { x: usize, y: usize, - keys: RedBlackTreeSet, } impl Location { @@ -178,17 +247,121 @@ impl Location { Location { x: (self.x as isize + dx) as usize, y: (self.y as isize + dy) as usize, - ..self.clone() } } - fn with_key(&self, c: char) -> Location { - if c.is_lowercase() && c.is_alphabetic() { - Location { - keys: self.keys.insert(c), - ..self.clone() - } +} + +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct KeySet { + bitset: u32, +} + +impl KeySet { + fn add_key(self, key: char) -> KeySet { + KeySet { + bitset: self.bitset | KeySet::key_to_bitset(key), + } + } + + fn door_is_locked(self, door: char) -> bool { + KeySet::door_to_bitset(door) & (!self.bitset) > 0 + } + + fn key_to_bitset(key: char) -> u32 { + if key.is_ascii_alphabetic() && key.is_ascii_lowercase() { + 1 << (key as u8 - b'a') } else { - self.clone() + 0 } } + + fn door_to_bitset(door: char) -> u32 { + if door.is_ascii_alphabetic() && door.is_ascii_uppercase() { + 1 << (door as u8 - b'A') + } else { + 0 + } + } +} + +#[test] +fn doors_are_locked_without_key() { + assert_eq!(true, KeySet::default().door_is_locked('A')) +} + +#[test] +fn doors_are_unlocked_with_key() { + assert_eq!(false, KeySet::default().add_key('a').door_is_locked('A')) +} + +#[test] +fn example_1() { + let maze: Maze = r" +######### +#b.A.@.a# +######### +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 8); +} + +#[test] +fn example_2() { + let maze: Maze = r" +################# +#i.G..c...e..H.p# +########.######## +#j.A..b...f..D.o# +########@######## +#k.E..a...g..B.n# +########.######## +#l.F..d...h..C.m# +################# +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 136); +} + +#[test] +fn example_3() { + let maze: Maze = r" +############# +#DcBa.#.GhKl# +#.###@#@#I### +#e#d#####j#k# +###C#@#@###J# +#fEbA.#.FgHi# +############# +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 32); +} + +#[test] +fn example_4() { + let maze: Maze = r" +############# +#g#f.D#..h#l# +#F###e#E###.# +#dCba@#@BcIJ# +############# +#nK.L@#@G...# +#M###N#H###.# +#o#m..#i#jk.# +############# +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 74); } -- cgit v1.2.3 From f5f3547a30427c0c0c96fa657af1b62fa68aedce Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 26 Dec 2019 16:52:34 +0200 Subject: Day 19: Tractor beam! --- Cargo.lock | 16 +++++++++ Cargo.toml | 1 + inputs/day_19.txt | 1 + src/bin/day_18.rs | 1 - src/bin/day_19.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 inputs/day_19.txt create mode 100644 src/bin/day_19.rs diff --git a/Cargo.lock b/Cargo.lock index 16321a7..02e042e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,7 @@ name = "aoc2019" version = "0.1.0" dependencies = [ "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cached 0.11.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)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -56,6 +57,14 @@ dependencies = [ "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cached" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -256,6 +265,11 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "once_cell" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro-error" version = "0.2.6" @@ -465,6 +479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" +"checksum cached 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b052fd10f32987c3bd028d91ef86190b36fba5c8fccb5515d42083f061e6104" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" @@ -487,6 +502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" +"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" diff --git a/Cargo.toml b/Cargo.toml index 0b84c43..a5c6e6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ rpds = "0.7.0" archery = "0.3.0" num = "0.2" rayon = "1.3.0" +cached = "0.11.0" [profile.release] debug = true diff --git a/inputs/day_19.txt b/inputs/day_19.txt new file mode 100644 index 0000000..e85881e --- /dev/null +++ b/inputs/day_19.txt @@ -0,0 +1 @@ +109,424,203,1,21102,11,1,0,1106,0,282,21101,0,18,0,1106,0,259,1201,1,0,221,203,1,21102,1,31,0,1106,0,282,21101,0,38,0,1106,0,259,20102,1,23,2,21202,1,1,3,21101,1,0,1,21101,0,57,0,1105,1,303,2101,0,1,222,20101,0,221,3,21001,221,0,2,21102,1,259,1,21101,0,80,0,1105,1,225,21101,185,0,2,21102,91,1,0,1106,0,303,1202,1,1,223,21001,222,0,4,21102,259,1,3,21101,225,0,2,21102,1,225,1,21101,0,118,0,1106,0,225,20102,1,222,3,21102,1,131,2,21101,133,0,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1105,1,259,2101,0,1,223,21002,221,1,4,21002,222,1,3,21101,0,16,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21101,0,195,0,106,0,109,20207,1,223,2,20101,0,23,1,21102,1,-1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,1201,-4,0,249,22101,0,-3,1,22101,0,-2,2,21201,-1,0,3,21101,0,250,0,1106,0,225,21201,1,0,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22102,1,-2,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,21201,-2,0,3,21101,343,0,0,1106,0,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,22101,0,-4,1,21102,384,1,0,1106,0,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21201,1,0,-4,109,-5,2106,0,0 diff --git a/src/bin/day_18.rs b/src/bin/day_18.rs index 8714e4f..34db7f9 100644 --- a/src/bin/day_18.rs +++ b/src/bin/day_18.rs @@ -1,4 +1,3 @@ -use rayon::prelude::*; use rpds::rbt_set; use rpds::vector; use rpds::vector::Vector; diff --git a/src/bin/day_19.rs b/src/bin/day_19.rs new file mode 100644 index 0000000..d5ee7f2 --- /dev/null +++ b/src/bin/day_19.rs @@ -0,0 +1,105 @@ +use aoc2019::*; +use cached::cached_key; +use cached::UnboundCache; +use rpds::list; +use rpds::list::List; +use rpds::vector; +use rpds::vector::Vector; +use std::collections::HashMap; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 19: Tractor Beam")] +/// Finds the effective area of a tractor beam in an n x n square, and +/// how far away you need to be to capture Santa's ship. +/// +/// See https://adventofcode.com/2019/day/19 for details. +struct Opt { + /// The size for a diagnostics scan. + #[structopt(long = "diagnostics-size")] + diagnostics_size: Option, + /// The size of Santa's ship + #[structopt(long = "ship-size")] + ship_size: 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::(); + + if let Some(size) = opt.diagnostics_size { + println!("{}", count_active_in_area(program.clone(), 0, 0, size)); + } + if let Some(size) = opt.ship_size { + println!("{:?}", find_closest_ship_space(program, size)) + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn count_active_in_area(program: IntcodeProgram, left: usize, top: usize, size: usize) -> usize { + (left..left + size) + .flat_map(|x| (top..top + size).map(move |y| (x, y))) + .filter(|(x, y)| tractor_beam_is_active(program.clone(), *x, *y)) + .count() +} + +fn area_is_all_full(program: IntcodeProgram, left: usize, top: usize, size: usize) -> bool { + // This check with a grid that's aligned to 10 gives an early exit + // for most, that will have the program executions shared. This + // makes the memoized tractor function more effective at cutting + // down on execution, even though you need to do the whole lot + // again to verify if this passes. + (left..left + size) + .flat_map(|x| (top..top + size).map(move |y| (x, y))) + .filter(|(x, y)| x % 10 == 0 && y % 10 == 0) + .all(|(x, y)| tractor_beam_is_active(program.clone(), x, y)) + && (left..left + size) + .flat_map(|x| (top..top + size).map(move |y| (x, y))) + .all(|(x, y)| tractor_beam_is_active(program.clone(), x, y)) +} + +fn find_closest_ship_space(program: IntcodeProgram, size: usize) -> (usize, usize) { + (0..) + .flat_map(|radius| { + (0..radius) + .flat_map(move |x| (0..radius).map(move |y| (x, y))) + .filter(move |(x, y)| { + (radius - 1) * (radius - 1) < x * x + y * y && x * x + y * y <= radius * radius + }) + }) + .find(|(x, y)| area_is_all_full(program.clone(), *x, *y, size)) + .unwrap() +} + +cached_key! { + TRACTOR_BEAM_IS_ACTIVE: UnboundCache<(usize, usize), bool> = UnboundCache::new(); + Key = { (x, y) }; + fn tractor_beam_is_active(program: IntcodeProgram, x: usize, y: usize) -> bool = { + program + .with_input(list![Intcode::from(x), Intcode::from(y)]) + .execute() + == Ok(vector![Intcode::from(1)]) + + } +} -- cgit v1.2.3 From 736952eeda1f4a77705ba6fe99dd2ed59131451e Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 30 Dec 2019 22:28:29 +0200 Subject: Parsing for day 20 --- inputs/day_20.txt | 113 +++++++++++++++++++++++++++++++++ src/bin/day_20.rs | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 299 insertions(+) create mode 100644 inputs/day_20.txt create mode 100644 src/bin/day_20.rs diff --git a/inputs/day_20.txt b/inputs/day_20.txt new file mode 100644 index 0000000..09d6330 --- /dev/null +++ b/inputs/day_20.txt @@ -0,0 +1,113 @@ + K Z V U I F + Q T Y Y E E + ###################################.#####.###.###########.#####.#.##################################### + #.......#.#.............#.........#.#.......#.#.#.........#.....#...#...#...........#...#.....#.#.....# + ###.#####.###.###.###.###########.#.###.#####.#.###.#.#.#.###.###.###.#####.#######.###.#####.#.###.### + #.#...#.#.#.#.#.#.#.#.....#...........#.....#.#...#.#.#.#...#.#.#.#.....#.#.#...#.#.#...#.#.#.....#...# + #.#.###.#.#.###.###.#.#########.###.#######.#.#.#.#######.#.#.#.#.#.###.#.#.#.###.#####.#.#.#.#####.### + #.....#...#...............#.#.#.#.#.#.....#.#.#.#...#.....#.#.#.#.#...#.....#.#.#.........#...#.#...#.# + #.#######.###########.###.#.#.###.#.###.#.#.#.#.###.###.###.#.#.#.#.###.#.###.#.#.#.#######.###.###.#.# + #...#.......#...#.#...#...#...#.#.#.#...#...#.....#.#.#.#...#...#...#...#.........#.#.#.#...#.......#.# + #.#######.#.###.#.#######.###.#.#.#.#.#.###.###.#####.#####.###.#.#####.#####.#.#.###.#.###.#.#######.# + #.#.#...#.#...#.......#.......#.#...#.#...#.#.#...#.#.......#...#.#.........#.#.#...............#.....# + #.#.#.#######.#####.#####.###.#.###.#.#####.#.#.###.#####.###.#####.###.###########.###############.### + #.#...#...#.......#...#...#.#.......#.....#.#.....#.#.......#.#...#.#.#.#.......#.......#...#...#.#...# + #.###.###.#####.#.###.#####.#####.#.###.#######.#.#.#######.#.#.#####.#.#.###########.#####.###.#.#.### + #.#.#.#...#...#.#.#...#.#.#.#.#.#.#.#...#.......#.#.#.#.....#.....#...............#...#.#...#.........# + #.#.#.#.#####.#.#####.#.#.#.#.#.###.#.#####.###.###.#.#####.#.#######.#.#######.#######.#.#.###.#####.# + #.......#.#.#...#.#...............#.#...#.#.#.......#...#...#.......#.#.#.#.#...#.#.....#.#.#...#.#...# + #.#######.#.###.#.#.###.#.#.#.###.#.###.#.###.#.###.#.###.#.#.#.#######.#.#.#####.#.#######.#.###.###.# + #.#.#.#.#.#.......#.#.#.#.#.#.#.#.#.#...#...#.#.#.#.#.....#.#.#.#.#.#...#.......#.#.#.#...#.#.#...#.#.# + #.#.#.#.#.#####.#####.#.#####.#.#.#.#.###.#.#.###.#####.#####.#.#.#.#.#####.#.###.#.#.#.###.#.###.#.### + #.#.#.#.#.#.....#.#.....#.......#.#.#.#...#.#...#...#.......#.#.#.#.........#.#...#.......#.#.#.#.#.#.# + #.#.#.#.#.#.###.#.#.#####.###.#.#.#.#.#.###.#.###.#.###.#######.#.#.###.###.#####.#.#.#.###.#.#.#.#.#.# + #.......#.#.#.#.#.#.#...#.#.#.#.#...#...#...#...#.#.#.....#.#...#...#...#.......#...#.#...#.#.#.#...#.# + #####.###.#.#.###.#####.###.###.###.#####.#####.#.#.#.#####.#.#.#####.#######.#####.#######.#.#.#.###.# + #.#...#.........#...#.#.......#...#...#.....#...#.#.#.....#...#.#...........#.#.#.#...#.#.........#...# + #.###.#.#.#######.#.#.#.#########.#########.#.###.#.#.#.###.#.#########.###.###.#.#.###.###.#######.### + #.#.....#...#...#.#...#.....#.......#.......#.....#.#.#...#.#.....#.....#.....#...#.#...#.........#...# + #.###.#.#.#####.###.###.#######.#####.#############.#.#########.###.###########.###.#.#.#.###.#.###.#.# + #...#.#.#.#.#...#.#.#.....# U N Q W Z N #.......#.#...#...#...#.#.# + ###.###.###.###.#.#.###.### Y D P L W J #####.#########.#######.### + #.#.#.#.#...#...#.#...#.#.# #.....#...#...........#.#.# + #.#.#.#.###.###.#.#.###.#.# ###.#.###.###.###.#####.#.# + #...................#.#...# #.#.#.........#...#........CB + #.###.#######.#.###.#.#.#.# #.#.#.###.#####.###.#.#.#.# + #.#.........#.#...#.....#.# #...#.#.....#...#...#.#.#..AA + #######.#######.###.#####.# #.#######.#.###.#.#.###.### + #.....#.......#...#...#...# QJ..#.#...#.#.#.#...#...#.#.# + ###.#.#.###.###########.### ###.#.#######.###########.# +YG....#.....#.#.......#......TY #.........#...........#...# + #.#.#.###########.#.#.##### #.#####.###.#########.#.#.# + #.#.#.#...#...#...#.#.#...# CB..#.#.......#.#.#.#.....#..DN + #######.#####.#.#.#####.### ###.#########.#.#.######### + #.....#...#...#.#.#...#.#.# #...#.........#...#.......# + #.###.#.#.#.#.#.#.#.#.#.#.# ###.###.#####.#.#.#.#####.# +SP..#.....#...#...#...#......YG #.......#...#...#.#.#.....# + ########################### #.#.###.###.#.###.#.#.##### +NJ....#.................#.#.# KQ..#.#.......#.#...#.#.....# + #.#.#.#####.#.#.#####.#.#.# ###.###.###.###.#.#.###.#.# + #.#.#.....#.#.#.#.....#...# #.#...#.#.#.#.#.#.....#.#..IT + ###.#####.###.#####.#####.# #.#.#####.###.############# + #.#.....#...#.....#........WE IE..#.#.#.#...............#.# + #.#.#.#.#.#########.#.###.# #.#.#.#.#.###.###.###.###.# + #...#.#...#.#.#.#...#.#...# #.#.#...#.#.#...#.#...#.#.# + #.#######.#.#.#.#####.##### #.#####.#.#.#.#.#####.#.#.# + #.#.....#.#.........#.#...# #...........#.#.#.#...#....QJ + #######.###.#.#.###.#####.# #######.#.#######.#.#.###.# + #.#.....#...#.#.#.........# #.....#.#.#...#.#...#.....# + #.###.#.#.#######.#.#####.# ###.#########.#.########### +YV..#...#.#...#.#.#.#.#.....# #.......#.........#.#.....# + #.#.###.#.#.#.#.#.###.#.### #.#####.###.#####.#.#.#.#.# + #.....#...#.#...#.#.#.#....QX #.#...#.........#.#...#.#..QP + ###.###.#######.###.###.#.# #.###.#.###.#####.#.#####.# + #.#.#.....#.....#.....#.#.# #.#.#.#.#...#.....#...#...# + #.#####.#######.###.#.##### #.#.#.#####.#.###.###.#.#.# + #.#...#.#.....#.#.#.#...#..DM FE..#.#...#.#.#.#.......#.#.# + #.#.#####.#.###.#.#.###.#.# #.#.#.#.#.###############.# + #.#.......#...#.#.....#...# #.#...#.#.#.....#.......#.# + #.#.#.#.#.###.#.#####.###.# #######.#.#.#######.#.##### +QX....#.#.#.#.............#.# #.......#.#.......#.#.....# + #####.#.#.#.#.#.########### ###.###.#.#.#.###.#.#####.# + #.#.#.#.#.#.#.#.#.........# GX..#.#.......#.#.#.......#..DM + #.#.###############.###.#.# #.#.#####.#.###.###.###.#.# + #.#.#.........#...#...#.#..CS #.....#.#.#.#.#...#.#.#.#.# + #.#.#######.#####.###.#.### #######.#.###.#.#####.##### +WE........#.#.#.#.#.#...#...# MX........#.#.........#......CS + #####.###.#.#.#.#.#.#.##### #####.###.###.#####.###.### + #...#...............#.#.#.# #.#.....#.#.......#...#...# + ###.###################.#.# #.#.###########.#.###.#.#.# + #...............#.#........ME #.#.#.#...#...#.#.#...#.#.# + #.#.#####.#####.#.#.###.#.# #.#.#####.#######.#.#####.# +GX..#...#.#.#...........#.#.# #.................#.......# + #.#.###.#######.###.#####.# J D Z V S I Y #.###.###.#.###.###.#.#.#.# + #.#.......#.......#.....#.# I N T Y P T V #...#...#.#.#.#.#.#.#.#.#.# + #.#.#.#########.#.#.#############.#########.###.#.#.#############.###.###########.###.#.#.#.#.#.#####.# + #.#.#.....#.....#.#...#.......#.....#.......#.....#.#.#.#.#...#...#.........#.....#...#.#.....#...#...# + #.#############.###.#######.#.#####.#.###.###.#####.#.#.#.###.#.#####.#.#.#####.#.#.#.#.#####.###.##### + #...........#.....#.....#...#.......#...#.#.#.....#.#.....#.#.......#.#.#...#...#.#.#.#.#.....#.#.....# + ###.#######.#######.#####.###.#######.#.###.###.#.#.#.###.#.#.#######.#############.#.#######.#.#.###.# + #.#.....#.#.#.#.......#.#.#.#...#...#.#...#...#.#.#.....#...#.......#.....#.#...#...#...#.......#.#...# + #.#.#.###.#.#.#.#.###.#.###.###.#.#.###.#.###.#.#########.#####.#.###.#.###.#.#########.#####.#####.#.# + #...#...#.....#.#.#...#...#.#...#.#...#.#.#.....#.#.#.....#...#.#.#...#.............#.....#.....#...#.# + #####.###########.#####.###.#.###.#.###.#####.#.#.#.###.#.#.#.###.#.#######.###.#########.#.#.######### + #.........#.....#.#...........#...#.#...#.#...#.#...#...#.#.#.....#.......#...#.#.....#.#.#.#.....#.#.# + ###.###.#.###.#####.#.#.#.#.#.#.###.###.#.###.#####.#.#####.#.###.###.#####.#####.#####.#####.#####.#.# + #...#.#.#.#.........#.#.#.#.#...#...#.....#.....#.......#...#.#.#.#.......#.#.#...#.....#.#.#.........# + #.#.#.#.###.###.###########.###.#.###.#.#####.#.#.#.#.#.#.#.###.###.#.###.###.###.#.#.#.#.#.#.###.#.#.# + #.#.#...#...#.....#.........#.#.#...#.#.#.#...#.#.#.#.#.#.#.......#.#...#.#.....#...#.#.#.......#.#.#.# + #.#.###.#.#.#.#.#.#####.#####.#.###.#.###.###.#####.#######.###.###.#########.###.#######.#.#.#####.#.# + #.#.#...#.#.#.#.#.#.#.#.#.......#...#...#...#...#.....#.#.....#.#.#.......#...#.....#.#.#.#.#.#.#...#.# + #.#####.#.#####.###.#.#######.#.#.#.###.###.#.#.###.###.###.#####.#.#.#####.#####.#.#.#.###.#.#.#####.# + #...#...#.#.....#.#.....#.#...#.#.#.#...#.#...#.#.......#.#.#.#.#...#...........#.#.#...#.#.#.....#.#.# + ###.###.#########.#####.#.###.#####.#.###.###.#####.#####.#.#.#.#.#######.#######.###.###.#####.#.#.### + #.....#.#.....................#...#.#.......#.#.....#.....#.....#.#...........#.....#.#.#.#.#...#.#...# + #.###.#####.#.#.#.###.#.#.#.###.###.###.#.###.#####.###.#.#.#########.###########.###.#.#.#.###.###.### + #...#...#...#.#.#.#...#.#.#.#.......#.#.#...#.....#.#...#.#.......#.#.........#.............#.........# + ###.#.#####.#############.#####.#.###.#.###.#####.#.#.###.###.#.#.#.#####.#.###.###.###.###.#.#####.### + #...#.#.#.#...#.#...#.......#...#.....#.#...#.....#...#.#.#.#.#.#...#.....#.....#.....#...#.#...#.....# + #.###.#.#.###.#.###.###.#####.#####.#####.###.#########.#.#.#####.#######.#####.###.#####.#.#.###.###.# + #.#.........#.#.........#.....#.....#.....#.........#.....#.......#...........#...#...#...#.#...#.#...# + ###################################.###.#######.#.###.###.###.#######.################################# + N J W Z Z M M T + D I L W Z X E Y diff --git a/src/bin/day_20.rs b/src/bin/day_20.rs new file mode 100644 index 0000000..eb10864 --- /dev/null +++ b/src/bin/day_20.rs @@ -0,0 +1,186 @@ +use rpds::rbt_set; +use rpds::vector; +use rpds::vector::Vector; +use rpds::RedBlackTreeMap; +use rpds::RedBlackTreeSet; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 20: Donut Maze")] +/// Finds the shortest path through a maze with portals. +/// +/// See https://adventofcode.com/2019/day/20 for details. +struct Opt {} + +fn main() { + let stdin = io::stdin(); + let _opt = Opt::from_args(); + + let maze = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .collect::() + .build(); + + println!("{}", maze.shortest_route()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +struct MazeBuilder { + map: Vector>, + portals: Vector<([char; 2], Point)>, +} + +impl FromIterator for MazeBuilder { + fn from_iter>(iter: T) -> Self { + MazeBuilder { + map: iter + .into_iter() + .map(|line| line.chars().collect()) + .collect(), + portals: Vector::new(), + } + } +} + +impl MazeBuilder { + fn build(self) -> Maze { + Maze { + walls: self + .map + .iter() + .map(|line| line.iter().map(|ch| *ch != '.').collect()) + .collect(), + portals: self.grouped_portals(), + entrance: self + .all_portals() + .find(|(id, _)| *id == ['A', 'A']) + .unwrap() + .1, + exit: self + .all_portals() + .find(|(id, _)| *id == ['Z', 'Z']) + .unwrap() + .1, + } + } + + fn grouped_portals(&self) -> Vector<(Point, Point)> { + self.all_portals() + .fold( + (Vector::new(), RedBlackTreeMap::new()), + |(matched, unmatched): ( + Vector<(Point, Point)>, + RedBlackTreeMap<[char; 2], Point>, + ), + (next_id, next_p)| match unmatched.get(&next_id) { + Some(pair) => ( + matched.push_back((pair.clone(), next_p)), + unmatched.remove(&next_id), + ), + None => (matched, unmatched.insert(next_id, next_p)), + }, + ) + .0 + } + + fn all_portals(&self) -> impl Iterator + '_ { + self.horizontal_trailing_portals() + .chain(self.horizontal_leading_portals()) + .chain(self.vertical_trailing_portals()) + .chain(self.vertical_leading_portals()) + } + + fn horizontal_trailing_portals(&self) -> impl Iterator + '_ { + // .XX + (0..self.map.len()) + .flat_map(move |y| (0..self.map[y].len() - 2).map(move |x| Point { x, y })) + .filter(move |p| { + self.map[p.y][p.x] == '.' + && self.map[p.y][p.x + 1].is_alphabetic() + && self.map[p.y][p.x + 2].is_alphabetic() + }) + .map(move |p| ([self.map[p.y][p.x + 1], self.map[p.y][p.x + 2]], p)) + } + + fn horizontal_leading_portals(&self) -> impl Iterator + '_ { + // XX. + (0..self.map.len()) + .flat_map(move |y| (0..self.map[y].len() - 2).map(move |x| Point { x, y })) + .filter(move |p| { + self.map[p.y][p.x + 2] == '.' + && self.map[p.y][p.x + 1].is_alphabetic() + && self.map[p.y][p.x].is_alphabetic() + }) + .map(move |p| { + ( + [self.map[p.y][p.x], self.map[p.y][p.x + 1]], + Point { x: p.x + 2, y: p.y }, + ) + }) + } + + fn vertical_trailing_portals(&self) -> impl Iterator + '_ { + // .XX + (0..self.map[0].len()) + .flat_map(move |x| (0..self.map.len() - 2).map(move |y| Point { x, y })) + .filter(move |p| { + self.map[p.y][p.x] == '.' + && self.map[p.y + 1][p.x].is_alphabetic() + && self.map[p.y + 2][p.x].is_alphabetic() + }) + .map(move |p| ([self.map[p.y + 1][p.x], self.map[p.y + 2][p.x]], p)) + } + + fn vertical_leading_portals(&self) -> impl Iterator + '_ { + // XX. + (0..self.map[0].len()) + .flat_map(move |x| (0..self.map.len() - 2).map(move |y| Point { x, y })) + .filter(move |p| { + self.map[p.y + 2][p.x] == '.' + && self.map[p.y + 1][p.x].is_alphabetic() + && self.map[p.y][p.x].is_alphabetic() + }) + .map(move |p| { + ( + [self.map[p.y][p.x], self.map[p.y + 1][p.x]], + Point { x: p.x, y: p.y + 2 }, + ) + }) + } +} + +#[derive(Debug)] +struct Maze { + walls: Vector>, + portals: Vector<(Point, Point)>, + entrance: Point, // AA + exit: Point, // ZZ +} + +#[derive(Debug, Clone)] +struct Point { + x: usize, + y: usize, +} + +impl Maze { + fn shortest_route(&self) -> usize { + unimplemented!() + } +} -- cgit v1.2.3 From abdee46919f089d20509c5930bfcd014a748e8ba Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 30 Dec 2019 23:18:20 +0200 Subject: Day 20 part 1 --- src/bin/day_20.rs | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/src/bin/day_20.rs b/src/bin/day_20.rs index eb10864..1bce235 100644 --- a/src/bin/day_20.rs +++ b/src/bin/day_20.rs @@ -1,5 +1,4 @@ use rpds::rbt_set; -use rpds::vector; use rpds::vector::Vector; use rpds::RedBlackTreeMap; use rpds::RedBlackTreeSet; @@ -43,7 +42,6 @@ fn exit_on_failed_assertion(data: Result, message struct MazeBuilder { map: Vector>, - portals: Vector<([char; 2], Point)>, } impl FromIterator for MazeBuilder { @@ -53,7 +51,6 @@ impl FromIterator for MazeBuilder { .into_iter() .map(|line| line.chars().collect()) .collect(), - portals: Vector::new(), } } } @@ -173,14 +170,159 @@ struct Maze { exit: Point, // ZZ } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] struct Point { x: usize, y: usize, } +impl Point { + fn add(&self, x: isize, y: isize) -> Point { + Point { + x: (self.x as isize + x) as usize, + y: (self.y as isize + y) as usize, + } + } +} + impl Maze { fn shortest_route(&self) -> usize { - unimplemented!() + iter::successors( + Some(( + rbt_set![self.entrance.clone()], + rbt_set![self.entrance.clone()], + )), + |(explored, locations)| { + Some(Maze::next_depth_states( + explored.clone(), + self.next_locations(locations, explored), + )) + }, + ) + // .inspect(|(explored, states)| eprintln!("{:?}", states)) + .take_while(|(_explored, states)| states.size() > 0) + .enumerate() + .find(|(_i, (_explored, states))| states.iter().any(|state| *state == self.exit)) + .unwrap() + .0 + } + + fn next_depth_states( + explored: RedBlackTreeSet, + locations: RedBlackTreeSet, + ) -> (RedBlackTreeSet, RedBlackTreeSet) { + ( + locations + .iter() + .fold(explored, |acc, next| acc.insert(next.clone())), + locations, + ) + } + + fn next_locations( + &self, + locations: &RedBlackTreeSet, + explored: &RedBlackTreeSet, + ) -> RedBlackTreeSet { + locations + .iter() + .flat_map(|p| { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .iter() + .map(move |(dx, dy)| p.add(*dx, *dy)) + .chain( + self.portals + .iter() + .filter(move |(from, _to)| p == from) + .map(|(_from, to)| to) + .cloned(), + ) + .chain( + self.portals + .iter() + .filter(move |(_to, from)| p == from) + .map(|(to, _from)| to) + .cloned(), + ) + }) + .filter(|p_next| !self.walls[p_next.y][p_next.x]) + .filter(|state| !explored.contains(state)) + .collect() } } + +#[test] +fn portal_maze_example_1() { + let maze: Maze = r" A + A + #######.######### + #######.........# + #######.#######.# + #######.#######.# + #######.#######.# + ##### B ###.# +BC...## C ###.# + ##.## ###.# + ##...DE F ###.# + ##### G ###.# + #########.#####.# +DE..#######...###.# + #.#########.###.# +FG..#########.....# + ###########.##### + Z + Z " + .split('\n') + .map(|s| s.to_string()) + .collect::() + .build(); + + assert_eq!(maze.shortest_route(), 23); +} + +#[test] +fn portal_maze_example_2() { + let maze: Maze = r" A + A + #################.############# + #.#...#...................#.#.# + #.#.#.###.###.###.#########.#.# + #.#.#.......#...#.....#.#.#...# + #.#########.###.#####.#.#.###.# + #.............#.#.....#.......# + ###.###########.###.#####.#.#.# + #.....# A C #.#.#.# + ####### S P #####.# + #.#...# #......VT + #.#.#.# #.##### + #...#.# YN....#.# + #.###.# #####.# +DI....#.# #.....# + #####.# #.###.# +ZZ......# QG....#..AS + ###.### ####### +JO..#.#.# #.....# + #.#.#.# ###.#.# + #...#..DI BU....#..LF + #####.# #.##### +YN......# VT..#....QG + #.###.# #.###.# + #.#...# #.....# + ###.### J L J #.#.### + #.....# O F P #.#...# + #.###.#####.#.#####.#####.###.# + #...#.#.#...#.....#.....#.#...# + #.#####.###.###.#.#.#########.# + #...#.#.....#...#.#.#.#.....#.# + #.###.#####.###.###.#.#.####### + #.#.........#...#.............# + #########.###.###.############# + B J C + U P P " + .split('\n') + .map(|s| s.to_string()) + .collect::() + .build(); + + assert_eq!(maze.shortest_route(), 58); +} -- cgit v1.2.3 From fc4aef0eb26fcd64a91f95e5aa8e9cbc800b3ba8 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 31 Dec 2019 20:19:05 +0200 Subject: Day 20 part 2 - now with depth! --- src/bin/day_20.rs | 122 +++++++++++++++++++++++------------------------------- 1 file changed, 52 insertions(+), 70 deletions(-) diff --git a/src/bin/day_20.rs b/src/bin/day_20.rs index 1bce235..953df75 100644 --- a/src/bin/day_20.rs +++ b/src/bin/day_20.rs @@ -14,11 +14,15 @@ use structopt::StructOpt; /// Finds the shortest path through a maze with portals. /// /// See https://adventofcode.com/2019/day/20 for details. -struct Opt {} +struct Opt { + /// include the rule that going through portals changes your depth + #[structopt(short = "d")] + include_depth: bool, +} fn main() { let stdin = io::stdin(); - let _opt = Opt::from_args(); + let opt = Opt::from_args(); let maze = stdin .lock() @@ -27,7 +31,7 @@ fn main() { .collect::() .build(); - println!("{}", maze.shortest_route()); + println!("{}", maze.shortest_route(opt.include_depth)); } fn exit_on_failed_assertion(data: Result, message: &str) -> A { @@ -87,7 +91,11 @@ impl MazeBuilder { ), (next_id, next_p)| match unmatched.get(&next_id) { Some(pair) => ( - matched.push_back((pair.clone(), next_p)), + matched.push_back(pair.clone().inside_out( + next_p, + self.map[0].len(), + self.map.len(), + )), unmatched.remove(&next_id), ), None => (matched, unmatched.insert(next_id, next_p)), @@ -183,34 +191,53 @@ impl Point { y: (self.y as isize + y) as usize, } } + + fn inside_out(self, other: Point, width: usize, height: usize) -> (Point, Point) { + if self.closest_side(width, height) > other.closest_side(width, height) { + (self, other) + } else { + (other, self) + } + } + + fn closest_side(&self, width: usize, height: usize) -> usize { + self.x.min(width - self.x).min(self.y).min(height - self.y) + } } impl Maze { - fn shortest_route(&self) -> usize { + fn shortest_route(&self, include_depth: bool) -> usize { iter::successors( Some(( - rbt_set![self.entrance.clone()], - rbt_set![self.entrance.clone()], + rbt_set![(self.entrance.clone(), 0)], + rbt_set![(self.entrance.clone(), 0)], )), |(explored, locations)| { Some(Maze::next_depth_states( explored.clone(), - self.next_locations(locations, explored), + self.next_locations(locations, explored, include_depth), )) }, ) // .inspect(|(explored, states)| eprintln!("{:?}", states)) .take_while(|(_explored, states)| states.size() > 0) .enumerate() - .find(|(_i, (_explored, states))| states.iter().any(|state| *state == self.exit)) + .find(|(_i, (_explored, states))| { + states + .iter() + .any(|(p_state, depth)| *p_state == self.exit && (!include_depth || *depth == 0)) + }) .unwrap() .0 } fn next_depth_states( - explored: RedBlackTreeSet, - locations: RedBlackTreeSet, - ) -> (RedBlackTreeSet, RedBlackTreeSet) { + explored: RedBlackTreeSet<(Point, isize)>, + locations: RedBlackTreeSet<(Point, isize)>, + ) -> ( + RedBlackTreeSet<(Point, isize)>, + RedBlackTreeSet<(Point, isize)>, + ) { ( locations .iter() @@ -221,31 +248,32 @@ impl Maze { fn next_locations( &self, - locations: &RedBlackTreeSet, - explored: &RedBlackTreeSet, - ) -> RedBlackTreeSet { + locations: &RedBlackTreeSet<(Point, isize)>, + explored: &RedBlackTreeSet<(Point, isize)>, + include_depth: bool, + ) -> RedBlackTreeSet<(Point, isize)> { locations .iter() - .flat_map(|p| { + .flat_map(|(p, depth)| { [(-1, 0), (1, 0), (0, -1), (0, 1)] .iter() - .map(move |(dx, dy)| p.add(*dx, *dy)) + .map(move |(dx, dy)| (p.add(*dx, *dy), *depth)) .chain( self.portals .iter() .filter(move |(from, _to)| p == from) - .map(|(_from, to)| to) - .cloned(), + .map(move |(_from, to)| (to.clone(), depth + 1)), ) .chain( self.portals .iter() .filter(move |(_to, from)| p == from) - .map(|(to, _from)| to) - .cloned(), + .map(move |(to, _from)| (to.clone(), depth - 1)), ) }) - .filter(|p_next| !self.walls[p_next.y][p_next.x]) + .filter(|(p_next, depth)| { + !self.walls[p_next.y][p_next.x] && (!include_depth || *depth >= 0) + }) .filter(|state| !explored.contains(state)) .collect() } @@ -277,52 +305,6 @@ FG..#########.....# .collect::() .build(); - assert_eq!(maze.shortest_route(), 23); -} - -#[test] -fn portal_maze_example_2() { - let maze: Maze = r" A - A - #################.############# - #.#...#...................#.#.# - #.#.#.###.###.###.#########.#.# - #.#.#.......#...#.....#.#.#...# - #.#########.###.#####.#.#.###.# - #.............#.#.....#.......# - ###.###########.###.#####.#.#.# - #.....# A C #.#.#.# - ####### S P #####.# - #.#...# #......VT - #.#.#.# #.##### - #...#.# YN....#.# - #.###.# #####.# -DI....#.# #.....# - #####.# #.###.# -ZZ......# QG....#..AS - ###.### ####### -JO..#.#.# #.....# - #.#.#.# ###.#.# - #...#..DI BU....#..LF - #####.# #.##### -YN......# VT..#....QG - #.###.# #.###.# - #.#...# #.....# - ###.### J L J #.#.### - #.....# O F P #.#...# - #.###.#####.#.#####.#####.###.# - #...#.#.#...#.....#.....#.#...# - #.#####.###.###.#.#.#########.# - #...#.#.....#...#.#.#.#.....#.# - #.###.#####.###.###.#.#.####### - #.#.........#...#.............# - #########.###.###.############# - B J C - U P P " - .split('\n') - .map(|s| s.to_string()) - .collect::() - .build(); - - assert_eq!(maze.shortest_route(), 58); + assert_eq!(maze.shortest_route(false), 23); + assert_eq!(maze.shortest_route(true), 26); } -- cgit v1.2.3 From 832190583eacad6d0166cbacb71f79fa93aef1d6 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 31 Dec 2019 20:45:13 +0200 Subject: Day 21 hello world, springbot bouncing into a hole --- inputs/day_21.txt | 1 + src/bin/day_17.rs | 7 ------- src/bin/day_21.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 7 deletions(-) create mode 100644 inputs/day_21.txt create mode 100644 src/bin/day_21.rs diff --git a/inputs/day_21.txt b/inputs/day_21.txt new file mode 100644 index 0000000..cafb613 --- /dev/null +++ b/inputs/day_21.txt @@ -0,0 +1 @@ +109,2050,21102,1,966,1,21101,0,13,0,1106,0,1378,21101,20,0,0,1105,1,1337,21101,27,0,0,1105,1,1279,1208,1,65,748,1005,748,73,1208,1,79,748,1005,748,110,1208,1,78,748,1005,748,132,1208,1,87,748,1005,748,169,1208,1,82,748,1005,748,239,21101,0,1041,1,21102,73,1,0,1106,0,1421,21101,0,78,1,21101,0,1041,2,21101,88,0,0,1106,0,1301,21101,68,0,1,21102,1041,1,2,21102,103,1,0,1106,0,1301,1101,0,1,750,1105,1,298,21101,0,82,1,21101,0,1041,2,21102,1,125,0,1105,1,1301,1102,1,2,750,1105,1,298,21102,79,1,1,21102,1,1041,2,21101,147,0,0,1106,0,1301,21102,1,84,1,21102,1,1041,2,21101,0,162,0,1106,0,1301,1101,0,3,750,1106,0,298,21101,0,65,1,21101,1041,0,2,21101,0,184,0,1106,0,1301,21101,76,0,1,21102,1,1041,2,21101,199,0,0,1106,0,1301,21102,75,1,1,21102,1,1041,2,21101,214,0,0,1105,1,1301,21101,221,0,0,1106,0,1337,21101,10,0,1,21102,1041,1,2,21102,236,1,0,1105,1,1301,1106,0,553,21102,1,85,1,21102,1,1041,2,21101,254,0,0,1105,1,1301,21101,78,0,1,21101,0,1041,2,21102,1,269,0,1106,0,1301,21102,276,1,0,1105,1,1337,21101,10,0,1,21102,1,1041,2,21101,0,291,0,1105,1,1301,1101,1,0,755,1105,1,553,21101,32,0,1,21102,1,1041,2,21102,313,1,0,1106,0,1301,21102,1,320,0,1106,0,1337,21102,327,1,0,1105,1,1279,1202,1,1,749,21102,65,1,2,21101,0,73,3,21102,1,346,0,1106,0,1889,1206,1,367,1007,749,69,748,1005,748,360,1101,0,1,756,1001,749,-64,751,1106,0,406,1008,749,74,748,1006,748,381,1102,1,-1,751,1105,1,406,1008,749,84,748,1006,748,395,1102,1,-2,751,1105,1,406,21102,1100,1,1,21101,0,406,0,1105,1,1421,21101,32,0,1,21102,1,1100,2,21101,421,0,0,1105,1,1301,21102,1,428,0,1106,0,1337,21102,435,1,0,1105,1,1279,2102,1,1,749,1008,749,74,748,1006,748,453,1102,1,-1,752,1106,0,478,1008,749,84,748,1006,748,467,1101,0,-2,752,1105,1,478,21101,1168,0,1,21101,0,478,0,1106,0,1421,21102,485,1,0,1105,1,1337,21102,1,10,1,21101,1168,0,2,21101,0,500,0,1105,1,1301,1007,920,15,748,1005,748,518,21101,0,1209,1,21102,1,518,0,1106,0,1421,1002,920,3,529,1001,529,921,529,101,0,750,0,1001,529,1,537,101,0,751,0,1001,537,1,545,1001,752,0,0,1001,920,1,920,1105,1,13,1005,755,577,1006,756,570,21102,1100,1,1,21101,570,0,0,1105,1,1421,21102,1,987,1,1105,1,581,21101,1001,0,1,21102,1,588,0,1106,0,1378,1101,0,758,593,1001,0,0,753,1006,753,654,21001,753,0,1,21101,610,0,0,1106,0,667,21101,0,0,1,21101,621,0,0,1106,0,1463,1205,1,647,21101,1015,0,1,21101,635,0,0,1106,0,1378,21101,1,0,1,21101,646,0,0,1105,1,1463,99,1001,593,1,593,1106,0,592,1006,755,664,1101,0,0,755,1105,1,647,4,754,99,109,2,1102,1,726,757,21202,-1,1,1,21101,9,0,2,21102,1,697,3,21102,692,1,0,1105,1,1913,109,-2,2105,1,0,109,2,101,0,757,706,1201,-1,0,0,1001,757,1,757,109,-2,2106,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,255,63,95,191,159,223,127,0,155,123,163,249,179,110,200,117,68,60,61,190,197,250,196,186,111,187,99,158,244,217,222,246,94,205,35,54,115,239,218,243,62,241,229,168,79,199,215,178,182,118,43,228,125,203,214,113,231,120,77,153,141,157,253,143,87,102,86,207,213,177,57,181,156,85,78,204,247,174,109,172,248,92,98,53,93,232,69,242,212,237,152,70,216,183,47,49,124,121,116,122,230,114,100,103,201,51,55,84,171,234,254,238,233,76,185,34,50,175,219,140,42,189,136,38,226,169,39,184,198,166,137,220,251,245,202,142,56,139,167,206,126,252,106,107,71,162,235,236,101,108,119,58,173,170,46,221,227,59,154,188,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,73,110,112,117,116,32,105,110,115,116,114,117,99,116,105,111,110,115,58,10,13,10,87,97,108,107,105,110,103,46,46,46,10,10,13,10,82,117,110,110,105,110,103,46,46,46,10,10,25,10,68,105,100,110,39,116,32,109,97,107,101,32,105,116,32,97,99,114,111,115,115,58,10,10,58,73,110,118,97,108,105,100,32,111,112,101,114,97,116,105,111,110,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,78,68,44,32,79,82,44,32,111,114,32,78,79,84,67,73,110,118,97,108,105,100,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,44,32,66,44,32,67,44,32,68,44,32,74,44,32,111,114,32,84,40,73,110,118,97,108,105,100,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,74,32,111,114,32,84,52,79,117,116,32,111,102,32,109,101,109,111,114,121,59,32,97,116,32,109,111,115,116,32,49,53,32,105,110,115,116,114,117,99,116,105,111,110,115,32,99,97,110,32,98,101,32,115,116,111,114,101,100,0,109,1,1005,1262,1270,3,1262,20101,0,1262,0,109,-1,2106,0,0,109,1,21102,1,1288,0,1106,0,1263,21001,1262,0,0,1102,0,1,1262,109,-1,2106,0,0,109,5,21102,1310,1,0,1105,1,1279,22102,1,1,-2,22208,-2,-4,-1,1205,-1,1332,22101,0,-3,1,21101,1332,0,0,1106,0,1421,109,-5,2106,0,0,109,2,21101,1346,0,0,1105,1,1263,21208,1,32,-1,1205,-1,1363,21208,1,9,-1,1205,-1,1363,1105,1,1373,21102,1,1370,0,1106,0,1279,1106,0,1339,109,-2,2105,1,0,109,5,1202,-4,1,1386,20101,0,0,-2,22101,1,-4,-4,21102,0,1,-3,22208,-3,-2,-1,1205,-1,1416,2201,-4,-3,1408,4,0,21201,-3,1,-3,1106,0,1396,109,-5,2106,0,0,109,2,104,10,22102,1,-1,1,21101,0,1436,0,1106,0,1378,104,10,99,109,-2,2105,1,0,109,3,20002,593,753,-1,22202,-1,-2,-1,201,-1,754,754,109,-3,2105,1,0,109,10,21102,5,1,-5,21102,1,1,-4,21102,1,0,-3,1206,-9,1555,21101,3,0,-6,21101,5,0,-7,22208,-7,-5,-8,1206,-8,1507,22208,-6,-4,-8,1206,-8,1507,104,64,1105,1,1529,1205,-6,1527,1201,-7,716,1515,21002,0,-11,-8,21201,-8,46,-8,204,-8,1105,1,1529,104,46,21201,-7,1,-7,21207,-7,22,-8,1205,-8,1488,104,10,21201,-6,-1,-6,21207,-6,0,-8,1206,-8,1484,104,10,21207,-4,1,-8,1206,-8,1569,21102,1,0,-9,1105,1,1689,21208,-5,21,-8,1206,-8,1583,21102,1,1,-9,1106,0,1689,1201,-5,716,1588,21002,0,1,-2,21208,-4,1,-1,22202,-2,-1,-1,1205,-2,1613,21201,-5,0,1,21102,1613,1,0,1105,1,1444,1206,-1,1634,22101,0,-5,1,21101,0,1627,0,1106,0,1694,1206,1,1634,21101,2,0,-3,22107,1,-4,-8,22201,-1,-8,-8,1206,-8,1649,21201,-5,1,-5,1206,-3,1663,21201,-3,-1,-3,21201,-4,1,-4,1106,0,1667,21201,-4,-1,-4,21208,-4,0,-1,1201,-5,716,1676,22002,0,-1,-1,1206,-1,1686,21101,1,0,-4,1105,1,1477,109,-10,2106,0,0,109,11,21102,0,1,-6,21101,0,0,-8,21101,0,0,-7,20208,-6,920,-9,1205,-9,1880,21202,-6,3,-9,1201,-9,921,1724,21002,0,1,-5,1001,1724,1,1733,20101,0,0,-4,21202,-4,1,1,21101,1,0,2,21101,9,0,3,21101,1754,0,0,1105,1,1889,1206,1,1772,2201,-10,-4,1767,1001,1767,716,1767,20102,1,0,-3,1105,1,1790,21208,-4,-1,-9,1206,-9,1786,22101,0,-8,-3,1105,1,1790,22101,0,-7,-3,1001,1733,1,1795,21001,0,0,-2,21208,-2,-1,-9,1206,-9,1812,21201,-8,0,-1,1105,1,1816,22101,0,-7,-1,21208,-5,1,-9,1205,-9,1837,21208,-5,2,-9,1205,-9,1844,21208,-3,0,-1,1106,0,1855,22202,-3,-1,-1,1106,0,1855,22201,-3,-1,-1,22107,0,-1,-1,1106,0,1855,21208,-2,-1,-9,1206,-9,1869,21201,-1,0,-8,1105,1,1873,22101,0,-1,-7,21201,-6,1,-6,1105,1,1708,22102,1,-8,-10,109,-11,2106,0,0,109,7,22207,-6,-5,-3,22207,-4,-6,-2,22201,-3,-2,-1,21208,-1,0,-6,109,-7,2105,1,0,0,109,5,2102,1,-2,1912,21207,-4,0,-1,1206,-1,1930,21102,1,0,-4,22101,0,-4,1,21202,-3,1,2,21102,1,1,3,21102,1949,1,0,1105,1,1954,109,-5,2105,1,0,109,6,21207,-4,1,-1,1206,-1,1977,22207,-5,-3,-1,1206,-1,1977,21202,-5,1,-5,1105,1,2045,22102,1,-5,1,21201,-4,-1,2,21202,-3,2,3,21102,1,1996,0,1105,1,1954,22102,1,1,-5,21102,1,1,-2,22207,-5,-3,-1,1206,-1,2015,21101,0,0,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2037,21202,-2,1,1,21101,2037,0,0,106,0,1912,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2106,0,0 diff --git a/src/bin/day_17.rs b/src/bin/day_17.rs index 9f5d3b8..e85373c 100644 --- a/src/bin/day_17.rs +++ b/src/bin/day_17.rs @@ -1,13 +1,6 @@ use aoc2019::*; -use rpds::list; -use rpds::list::List; -use rpds::rbt_set; -use rpds::set::red_black_tree_set::RedBlackTreeSet; -use rpds::vector; -use rpds::vector::Vector; use std::io; use std::io::prelude::*; -use std::iter; use std::process; use structopt::StructOpt; diff --git a/src/bin/day_21.rs b/src/bin/day_21.rs new file mode 100644 index 0000000..106ce82 --- /dev/null +++ b/src/bin/day_21.rs @@ -0,0 +1,62 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 21: Springdroid Adventure")] +/// Pilots a springdroid around! +/// +/// See https://adventofcode.com/2019/day/21 for details. +struct Opt {} + +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::(); + + let result = exit_on_failed_assertion( + { + let input = vec!["NOT A J\n", "WALK\n"]; + program + .with_input( + input + .iter() + .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) + .collect(), + ) + .execute() + }, + "Program failed", + ); + + println!( + "{}", + result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", result.last().unwrap()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} -- cgit v1.2.3 From d93d20427b7a15dd07dbb13a4203b8168ee03f6c Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 31 Dec 2019 21:04:18 +0200 Subject: Springbot walking, running, and jumping! --- src/bin/day_21.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/src/bin/day_21.rs b/src/bin/day_21.rs index 106ce82..7fa781c 100644 --- a/src/bin/day_21.rs +++ b/src/bin/day_21.rs @@ -23,9 +23,17 @@ fn main() { .map(|x| exit_on_failed_assertion(x.trim().parse::(), "Invalid number")) .collect::(); - let result = exit_on_failed_assertion( + let walk_result = exit_on_failed_assertion( { - let input = vec!["NOT A J\n", "WALK\n"]; + let input = vec![ + "NOT T T\n", + "AND A T\n", + "AND B T\n", + "AND C T\n", + "NOT T J\n", + "AND D J\n", + "WALK\n", + ]; program .with_input( input @@ -40,7 +48,7 @@ fn main() { println!( "{}", - result + walk_result .drop_last() .unwrap() .iter() @@ -48,7 +56,46 @@ fn main() { .map(|c| c as char) .collect::() ); - println!("{}", result.last().unwrap()); + println!("{}", walk_result.last().unwrap()); + + let run_result = exit_on_failed_assertion( + { + // (!A || !B || !C) && D && (E || H) + let input = vec![ + "OR E J\n", + "OR H J\n", + "AND D J\n", + "NOT T T\n", + "AND A T\n", + "AND B T\n", + "AND C T\n", + "NOT T T\n", + "AND T J\n", + "RUN\n", + ]; + program + .with_input( + input + .iter() + .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) + .collect(), + ) + .execute() + }, + "Program failed", + ); + + println!( + "{}", + run_result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", run_result.last().unwrap()); } fn exit_on_failed_assertion(data: Result, message: &str) -> A { -- cgit v1.2.3 From f6995e330034d87473ed2d297f6a993b103b0556 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Wed, 1 Jan 2020 14:28:52 +0200 Subject: Day 22 part 1, modular shuffling --- inputs/day_22.txt | 100 ++++++++++++++++++++++++++++ src/bin/day_22.rs | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 293 insertions(+) create mode 100644 inputs/day_22.txt create mode 100644 src/bin/day_22.rs diff --git a/inputs/day_22.txt b/inputs/day_22.txt new file mode 100644 index 0000000..b61e760 --- /dev/null +++ b/inputs/day_22.txt @@ -0,0 +1,100 @@ +deal with increment 34 +deal into new stack +cut 1712 +deal into new stack +cut 1984 +deal with increment 62 +deal into new stack +deal with increment 13 +deal into new stack +deal with increment 67 +cut -5590 +deal with increment 63 +cut -1086 +deal with increment 52 +cut 7894 +deal with increment 71 +cut -864 +deal into new stack +cut 239 +deal with increment 17 +cut -7187 +deal with increment 62 +deal into new stack +cut -7380 +deal with increment 14 +cut 3842 +deal into new stack +cut -5258 +deal with increment 40 +deal into new stack +deal with increment 45 +cut -6026 +deal with increment 21 +cut 3600 +deal with increment 56 +cut 2329 +deal into new stack +deal with increment 13 +cut -2409 +deal with increment 49 +cut 294 +deal into new stack +cut 4776 +deal with increment 17 +cut 5801 +deal with increment 43 +cut 8999 +deal with increment 46 +cut -8527 +deal with increment 4 +deal into new stack +cut -6767 +deal into new stack +deal with increment 33 +cut -532 +deal with increment 29 +deal into new stack +deal with increment 56 +cut 6867 +deal with increment 70 +cut 4276 +deal into new stack +cut -5621 +deal with increment 56 +cut -2966 +deal with increment 70 +deal into new stack +deal with increment 51 +cut -4097 +deal with increment 42 +deal into new stack +cut -5180 +deal with increment 61 +deal into new stack +cut 5367 +deal with increment 50 +cut 3191 +deal with increment 75 +cut 915 +deal with increment 72 +cut -3893 +deal with increment 22 +cut -3405 +deal with increment 30 +cut -6509 +deal with increment 31 +cut -7220 +deal with increment 45 +cut 6489 +deal with increment 70 +cut -4047 +deal into new stack +deal with increment 75 +cut 3980 +deal with increment 10 +cut 9677 +deal into new stack +deal with increment 45 +cut -6969 +deal into new stack diff --git a/src/bin/day_22.rs b/src/bin/day_22.rs new file mode 100644 index 0000000..cadfac4 --- /dev/null +++ b/src/bin/day_22.rs @@ -0,0 +1,193 @@ +use cached::cached; +use rpds::rbt_set; +use rpds::vector::Vector; +use rpds::RedBlackTreeMap; +use rpds::RedBlackTreeMapSync; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 22: Slam Shuffle")] +/// Shuffles some cards. +/// +/// See https://adventofcode.com/2019/day/22 for details. +struct Opt { + /// The size of the deck + deck_size: usize, + /// At the end, query the position of card + card: usize, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let instructions = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Parse error")) + .collect::>(); + + //eprintln!("{:?}", instructions); + + println!( + "{}", + Deck::new(opt.deck_size) + .shuffle(&instructions) + .find_position(opt.card) + ); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Clone)] +struct Deck { + zero: usize, + cards: Vector, +} + +impl Deck { + fn new(deck_size: usize) -> Self { + Deck { + zero: 0, + cards: (0..deck_size).collect(), + } + } + + fn shuffle(&self, instructions: &[Instruction]) -> Deck { + instructions.iter().fold(self.clone(), |deck, instruction| { + //eprintln!("{} :: {}", deck.zero, deck.cards); + deck.single_shuffle(instruction) + }) + } + + fn single_shuffle(&self, instruction: &Instruction) -> Deck { + match instruction { + Instruction::DealIntoNewStack => Deck { + cards: (0..self.cards.len()) + .map(|i| self.at(self.cards.len() - i - 1)) + .collect(), + zero: 0, + }, + Instruction::Cut(n) => Deck { + zero: mod_plus(self.zero, *n, self.cards.len()), + ..self.clone() + }, + Instruction::ReverseCut(n) => Deck { + zero: mod_sub(self.zero, *n, self.cards.len()), + ..self.clone() + }, + Instruction::DealWithIncrement(n) => Deck { + cards: (0..self.cards.len()) + .map(|i| self.at(*layout_after_shift(*n, self.cards.len()).get(&i).unwrap())) + .collect(), + zero: 0, + }, + } + } + + fn at(&self, index: usize) -> usize { + self.cards[mod_plus(index, self.zero, self.cards.len())] + } + + fn find_position(&self, value: usize) -> usize { + mod_sub( + self.cards.iter().position(|x| *x == value).unwrap(), + self.zero, + self.cards.len(), + ) + } +} + +fn mod_plus(a: usize, b: usize, modulus: usize) -> usize { + (a + b) % modulus +} + +fn mod_sub(a: usize, b: usize, modulus: usize) -> usize { + (a + modulus - b) % modulus +} + +fn mod_times(a: usize, b: usize, modulus: usize) -> usize { + (a * b) % modulus +} + +cached! { + LAYOUT_AFTER_SHIFT; + fn layout_after_shift(n: usize, modulus: usize) -> RedBlackTreeMapSync = { + (0..modulus).fold(RedBlackTreeMapSync::new_sync(), |acc, next| { + acc.insert(mod_times(next, n, modulus), next) + }) + } +} + +#[derive(Debug)] +enum Instruction { + DealIntoNewStack, + Cut(usize), + ReverseCut(usize), + DealWithIncrement(usize), +} + +impl FromStr for Instruction { + type Err = ParseErr; + fn from_str(s: &str) -> Result { + if s.starts_with("deal into new stack") { + Ok(Instruction::DealIntoNewStack) + } else if s.starts_with("cut -") { + s.split(' ') + .nth(1) + .map(|val| { + val.parse::() + .map_err(|_| ParseErr) + .map(|parsed| Instruction::ReverseCut(parsed.abs() as usize)) + }) + .unwrap_or(Err(ParseErr)) + } else if s.starts_with("cut") { + s.split(' ') + .nth(1) + .map(|val| { + val.parse::() + .map_err(|_| ParseErr) + .map(|parsed| Instruction::Cut(parsed)) + }) + .unwrap_or(Err(ParseErr)) + } else if s.starts_with("deal with increment") { + s.split(' ') + .nth(3) + .map(|val| { + val.parse::() + .map_err(|_| ParseErr) + .map(|parsed| Instruction::DealWithIncrement(parsed)) + }) + .unwrap_or(Err(ParseErr)) + } else { + Err(ParseErr) + } + } +} + +#[derive(Debug, Clone, Copy)] +struct ParseErr; + +impl fmt::Display for ParseErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Error parsing input") + } +} + +impl std::error::Error for ParseErr {} -- cgit v1.2.3 From c8102cb02d2cfca3cade459c56f7b0de2c79e6e8 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 5 Jan 2020 02:19:40 +0200 Subject: Reimplementation of day 22 that doesn't need the whole deck in memory --- readme.org | 1 + src/bin/day_22.rs | 214 ++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 143 insertions(+), 72 deletions(-) diff --git a/readme.org b/readme.org index e189346..c674de4 100644 --- a/readme.org +++ b/readme.org @@ -23,3 +23,4 @@ program should only be pure expressions. nested in a way that makes it harder to name and read. - The persistent data structures don't integrate with Rayon iterators. - Easier to test subsets, but harder to inspect and audit runtime behaviour. +- Although it isn't frequently used, Rust supports functions inside functions. diff --git a/src/bin/day_22.rs b/src/bin/day_22.rs index cadfac4..fbe3f4c 100644 --- a/src/bin/day_22.rs +++ b/src/bin/day_22.rs @@ -1,13 +1,9 @@ -use cached::cached; -use rpds::rbt_set; -use rpds::vector::Vector; -use rpds::RedBlackTreeMap; -use rpds::RedBlackTreeMapSync; +use num::bigint::BigInt; +use num::traits::identities::Zero; +use num::traits::sign::abs; use std::fmt; use std::io; use std::io::prelude::*; -use std::iter; -use std::iter::FromIterator; use std::process; use std::str::FromStr; use structopt::StructOpt; @@ -19,9 +15,15 @@ use structopt::StructOpt; /// See https://adventofcode.com/2019/day/22 for details. struct Opt { /// The size of the deck - deck_size: usize, + deck_size: BigInt, /// At the end, query the position of card - card: usize, + card: BigInt, + /// Number of repetitions + repetitions: usize, + + /// Prints the card in position n, rather than the position of card n + #[structopt(short = "p")] + position_mode: bool, } fn main() { @@ -37,12 +39,27 @@ fn main() { //eprintln!("{:?}", instructions); - println!( - "{}", - Deck::new(opt.deck_size) - .shuffle(&instructions) - .find_position(opt.card) - ); + if opt.position_mode { + println!( + "{}", + Card { + position: opt.card, + modulus: opt.deck_size + } + .shuffle_reverse(&instructions, opt.repetitions) + .position + ); + } else { + println!( + "{}", + Card { + position: opt.card, + modulus: opt.deck_size + } + .shuffle(&instructions, opt.repetitions) + .position + ); + } } fn exit_on_failed_assertion(data: Result, message: &str) -> A { @@ -56,91 +73,128 @@ fn exit_on_failed_assertion(data: Result, message } #[derive(Clone)] -struct Deck { - zero: usize, - cards: Vector, +struct Card { + position: BigInt, + modulus: BigInt, } -impl Deck { - fn new(deck_size: usize) -> Self { - Deck { - zero: 0, - cards: (0..deck_size).collect(), - } - } - - fn shuffle(&self, instructions: &[Instruction]) -> Deck { - instructions.iter().fold(self.clone(), |deck, instruction| { - //eprintln!("{} :: {}", deck.zero, deck.cards); - deck.single_shuffle(instruction) +impl Card { + fn shuffle(&self, instructions: &[Instruction], repetitions: usize) -> Card { + (0..repetitions).fold(self.clone(), |acc, _| { + instructions.iter().fold(acc, |card, instruction| { + //eprintln!("{} :: {}", deck.zero, deck.cards); + card.single_shuffle(instruction) + }) }) } - fn single_shuffle(&self, instruction: &Instruction) -> Deck { + fn single_shuffle(&self, instruction: &Instruction) -> Card { match instruction { - Instruction::DealIntoNewStack => Deck { - cards: (0..self.cards.len()) - .map(|i| self.at(self.cards.len() - i - 1)) - .collect(), - zero: 0, + Instruction::DealIntoNewStack => Card { + position: self.modulus.clone() - self.position.clone() - 1, + modulus: self.modulus.clone(), }, - Instruction::Cut(n) => Deck { - zero: mod_plus(self.zero, *n, self.cards.len()), - ..self.clone() + Instruction::Cut(n) => Card { + position: mod_sub(self.position.clone(), n.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), }, - Instruction::ReverseCut(n) => Deck { - zero: mod_sub(self.zero, *n, self.cards.len()), - ..self.clone() + Instruction::ReverseCut(n) => Card { + position: mod_plus(self.position.clone(), n.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), }, - Instruction::DealWithIncrement(n) => Deck { - cards: (0..self.cards.len()) - .map(|i| self.at(*layout_after_shift(*n, self.cards.len()).get(&i).unwrap())) - .collect(), - zero: 0, + Instruction::DealWithIncrement(n) => Card { + position: mod_times(self.position.clone(), n.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), }, } } - fn at(&self, index: usize) -> usize { - self.cards[mod_plus(index, self.zero, self.cards.len())] + fn shuffle_reverse(&self, instructions: &[Instruction], repetitions: usize) -> Card { + (0..repetitions).fold(self.clone(), |acc, _| { + instructions.iter().rev().fold(acc, |card, instruction| { + //eprintln!("{} :: {}", deck.zero, deck.cards); + card.single_shuffle_reverse(instruction) + }) + }) } - fn find_position(&self, value: usize) -> usize { - mod_sub( - self.cards.iter().position(|x| *x == value).unwrap(), - self.zero, - self.cards.len(), - ) + fn single_shuffle_reverse(&self, instruction: &Instruction) -> Card { + match instruction { + Instruction::DealIntoNewStack => Card { + position: self.modulus.clone() - self.position.clone() - 1, + modulus: self.modulus.clone(), + }, + Instruction::Cut(n) => Card { + position: mod_plus(self.position.clone(), n.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), + }, + Instruction::ReverseCut(n) => Card { + position: mod_sub(self.position.clone(), n.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), + }, + Instruction::DealWithIncrement(n) => Card { + position: mod_divide(self.position.clone(), n.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), + }, + } } } -fn mod_plus(a: usize, b: usize, modulus: usize) -> usize { +fn mod_plus(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { (a + b) % modulus } -fn mod_sub(a: usize, b: usize, modulus: usize) -> usize { - (a + modulus - b) % modulus +fn mod_sub(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + (a + modulus.clone() - b) % modulus } -fn mod_times(a: usize, b: usize, modulus: usize) -> usize { +fn mod_times(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { (a * b) % modulus } -cached! { - LAYOUT_AFTER_SHIFT; - fn layout_after_shift(n: usize, modulus: usize) -> RedBlackTreeMapSync = { - (0..modulus).fold(RedBlackTreeMapSync::new_sync(), |acc, next| { - acc.insert(mod_times(next, n, modulus), next) - }) +fn mod_divide(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + mod_times(a, mod_inverse(b, modulus.clone()), modulus) +} + +// NB: This may give nonsense if modulus isn't coprime with a +fn mod_inverse(a: BigInt, modulus: BigInt) -> BigInt { + (euclid_gcd_coefficients(a, modulus.clone()).0 + modulus.clone()) as BigInt % modulus +} + +fn euclid_gcd_coefficients(a: BigInt, b: BigInt) -> (BigInt, BigInt) { + fn euclid_gcd_coefficients_inner( + r: BigInt, + old_r: BigInt, + s: BigInt, + old_s: BigInt, + t: BigInt, + old_t: BigInt, + ) -> (BigInt, BigInt) { + if r.is_zero() { + (old_s, old_t) + } else { + euclid_gcd_coefficients_inner( + old_r.clone() - (old_r.clone() / r.clone()) * r.clone(), + r.clone(), + old_s - (old_r.clone() / r.clone()) * s.clone(), + s, + old_t - (old_r.clone() / r) * t.clone(), + t, + ) + } } + + assert!(a < b); + + euclid_gcd_coefficients_inner(b, a, 0.into(), 1.into(), 1.into(), 0.into()) } #[derive(Debug)] enum Instruction { DealIntoNewStack, - Cut(usize), - ReverseCut(usize), - DealWithIncrement(usize), + Cut(BigInt), + ReverseCut(BigInt), + DealWithIncrement(BigInt), } impl FromStr for Instruction { @@ -152,16 +206,16 @@ impl FromStr for Instruction { s.split(' ') .nth(1) .map(|val| { - val.parse::() + val.parse::() .map_err(|_| ParseErr) - .map(|parsed| Instruction::ReverseCut(parsed.abs() as usize)) + .map(|parsed| Instruction::ReverseCut(abs(parsed))) }) .unwrap_or(Err(ParseErr)) } else if s.starts_with("cut") { s.split(' ') .nth(1) .map(|val| { - val.parse::() + val.parse::() .map_err(|_| ParseErr) .map(|parsed| Instruction::Cut(parsed)) }) @@ -170,7 +224,7 @@ impl FromStr for Instruction { s.split(' ') .nth(3) .map(|val| { - val.parse::() + val.parse::() .map_err(|_| ParseErr) .map(|parsed| Instruction::DealWithIncrement(parsed)) }) @@ -191,3 +245,19 @@ impl fmt::Display for ParseErr { } impl std::error::Error for ParseErr {} + +#[test] +fn mod_inverse_of_13() { + assert_eq!(mod_inverse(1.into(), 13.into()), 1.into()); + assert_eq!(mod_inverse(2.into(), 13.into()), 7.into()); + assert_eq!(mod_inverse(3.into(), 13.into()), 9.into()); + assert_eq!(mod_inverse(4.into(), 13.into()), 10.into()); + assert_eq!(mod_inverse(5.into(), 13.into()), 8.into()); + assert_eq!(mod_inverse(6.into(), 13.into()), 11.into()); + assert_eq!(mod_inverse(7.into(), 13.into()), 2.into()); + assert_eq!(mod_inverse(8.into(), 13.into()), 5.into()); + assert_eq!(mod_inverse(9.into(), 13.into()), 3.into()); + assert_eq!(mod_inverse(10.into(), 13.into()), 4.into()); + assert_eq!(mod_inverse(11.into(), 13.into()), 6.into()); + assert_eq!(mod_inverse(12.into(), 13.into()), 12.into()); +} -- cgit v1.2.3 From e006385f3445796ed5a2faaa16f122ddc50cf249 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 5 Jan 2020 21:21:44 +0200 Subject: Day 22: adventures in modular math --- src/bin/day_22.rs | 234 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 148 insertions(+), 86 deletions(-) diff --git a/src/bin/day_22.rs b/src/bin/day_22.rs index fbe3f4c..5b999a6 100644 --- a/src/bin/day_22.rs +++ b/src/bin/day_22.rs @@ -1,6 +1,8 @@ +use derive_more::Display; use num::bigint::BigInt; use num::traits::identities::Zero; use num::traits::sign::abs; +use num::traits::Signed; use std::fmt; use std::io; use std::io::prelude::*; @@ -19,7 +21,7 @@ struct Opt { /// At the end, query the position of card card: BigInt, /// Number of repetitions - repetitions: usize, + repetitions: BigInt, /// Prints the card in position n, rather than the position of card n #[structopt(short = "p")] @@ -42,22 +44,30 @@ fn main() { if opt.position_mode { println!( "{}", - Card { - position: opt.card, - modulus: opt.deck_size - } - .shuffle_reverse(&instructions, opt.repetitions) - .position + instructions + .iter() + .rev() + .fold( + StandardisedInstruction::identity(opt.deck_size.clone()), + |acc, next| acc.then(&(next.clone(), opt.deck_size.clone(), false).into()) + ) + .repeat(opt.repetitions) + .apply(opt.card.clone()) ); } else { println!( "{}", - Card { - position: opt.card, - modulus: opt.deck_size - } - .shuffle(&instructions, opt.repetitions) - .position + instructions + .iter() + .fold( + StandardisedInstruction::identity(opt.deck_size.clone()), + |acc, next| { + eprintln!("{}", acc); + acc.then(&(next.clone(), opt.deck_size.clone(), true).into()) + } + ) + .repeat(opt.repetitions) + .apply(opt.card.clone()) ); } } @@ -72,93 +82,37 @@ fn exit_on_failed_assertion(data: Result, message } } -#[derive(Clone)] -struct Card { - position: BigInt, - modulus: BigInt, -} - -impl Card { - fn shuffle(&self, instructions: &[Instruction], repetitions: usize) -> Card { - (0..repetitions).fold(self.clone(), |acc, _| { - instructions.iter().fold(acc, |card, instruction| { - //eprintln!("{} :: {}", deck.zero, deck.cards); - card.single_shuffle(instruction) - }) - }) - } - - fn single_shuffle(&self, instruction: &Instruction) -> Card { - match instruction { - Instruction::DealIntoNewStack => Card { - position: self.modulus.clone() - self.position.clone() - 1, - modulus: self.modulus.clone(), - }, - Instruction::Cut(n) => Card { - position: mod_sub(self.position.clone(), n.clone(), self.modulus.clone()), - modulus: self.modulus.clone(), - }, - Instruction::ReverseCut(n) => Card { - position: mod_plus(self.position.clone(), n.clone(), self.modulus.clone()), - modulus: self.modulus.clone(), - }, - Instruction::DealWithIncrement(n) => Card { - position: mod_times(self.position.clone(), n.clone(), self.modulus.clone()), - modulus: self.modulus.clone(), - }, - } - } - - fn shuffle_reverse(&self, instructions: &[Instruction], repetitions: usize) -> Card { - (0..repetitions).fold(self.clone(), |acc, _| { - instructions.iter().rev().fold(acc, |card, instruction| { - //eprintln!("{} :: {}", deck.zero, deck.cards); - card.single_shuffle_reverse(instruction) - }) - }) - } - - fn single_shuffle_reverse(&self, instruction: &Instruction) -> Card { - match instruction { - Instruction::DealIntoNewStack => Card { - position: self.modulus.clone() - self.position.clone() - 1, - modulus: self.modulus.clone(), - }, - Instruction::Cut(n) => Card { - position: mod_plus(self.position.clone(), n.clone(), self.modulus.clone()), - modulus: self.modulus.clone(), - }, - Instruction::ReverseCut(n) => Card { - position: mod_sub(self.position.clone(), n.clone(), self.modulus.clone()), - modulus: self.modulus.clone(), - }, - Instruction::DealWithIncrement(n) => Card { - position: mod_divide(self.position.clone(), n.clone(), self.modulus.clone()), - modulus: self.modulus.clone(), - }, - } - } -} - fn mod_plus(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - (a + b) % modulus + mod_normalize(a + b, modulus) } fn mod_sub(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - (a + modulus.clone() - b) % modulus + mod_normalize(a - b, modulus) } fn mod_times(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - (a * b) % modulus + mod_normalize(a * b, modulus) } fn mod_divide(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { mod_times(a, mod_inverse(b, modulus.clone()), modulus) } +fn mod_pow(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + a.modpow(&b, &modulus) +} + +fn mod_normalize(a: BigInt, modulus: BigInt) -> BigInt { + if a.is_negative() { + a.clone() + modulus.clone() * (1 + abs(a) / modulus) + } else { + a % modulus + } +} + // NB: This may give nonsense if modulus isn't coprime with a fn mod_inverse(a: BigInt, modulus: BigInt) -> BigInt { - (euclid_gcd_coefficients(a, modulus.clone()).0 + modulus.clone()) as BigInt % modulus + mod_normalize(euclid_gcd_coefficients(a, modulus.clone()).0, modulus) } fn euclid_gcd_coefficients(a: BigInt, b: BigInt) -> (BigInt, BigInt) { @@ -189,7 +143,7 @@ fn euclid_gcd_coefficients(a: BigInt, b: BigInt) -> (BigInt, BigInt) { euclid_gcd_coefficients_inner(b, a, 0.into(), 1.into(), 1.into(), 0.into()) } -#[derive(Debug)] +#[derive(Debug, Clone)] enum Instruction { DealIntoNewStack, Cut(BigInt), @@ -235,6 +189,114 @@ impl FromStr for Instruction { } } +// f(x) = ax + b mod c +#[derive(Display, Clone)] +#[display(fmt = "f(x) = {} x + {} % {}", a, b, modulus)] +struct StandardisedInstruction { + a: BigInt, + b: BigInt, + modulus: BigInt, +} + +impl From<(Instruction, BigInt, bool)> for StandardisedInstruction { + fn from((instruction, modulus, forward): (Instruction, BigInt, bool)) -> Self { + match (instruction, forward) { + (Instruction::DealIntoNewStack, _) => StandardisedInstruction { + a: BigInt::from(-1), + b: BigInt::from(-1), + modulus: modulus, + }, + (Instruction::Cut(n), true) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(-n), + modulus: modulus, + }, + (Instruction::Cut(n), false) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(n), + modulus: modulus, + }, + (Instruction::ReverseCut(n), true) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(n), + modulus: modulus, + }, + (Instruction::ReverseCut(n), false) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(-n), + modulus: modulus, + }, + (Instruction::DealWithIncrement(n), true) => StandardisedInstruction { + a: BigInt::from(n), + b: BigInt::from(0), + modulus: modulus, + }, + (Instruction::DealWithIncrement(n), false) => StandardisedInstruction { + a: BigInt::from(mod_inverse(n, modulus.clone())), + b: BigInt::from(0), + modulus: modulus, + }, + } + .normalise() + } +} + +impl StandardisedInstruction { + fn identity(modulus: BigInt) -> StandardisedInstruction { + StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(0), + modulus, + } + } + fn normalise(&self) -> StandardisedInstruction { + StandardisedInstruction { + a: mod_normalize(self.a.clone(), self.modulus.clone()), + b: mod_normalize(self.b.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), + } + } + fn then(&self, other: &StandardisedInstruction) -> StandardisedInstruction { + // g(f(x)) = ga (fa x + fb) + gb = + StandardisedInstruction { + a: mod_times(self.a.clone(), other.a.clone(), self.modulus.clone()), + b: mod_plus( + mod_times(self.b.clone(), other.a.clone(), self.modulus.clone()), + other.b.clone(), + self.modulus.clone(), + ), + modulus: self.modulus.clone(), + } + } + fn repeat(&self, repetitions: BigInt) -> StandardisedInstruction { + StandardisedInstruction { + a: mod_pow(self.a.clone(), repetitions.clone(), self.modulus.clone()), + b: mod_divide( + mod_times( + self.b.clone(), + mod_sub( + BigInt::from(1), + mod_pow(self.a.clone(), repetitions.clone(), self.modulus.clone()), + self.modulus.clone(), + ), + self.modulus.clone(), + ), + mod_sub(BigInt::from(1), self.a.clone(), self.modulus.clone()), + self.modulus.clone(), + ), + modulus: self.modulus.clone(), + } + } + + fn apply(&self, x: BigInt) -> BigInt { + mod_plus( + mod_times(self.a.clone(), x, self.modulus.clone()), + self.b.clone(), + self.modulus.clone(), + ) + } +} + #[derive(Debug, Clone, Copy)] struct ParseErr; -- cgit v1.2.3 From e84bfa982047875ab6a7a9b3e65b251e2f7b7c51 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Fri, 10 Jan 2020 21:36:35 +0200 Subject: Day 23: A network of intcodes --- inputs/day_23.txt | 1 + src/bin/day_23.rs | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 inputs/day_23.txt create mode 100644 src/bin/day_23.rs diff --git a/inputs/day_23.txt b/inputs/day_23.txt new file mode 100644 index 0000000..e4f8887 --- /dev/null +++ b/inputs/day_23.txt @@ -0,0 +1 @@ +3,62,1001,62,11,10,109,2215,105,1,0,1846,1780,1120,1959,571,2182,1083,631,1485,1306,1157,2153,1654,1592,1454,664,1815,951,2124,794,695,2023,1378,1248,1518,984,1887,2058,823,1019,891,1277,1685,2089,1341,1922,1186,765,1751,1413,602,922,858,1623,1217,1559,1050,1990,734,1720,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1106,0,73,3,65,20101,0,64,1,21001,66,0,2,21101,105,0,0,1105,1,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,133,1,133,68,133,101,0,0,62,1001,133,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1101,1,0,0,1001,161,1,169,101,0,65,0,1101,0,1,61,1101,0,0,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1105,1,178,21102,1,210,0,105,1,69,2101,0,1,70,1102,0,1,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1105,1,218,1105,1,73,109,4,21101,0,0,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1106,0,263,22102,1,-3,-3,109,-4,2106,0,0,109,4,21101,0,1,-3,21101,0,0,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,21202,-3,1,-3,109,-4,2106,0,0,109,1,101,1,68,358,21001,0,0,1,101,3,68,366,21001,0,0,2,21102,1,376,0,1106,0,436,22101,0,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21102,1,0,-4,21102,1,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,385,471,20102,1,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1106,0,547,21102,-1,1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1106,0,529,21201,-4,0,-7,109,-8,2106,0,0,109,1,101,1,68,564,20102,1,0,0,109,-1,2106,0,0,1102,97571,1,66,1101,1,0,67,1101,598,0,68,1101,556,0,69,1101,0,1,71,1101,0,600,72,1105,1,73,1,-1605712,28,112719,1102,1,48679,66,1102,1,1,67,1102,1,629,68,1102,556,1,69,1101,0,0,71,1102,631,1,72,1106,0,73,1,1782,1102,1,7877,66,1102,1,2,67,1101,658,0,68,1101,302,0,69,1102,1,1,71,1102,1,662,72,1105,1,73,0,0,0,0,26,81559,1101,0,22453,66,1101,1,0,67,1102,1,691,68,1101,0,556,69,1102,1,1,71,1102,1,693,72,1105,1,73,1,125,35,19959,1101,0,21493,66,1101,0,5,67,1102,1,722,68,1101,0,302,69,1102,1,1,71,1101,0,732,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,2,56893,1102,77191,1,66,1101,1,0,67,1102,1,761,68,1101,556,0,69,1101,1,0,71,1101,763,0,72,1105,1,73,1,1037327,8,179734,1101,57977,0,66,1101,0,1,67,1101,792,0,68,1102,556,1,69,1101,0,0,71,1101,0,794,72,1105,1,73,1,1430,1102,57173,1,66,1101,0,1,67,1101,0,821,68,1102,1,556,69,1101,0,0,71,1101,0,823,72,1106,0,73,1,1128,1101,0,37573,66,1102,1,3,67,1102,1,850,68,1102,253,1,69,1102,1,1,71,1101,856,0,72,1105,1,73,0,0,0,0,0,0,17,209158,1101,0,17569,66,1102,1,1,67,1101,0,885,68,1102,556,1,69,1101,2,0,71,1101,887,0,72,1106,0,73,1,8329,20,85972,34,54146,1101,84653,0,66,1101,1,0,67,1101,0,918,68,1102,1,556,69,1102,1,1,71,1101,0,920,72,1105,1,73,1,3167,20,64479,1101,0,88657,66,1102,1,1,67,1101,0,949,68,1101,556,0,69,1102,0,1,71,1102,1,951,72,1105,1,73,1,1419,1101,0,104579,66,1101,2,0,67,1101,0,978,68,1101,0,302,69,1101,0,1,71,1102,982,1,72,1105,1,73,0,0,0,0,6,76316,1102,33797,1,66,1101,0,1,67,1102,1011,1,68,1101,556,0,69,1102,1,3,71,1101,0,1013,72,1105,1,73,1,5,35,13306,35,26612,39,113194,1102,75781,1,66,1101,0,1,67,1102,1,1046,68,1102,1,556,69,1101,0,1,71,1101,1048,0,72,1106,0,73,1,1777,20,42986,1101,32183,0,66,1102,1,1,67,1102,1,1077,68,1102,556,1,69,1102,1,2,71,1102,1,1079,72,1105,1,73,1,10,35,6653,39,169791,1101,19079,0,66,1101,0,4,67,1102,1,1110,68,1102,253,1,69,1101,0,1,71,1102,1118,1,72,1105,1,73,0,0,0,0,0,0,0,0,7,7877,1102,1,56893,66,1101,0,4,67,1102,1147,1,68,1101,253,0,69,1102,1,1,71,1101,0,1155,72,1105,1,73,0,0,0,0,0,0,0,0,45,73189,1102,104651,1,66,1101,1,0,67,1102,1,1184,68,1101,556,0,69,1101,0,0,71,1101,0,1186,72,1105,1,73,1,1351,1101,0,43661,66,1101,1,0,67,1102,1213,1,68,1101,0,556,69,1102,1,1,71,1101,1215,0,72,1105,1,73,1,763676,28,75146,1101,16963,0,66,1102,1,1,67,1102,1,1244,68,1102,1,556,69,1102,1,1,71,1102,1246,1,72,1106,0,73,1,11,26,163118,1101,461,0,66,1101,1,0,67,1102,1275,1,68,1101,556,0,69,1101,0,0,71,1102,1,1277,72,1106,0,73,1,1263,1102,101483,1,66,1101,1,0,67,1102,1304,1,68,1102,556,1,69,1102,0,1,71,1102,1306,1,72,1106,0,73,1,1607,1101,0,14251,66,1101,0,3,67,1102,1333,1,68,1101,302,0,69,1102,1,1,71,1102,1,1339,72,1105,1,73,0,0,0,0,0,0,2,170679,1101,0,27073,66,1101,0,4,67,1102,1,1368,68,1102,1,302,69,1101,1,0,71,1101,0,1376,72,1106,0,73,0,0,0,0,0,0,0,0,1,154743,1101,0,15583,66,1101,0,1,67,1102,1,1405,68,1102,556,1,69,1101,0,3,71,1101,0,1407,72,1106,0,73,1,1,33,14998,21,302361,34,81219,1101,0,56597,66,1101,0,6,67,1102,1440,1,68,1102,1,302,69,1102,1,1,71,1101,1452,0,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,45,146378,1102,6991,1,66,1101,0,1,67,1102,1,1481,68,1102,1,556,69,1101,0,1,71,1102,1,1483,72,1106,0,73,1,902,21,201574,1102,1,89867,66,1101,2,0,67,1101,1512,0,68,1101,0,302,69,1101,1,0,71,1102,1516,1,72,1106,0,73,0,0,0,0,5,10798,1102,1,61553,66,1102,1,1,67,1102,1,1545,68,1102,556,1,69,1101,0,6,71,1101,0,1547,72,1106,0,73,1,2,20,21493,17,104579,7,15754,26,244677,39,282985,39,339582,1101,73189,0,66,1102,2,1,67,1101,0,1586,68,1101,0,351,69,1102,1,1,71,1101,0,1590,72,1105,1,73,0,0,0,0,255,60251,1101,0,91463,66,1102,1,1,67,1101,1619,0,68,1101,556,0,69,1102,1,1,71,1101,0,1621,72,1105,1,73,1,6467743,28,37573,1102,1,34369,66,1101,0,1,67,1101,1650,0,68,1102,556,1,69,1102,1,1,71,1101,1652,0,72,1105,1,73,1,8933,21,100787,1102,1,77081,66,1101,0,1,67,1101,1681,0,68,1102,1,556,69,1102,1,1,71,1101,1683,0,72,1105,1,73,1,2310,33,7499,1101,0,44699,66,1101,0,1,67,1102,1712,1,68,1101,556,0,69,1101,3,0,71,1101,1714,0,72,1105,1,73,1,3,8,89867,5,5399,34,108292,1101,97387,0,66,1102,1,1,67,1102,1747,1,68,1102,556,1,69,1102,1,1,71,1102,1749,1,72,1105,1,73,1,4,20,107465,1101,0,13463,66,1101,1,0,67,1101,1778,0,68,1101,0,556,69,1102,0,1,71,1102,1,1780,72,1106,0,73,1,1250,1102,51581,1,66,1102,1,3,67,1102,1807,1,68,1101,302,0,69,1101,0,1,71,1102,1,1813,72,1105,1,73,0,0,0,0,0,0,2,113786,1102,1,73679,66,1102,1,1,67,1102,1842,1,68,1102,556,1,69,1101,1,0,71,1102,1,1844,72,1105,1,73,1,160,39,56597,1101,0,60251,66,1101,0,1,67,1101,1873,0,68,1102,556,1,69,1102,6,1,71,1101,1875,0,72,1106,0,73,1,22677,47,94099,1,51581,1,103162,9,14251,9,28502,9,42753,1101,0,81559,66,1101,0,3,67,1102,1914,1,68,1101,0,302,69,1101,1,0,71,1102,1920,1,72,1105,1,73,0,0,0,0,0,0,47,188198,1101,0,6653,66,1101,4,0,67,1102,1949,1,68,1101,302,0,69,1101,0,1,71,1101,0,1957,72,1106,0,73,0,0,0,0,0,0,0,0,39,226388,1101,63659,0,66,1101,0,1,67,1101,0,1986,68,1102,556,1,69,1102,1,1,71,1102,1,1988,72,1105,1,73,1,-2,34,27073,1101,94099,0,66,1101,2,0,67,1101,0,2017,68,1101,0,302,69,1102,1,1,71,1102,2021,1,72,1106,0,73,0,0,0,0,2,227572,1101,100787,0,66,1101,0,3,67,1101,2050,0,68,1102,1,302,69,1101,1,0,71,1101,0,2056,72,1105,1,73,0,0,0,0,0,0,6,19079,1101,0,47599,66,1102,1,1,67,1101,0,2085,68,1102,556,1,69,1102,1,1,71,1101,2087,0,72,1105,1,73,1,2677,33,22497,1102,1,7499,66,1101,0,3,67,1101,2116,0,68,1102,1,302,69,1101,0,1,71,1101,0,2122,72,1105,1,73,0,0,0,0,0,0,6,38158,1101,0,101359,66,1102,1,1,67,1101,2151,0,68,1102,1,556,69,1102,1,0,71,1102,1,2153,72,1105,1,73,1,1752,1101,48091,0,66,1101,1,0,67,1102,1,2180,68,1101,0,556,69,1101,0,0,71,1101,0,2182,72,1106,0,73,1,1463,1102,5399,1,66,1101,0,2,67,1102,1,2209,68,1101,0,302,69,1102,1,1,71,1101,0,2213,72,1106,0,73,0,0,0,0,6,57237 diff --git a/src/bin/day_23.rs b/src/bin/day_23.rs new file mode 100644 index 0000000..e074cf4 --- /dev/null +++ b/src/bin/day_23.rs @@ -0,0 +1,211 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::vector::Vector; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 23: Category Six")] +/// Executes an Intcode program on a network of computers +/// +/// See https://adventofcode.com/2019/day/23 for details. +struct Opt { + #[structopt(short = "n", long = "network-size")] + network_size: usize, + #[structopt(long = "nat")] + send_nat: 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::(), "Invalid number")) + .collect::(); + + let network = Network::new(program, opt.network_size); + + if opt.send_nat { + println!("{}", network.first_repeated_nat_packet().y); + } else { + println!("{}", network.first_nat_packet().y); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug, Clone)] +struct Network { + computers: Vector, + nat: Option, + is_potentially_idle: bool, + is_idle: bool, +} + +impl Network { + fn new(program: IntcodeProgram, network_size: usize) -> Network { + Network { + computers: (0..network_size) + .map(|ip| program.with_input(list![ip.into(), Intcode::from(-1)])) + .collect(), + nat: None, + is_potentially_idle: false, + is_idle: false, + } + } + + fn first_nat_packet(&self) -> Packet { + iter::successors(Some(self.clone()), |network| Some(network.next())) + .filter_map(|network| network.nat) + .next() + .unwrap() + } + + fn first_repeated_nat_packet(&self) -> Packet { + self.sent_nat_packets() + .zip(self.sent_nat_packets().skip(1)) + // .inspect(|(nat, _p2)| eprintln!("{}", nat.y)) + .find(|(p1, p2)| p1.y == p2.y) + .unwrap() + .0 + } + + fn sent_nat_packets<'a>(&'a self) -> impl Iterator + 'a { + iter::successors(Some(self.clone()), |network| { + Some(network.with_nat_packet_sent().run_to_network_idle()) + }) + .filter_map(|network| network.nat) + } + + fn run_to_network_idle(&self) -> Network { + iter::successors(Some(self.clone()), |network| Some(network.next())) + .find(|network| network.is_idle) + .unwrap() + } + + fn with_nat_packet_sent(&self) -> Network { + if self.nat.is_some() { + Network { + computers: self + .computers + .iter() + .enumerate() + .map(|(ip, computer)| { + computer + .with_additional_input( + self.nat + .iter() + .filter(|packet| packet.dest == Intcode::from(ip)) + .flat_map(|packet| vec![packet.x.clone(), packet.y.clone()]) + .collect(), + ) + .run_to_termination_or_input() + }) + .collect(), + nat: self.nat.clone(), + is_potentially_idle: false, + is_idle: false, + } + } else { + self.clone() + } + } + + fn next(&self) -> Network { + Network { + computers: self + .computers + .iter() + .enumerate() + .map(|(ip, computer)| { + computer + .with_cleared_output() + .with_additional_input(if self.empty_queues() { + list![Intcode::from(-1)] + } else { + list![] + }) + .with_additional_input( + self.pending_packets() + .filter(|packet| packet.dest == Intcode::from(ip)) + .flat_map(|packet| vec![packet.x, packet.y]) + .collect(), + ) + .run_to_termination_or_input() + }) + .collect(), + nat: self + .pending_packets() + .filter(|packet| packet.is_nat()) + .map(|packet| packet.with_dest(0.into())) + .last() + .or_else(|| self.nat.clone()), + is_potentially_idle: self.empty_queues(), + is_idle: self.is_potentially_idle && self.empty_queues(), + } + } + + fn pending_packets<'a>(&'a self) -> impl Iterator + 'a { + self.computers.iter().flat_map(|computer| { + computer + .output + .iter() + .cloned() + .collect::>() + .chunks_exact(3) + .map(|packet| Packet { + dest: packet[0].clone(), + x: packet[1].clone(), + y: packet[2].clone(), + }) + .collect::>() + }) + } + + fn pending_input<'a>(&'a self) -> impl Iterator + 'a { + self.computers + .iter() + .flat_map(|computer| computer.input.iter().cloned().collect::>()) + } + + fn empty_queues(&self) -> bool { + self.pending_packets().count() == 0 && self.pending_input().count() == 0 + } +} + +#[derive(Debug, Clone)] +struct Packet { + dest: Intcode, + x: Intcode, + y: Intcode, +} + +impl Packet { + fn is_nat(&self) -> bool { + self.dest == 255.into() + } + + fn with_dest(&self, dest: Intcode) -> Packet { + Packet { + dest, + ..self.clone() + } + } +} -- cgit v1.2.3 From 6109fe0bb6ad6b642df35f2b6ecd22815dac4fe5 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sat, 11 Jan 2020 20:16:52 +0200 Subject: Day 24: bugs of life --- inputs/day_24.txt | 5 ++ src/bin/day_24.rs | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 inputs/day_24.txt create mode 100644 src/bin/day_24.rs diff --git a/inputs/day_24.txt b/inputs/day_24.txt new file mode 100644 index 0000000..ba900ad --- /dev/null +++ b/inputs/day_24.txt @@ -0,0 +1,5 @@ +##.#. +.##.. +##.#. +.#### +###.. diff --git a/src/bin/day_24.rs b/src/bin/day_24.rs new file mode 100644 index 0000000..ef10ae8 --- /dev/null +++ b/src/bin/day_24.rs @@ -0,0 +1,136 @@ +use rpds::vector::Vector; +use rpds::RedBlackTreeSet; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 24: Planet of Discord")] +/// Simulates the life and death of Eris bugs +/// +/// See https://adventofcode.com/2019/day/24 for details. +struct Opt {} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let initial_state: State = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .collect(); + + println!( + "{}", + initial_state.first_repeated_state().biodiversity_rating() + ); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct State { + grid: Vector>, +} + +impl FromIterator for State { + fn from_iter>(iter: T) -> Self { + State { + grid: iter + .into_iter() + .map(|line| line.chars().map(|c| c == '#').collect::>()) + .collect(), + } + } +} + +impl fmt::Display for State { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.grid + .iter() + .map(|row| { + writeln!( + f, + "{}", + row.iter() + .map(|alive| if *alive { '#' } else { '.' }) + .collect::() + ) + }) + .collect() + } +} + +impl State { + fn first_repeated_state(&self) -> State { + iter::successors( + Some((RedBlackTreeSet::new(), self.clone())), + |(seen, state)| { + eprintln!("{}", state); + Some((seen.insert(state.clone()), state.next())) + }, + ) + .find(|(seen, state)| seen.contains(state)) + .unwrap() + .1 + } + + fn next(&self) -> State { + State { + grid: self + .grid + .iter() + .enumerate() + .map(|(y, row)| { + row.iter() + .enumerate() + .map(|(x, alive)| { + if *alive { + self.count_alive_neighbours(x, y) == 1 + } else { + self.count_alive_neighbours(x, y) == 1 + || self.count_alive_neighbours(x, y) == 2 + } + }) + .collect() + }) + .collect(), + } + } + + fn biodiversity_rating(&self) -> usize { + self.grid + .iter() + .flat_map(|row| row.iter()) + .enumerate() + .map(|(i, state)| if *state { 2_usize.pow(i as u32) } else { 0 }) + .sum() + } + + fn count_alive_neighbours(&self, x: usize, y: usize) -> usize { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .into_iter() + .filter_map(|(dx, dy)| { + if (x > 0 || *dx >= 0) && (y > 0 || *dy >= 0) { + Some(((x as i32 + dx) as usize, (y as i32 + dy) as usize)) + } else { + None + } + }) + .filter(|(x, y)| self.grid.get(*y).and_then(|row| row.get(*x)).cloned() == Some(true)) + .count() + } +} -- cgit v1.2.3 From ed7446803e7ca210909a71936fb23ce9a50f1663 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 12 Jan 2020 16:32:23 +0200 Subject: Refactor buggy game of life to use Set instead of Vector This sets me up for the infinite play space of part 2 --- src/bin/day_24.rs | 113 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 55 deletions(-) diff --git a/src/bin/day_24.rs b/src/bin/day_24.rs index ef10ae8..56c4b94 100644 --- a/src/bin/day_24.rs +++ b/src/bin/day_24.rs @@ -1,4 +1,3 @@ -use rpds::vector::Vector; use rpds::RedBlackTreeSet; use std::fmt; use std::io; @@ -43,45 +42,36 @@ fn exit_on_failed_assertion(data: Result, message #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] struct State { - grid: Vector>, + alive: RedBlackTreeSet, } impl FromIterator for State { fn from_iter>(iter: T) -> Self { State { - grid: iter + alive: iter .into_iter() - .map(|line| line.chars().map(|c| c == '#').collect::>()) + .enumerate() + .flat_map(move |(y, line)| { + line.chars() + .enumerate() + .filter(move |(_x, c)| *c == '#') + .map(move |(x, _c)| Coordinate { + x: x as isize, + y: y as isize, + depth: 0, + }) + .collect::>() + }) .collect(), } } } -impl fmt::Display for State { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.grid - .iter() - .map(|row| { - writeln!( - f, - "{}", - row.iter() - .map(|alive| if *alive { '#' } else { '.' }) - .collect::() - ) - }) - .collect() - } -} - impl State { fn first_repeated_state(&self) -> State { iter::successors( Some((RedBlackTreeSet::new(), self.clone())), - |(seen, state)| { - eprintln!("{}", state); - Some((seen.insert(state.clone()), state.next())) - }, + |(seen, state)| Some((seen.insert(state.clone()), state.next())), ) .find(|(seen, state)| seen.contains(state)) .unwrap() @@ -90,47 +80,60 @@ impl State { fn next(&self) -> State { State { - grid: self - .grid - .iter() - .enumerate() - .map(|(y, row)| { - row.iter() - .enumerate() - .map(|(x, alive)| { - if *alive { - self.count_alive_neighbours(x, y) == 1 - } else { - self.count_alive_neighbours(x, y) == 1 - || self.count_alive_neighbours(x, y) == 2 - } - }) - .collect() - }) + alive: self + .still_alive_next_round() + .chain(self.comes_alive_next_round()) .collect(), } } fn biodiversity_rating(&self) -> usize { - self.grid + self.alive .iter() - .flat_map(|row| row.iter()) - .enumerate() - .map(|(i, state)| if *state { 2_usize.pow(i as u32) } else { 0 }) + .map(|coord| 2_usize.pow((coord.y * 5 + coord.x) as u32)) .sum() } - fn count_alive_neighbours(&self, x: usize, y: usize) -> usize { + fn still_alive_next_round<'a>(&'a self) -> impl Iterator + 'a { + self.alive + .iter() + .filter(move |coord| self.count_alive_neighbours(**coord) == 1) + .cloned() + } + + fn comes_alive_next_round<'a>(&'a self) -> impl Iterator + 'a { + self.alive + .iter() + .flat_map(|coord| Self::neighbours(*coord)) + .filter(move |coord| !self.alive.contains(coord)) + .filter(move |coord| { + self.count_alive_neighbours(*coord) == 1 || self.count_alive_neighbours(*coord) == 2 + }) + } + + fn count_alive_neighbours(&self, coordinate: Coordinate) -> usize { + Self::neighbours(coordinate) + .into_iter() + .filter(|coord| self.alive.contains(coord)) + .count() + } + + fn neighbours(coordinate: Coordinate) -> Vec { [(-1, 0), (1, 0), (0, -1), (0, 1)] .into_iter() - .filter_map(|(dx, dy)| { - if (x > 0 || *dx >= 0) && (y > 0 || *dy >= 0) { - Some(((x as i32 + dx) as usize, (y as i32 + dy) as usize)) - } else { - None - } + .map(|(dx, dy)| Coordinate { + x: coordinate.x + dx, + y: coordinate.y + dy, + depth: coordinate.depth, }) - .filter(|(x, y)| self.grid.get(*y).and_then(|row| row.get(*x)).cloned() == Some(true)) - .count() + .filter(|coord| coord.x >= 0 && coord.x < 5 && coord.y >= 0 && coord.y < 5) + .collect() } } + +#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] +struct Coordinate { + x: isize, + y: isize, + depth: isize, +} -- cgit v1.2.3 From 87572a858c724f1c7414743ad397e79101c46727 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 12 Jan 2020 22:53:40 +0200 Subject: Fractal descent of bugs --- src/bin/day_24.rs | 138 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 119 insertions(+), 19 deletions(-) diff --git a/src/bin/day_24.rs b/src/bin/day_24.rs index 56c4b94..ebc6a1b 100644 --- a/src/bin/day_24.rs +++ b/src/bin/day_24.rs @@ -1,5 +1,4 @@ use rpds::RedBlackTreeSet; -use std::fmt; use std::io; use std::io::prelude::*; use std::iter; @@ -12,7 +11,15 @@ use structopt::StructOpt; /// Simulates the life and death of Eris bugs /// /// See https://adventofcode.com/2019/day/24 for details. -struct Opt {} +struct Opt { + /// How many iterations of the game of life should be run + /// If not provided, runs until a state appears twice. + #[structopt(short = "n")] + depth: Option, + /// Interprets the map as being one part of an infinite fractal map + #[structopt(short = "f")] + fractal: bool, +} fn main() { let stdin = io::stdin(); @@ -22,12 +29,16 @@ fn main() { .lock() .lines() .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .collect(); + .collect::() + .with_fractal_mode(opt.fractal); + + let final_state = match opt.depth { + Some(depth) => initial_state.n_steps_forward(depth), + None => initial_state.first_repeated_state(), + }; - println!( - "{}", - initial_state.first_repeated_state().biodiversity_rating() - ); + println!("Bugs: {}", final_state.alive.size()); + println!("Biodiversity: {}", final_state.biodiversity_rating()); } fn exit_on_failed_assertion(data: Result, message: &str) -> A { @@ -43,6 +54,7 @@ fn exit_on_failed_assertion(data: Result, message #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] struct State { alive: RedBlackTreeSet, + fractal_mode: bool, } impl FromIterator for State { @@ -63,11 +75,25 @@ impl FromIterator for State { .collect::>() }) .collect(), + fractal_mode: false, } } } impl State { + fn with_fractal_mode(&self, fractal_mode: bool) -> State { + State { + fractal_mode, + ..self.clone() + } + } + + fn n_steps_forward(&self, n: usize) -> Self { + iter::successors(Some(self.clone()), |state| Some(state.next())) + .nth(n) + .unwrap() + } + fn first_repeated_state(&self) -> State { iter::successors( Some((RedBlackTreeSet::new(), self.clone())), @@ -84,6 +110,7 @@ impl State { .still_alive_next_round() .chain(self.comes_alive_next_round()) .collect(), + ..self.clone() } } @@ -104,7 +131,7 @@ impl State { fn comes_alive_next_round<'a>(&'a self) -> impl Iterator + 'a { self.alive .iter() - .flat_map(|coord| Self::neighbours(*coord)) + .flat_map(move |coord| self.neighbours(*coord)) .filter(move |coord| !self.alive.contains(coord)) .filter(move |coord| { self.count_alive_neighbours(*coord) == 1 || self.count_alive_neighbours(*coord) == 2 @@ -112,22 +139,95 @@ impl State { } fn count_alive_neighbours(&self, coordinate: Coordinate) -> usize { - Self::neighbours(coordinate) + self.neighbours(coordinate) .into_iter() .filter(|coord| self.alive.contains(coord)) .count() } - fn neighbours(coordinate: Coordinate) -> Vec { - [(-1, 0), (1, 0), (0, -1), (0, 1)] - .into_iter() - .map(|(dx, dy)| Coordinate { - x: coordinate.x + dx, - y: coordinate.y + dy, - depth: coordinate.depth, - }) - .filter(|coord| coord.x >= 0 && coord.x < 5 && coord.y >= 0 && coord.y < 5) - .collect() + fn neighbours(&self, coordinate: Coordinate) -> Vec { + if self.fractal_mode { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .into_iter() + .map(|(dx, dy)| Coordinate { + x: coordinate.x + dx, + y: coordinate.y + dy, + depth: coordinate.depth, + }) + .flat_map(move |coord| match (coord.x, coord.y) { + (x, _y) if x < 0 => vec![Coordinate { + x: 1, + y: 2, + depth: coord.depth - 1, + }] + .into_iter(), + (_x, y) if y < 0 => vec![Coordinate { + x: 2, + y: 1, + depth: coord.depth - 1, + }] + .into_iter(), + (x, _y) if x >= 5 => vec![Coordinate { + x: 3, + y: 2, + depth: coord.depth - 1, + }] + .into_iter(), + (_x, y) if y >= 5 => vec![Coordinate { + x: 2, + y: 3, + depth: coord.depth - 1, + }] + .into_iter(), + (2, 2) => match (coordinate.x, coordinate.y) { + (1, 2) => (0..5) + .map(|y| Coordinate { + x: 0, + y, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (2, 1) => (0..5) + .map(|x| Coordinate { + x, + y: 0, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (3, 2) => (0..5) + .map(|y| Coordinate { + x: 4, + y, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (2, 3) => (0..5) + .map(|x| Coordinate { + x, + y: 4, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (_, _) => vec![].into_iter(), + }, + _ => vec![coord.clone()].into_iter(), + }) + .collect() + } else { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .into_iter() + .map(|(dx, dy)| Coordinate { + x: coordinate.x + dx, + y: coordinate.y + dy, + depth: coordinate.depth, + }) + .filter(|coord| coord.x >= 0 && coord.x < 5 && coord.y >= 0 && coord.y < 5) + .collect() + } } } -- cgit v1.2.3 From fa3b0d8cb573a2a0700fa565d6cf12abf66dc70f Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Mon, 13 Jan 2020 23:08:19 +0200 Subject: Day 25: Text adventure game! --- inputs/day_25.txt | 1 + src/bin/day_25.dot | 43 +++++++++++++++++++++ src/bin/day_25.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 14 +++---- 4 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 inputs/day_25.txt create mode 100644 src/bin/day_25.dot create mode 100644 src/bin/day_25.rs diff --git a/inputs/day_25.txt b/inputs/day_25.txt new file mode 100644 index 0000000..5351575 --- /dev/null +++ b/inputs/day_25.txt @@ -0,0 +1 @@ +109,4795,21102,1,3124,1,21102,1,13,0,1106,0,1424,21102,1,166,1,21101,24,0,0,1105,1,1234,21102,31,1,0,1106,0,1984,1106,0,13,6,4,3,2,52,51,21,4,28,56,55,3,19,-9,-10,47,89,88,90,90,6,77,73,85,71,1,76,68,63,65,22,-27,70,76,81,87,5,105,105,107,108,95,4,97,92,109,109,5,110,105,110,108,95,4,115,96,109,109,13,-3,59,101,85,92,97,13,84,80,92,78,34,-15,26,-16,46,88,72,79,84,0,72,76,-3,85,74,79,75,-8,64,68,75,57,65,70,64,66,72,8,-41,32,-22,56,77,82,-4,60,76,62,70,-2,74,-11,55,52,68,67,73,56,60,52,-20,44,56,66,-24,48,58,42,49,54,-16,-53,10,0,56,99,96,95,82,94,83,45,-9,23,-13,61,85,88,74,71,82,73,79,73,89,67,65,-4,62,73,70,69,56,68,57,2,-35,24,-14,64,85,90,4,70,67,79,7,83,-2,68,75,-5,78,65,57,75,-10,76,53,76,0,-37,31,-21,57,78,83,-3,64,74,72,0,76,-9,73,58,57,-13,70,57,49,67,-18,54,64,48,55,-23,48,44,56,42,-14,-51,14,-4,74,95,100,14,97,77,86,79,9,92,79,75,5,27,-17,61,82,87,1,68,78,76,4,80,-5,66,58,78,60,-10,73,60,52,70,-15,57,67,51,58,-6,-43,14,-4,74,95,100,14,81,94,90,90,9,92,79,75,5,60,-50,23,42,38,-32,38,39,30,42,47,-38,30,36,28,25,41,38,34,31,18,23,29,19,33,-52,20,29,-55,27,27,27,8,15,-61,22,16,-64,24,13,18,-54,-69,-70,-14,7,12,-74,-8,-11,1,-71,5,-80,-4,-3,3,-15,-84,-85,-109,29,-19,59,80,85,-1,82,62,71,64,-6,77,64,60,-10,62,66,57,59,63,57,67,51,-19,56,58,57,57,-10,-47,44,-34,39,58,54,-16,60,61,57,64,48,56,-23,52,40,60,38,-28,44,53,-31,55,32,55,-35,48,42,41,-39,32,38,42,-42,-44,12,33,38,-48,28,19,25,32,-52,-76,-77,59,-49,13,55,-30,42,51,-33,49,50,32,31,31,39,36,48,-42,24,35,32,34,29,21,35,19,25,37,-53,14,10,26,18,-57,-59,-3,18,23,-63,1,17,3,-67,1,-4,14,-2,6,-73,-8,14,-76,-12,-78,-40,2,4,-13,-82,-106,-107,35,-25,53,74,79,0,74,60,-10,65,53,72,64,52,56,52,50,-19,53,57,62,56,-24,58,54,38,39,40,-29,-31,2,56,35,-34,-58,-59,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-94,-98,-103,-83,-97,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-90,-94,-97,-97,-86,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,263,-253,-199,-233,-158,-156,-151,-169,-226,-239,-158,-162,-176,-164,-160,-172,-179,-247,-162,-170,-177,-184,-183,-253,-171,-190,-167,-174,-258,-257,-227,-183,-197,-187,-175,-182,-193,-184,-268,-202,-191,-194,-192,-197,-205,-191,-207,-276,-278,-222,-201,-196,-282,-206,-219,-196,-286,-207,-206,-210,-223,-222,-223,-225,-280,-293,-296,-232,-220,-231,-300,-212,-223,-218,-304,-236,-228,-223,-239,-227,-310,-227,-240,-244,-314,-248,-237,-250,-243,-239,-247,-237,-308,-345,-273,-260,-248,-243,-263,-329,-252,-252,-248,-260,-267,-266,-253,-337,-249,-260,-255,-259,-342,-260,-267,-280,-270,-271,-348,-281,-268,-272,-279,-285,-342,-355,-280,-278,-279,-284,-277,-361,-282,-278,-274,-275,-290,-298,-300,-369,-300,-292,-290,-373,-309,-375,-299,-298,-301,-310,-302,-297,-370,-383,-302,-316,-321,-311,-315,-299,-321,-308,-392,-306,-322,-330,-312,-397,-326,-334,-317,-401,-330,-338,-324,-325,-337,-329,-339,-341,-398,-411,-347,-335,-346,-415,-334,-352,-350,-346,-341,-338,-422,-334,-345,-340,-344,-427,-345,-357,-357,-351,-432,-365,-361,-353,-367,-370,-354,-363,-351,-427,-464,-441,-397,-373,-434,-447,-376,-380,-374,-375,-373,-452,-454,-398,-377,-372,-458,-376,-388,-382,-377,-387,-396,-465,-400,-398,-468,-404,-404,-395,-403,-473,-390,-396,-476,-406,-409,-395,-480,-408,-404,-483,-418,-396,-486,-403,-399,-409,-417,-413,-421,-493,37,-5,73,71,-8,75,62,58,-12,62,55,74,64,48,50,-19,45,63,-22,61,48,44,-26,50,37,44,48,-31,33,40,48,41,43,30,37,-25,-38,-63,0,0,109,7,21101,0,0,-2,22208,-2,-5,-1,1205,-1,1169,22202,-2,-4,1,22201,1,-6,1,21202,-2,1,2,21102,1162,1,0,2105,1,-3,21201,-2,1,-2,1106,0,1136,109,-7,2106,0,0,109,6,2101,0,-5,1182,20101,0,0,-2,21102,0,1,-3,21201,-5,1,-5,22208,-3,-2,-1,1205,-1,1229,2201,-5,-3,1205,20101,0,0,1,22102,1,-3,2,21202,-2,1,3,21102,1,1222,0,2105,1,-4,21201,-3,1,-3,1105,1,1192,109,-6,2106,0,0,109,2,21202,-1,1,1,21101,1256,0,2,21102,1251,1,0,1106,0,1174,109,-2,2105,1,0,109,5,22201,-4,-3,-1,22201,-2,-1,-1,204,-1,109,-5,2106,0,0,109,3,1202,-2,1,1280,1006,0,1303,104,45,104,32,1201,-1,66,1291,21002,0,1,1,21101,1301,0,0,1105,1,1234,104,10,109,-3,2105,1,0,0,0,109,2,2101,0,-1,1309,1102,1,0,1308,21102,1,4601,1,21102,13,1,2,21101,4,0,3,21102,1,1353,4,21101,1343,0,0,1105,1,1130,20102,1,1308,-1,109,-2,2106,0,0,63,109,3,1201,-2,0,1360,20008,0,1309,-1,1206,-1,1419,1005,1308,1398,1102,1,1,1308,21008,1309,-1,-1,1206,-1,1387,21102,106,1,1,1106,0,1391,21101,0,92,1,21102,1,1398,0,1106,0,1234,104,45,104,32,1201,-2,1,1407,21002,0,1,1,21102,1417,1,0,1105,1,1234,104,10,109,-3,2105,1,0,109,3,1202,-2,1,1128,21102,1,34,1,21101,0,1441,0,1106,0,1234,1001,1128,0,1447,20101,0,0,1,21102,1,1456,0,1105,1,1234,21102,1,41,1,21101,1467,0,0,1105,1,1234,1001,1128,1,1472,21002,0,1,1,21101,1482,0,0,1105,1,1234,21102,46,1,1,21102,1493,1,0,1105,1,1234,21001,1128,3,1,21102,4,1,2,21102,1,1,3,21102,1,1273,4,21101,1516,0,0,1106,0,1130,21001,1128,0,1,21102,1,1527,0,1105,1,1310,1001,1128,2,1532,21002,0,1,-1,1206,-1,1545,21101,0,1545,0,2105,1,-1,109,-3,2106,0,0,109,0,99,109,2,1102,1,0,1550,21101,0,4601,1,21102,13,1,2,21101,4,0,3,21101,1664,0,4,21102,1,1582,0,1105,1,1130,2,2486,1352,1551,1102,0,1,1552,21001,1550,0,1,21102,1,33,2,21101,0,1702,3,21102,1,1609,0,1106,0,2722,21007,1552,0,-1,1205,-1,1630,20107,0,1552,-1,1205,-1,1637,21102,1,1630,0,1106,0,1752,21101,0,548,1,1106,0,1641,21101,687,0,1,21101,0,1648,0,1105,1,1234,21101,0,4457,1,21101,1659,0,0,1106,0,1424,109,-2,2105,1,0,109,4,21202,-2,-1,-2,2102,1,-3,1675,21008,0,-1,-1,1206,-1,1697,1201,-3,2,1687,20101,-27,0,-3,22201,-3,-2,-3,2001,1550,-3,1550,109,-4,2105,1,0,109,5,21008,1552,0,-1,1206,-1,1747,1201,-3,1901,1717,20101,0,0,-2,1205,-4,1736,20207,-2,1551,-1,1205,-1,1747,1102,-1,1,1552,1105,1,1747,22007,1551,-2,-1,1205,-1,1747,1102,1,1,1552,109,-5,2105,1,0,109,1,21101,826,0,1,21102,1765,1,0,1105,1,1234,21002,1550,1,1,21102,1776,1,0,1105,1,2863,21102,1090,1,1,21102,1787,1,0,1106,0,1234,99,1106,0,1787,109,-1,2106,0,0,109,1,21101,512,0,1,21101,0,1809,0,1106,0,1234,99,1105,1,1809,109,-1,2105,1,0,109,1,1102,1,1,1129,109,-1,2106,0,0,109,1,21102,1,377,1,21101,0,1842,0,1105,1,1234,1106,0,1831,109,-1,2106,0,0,109,1,21101,407,0,1,21101,1863,0,0,1105,1,1234,99,1106,0,1863,109,-1,2106,0,0,109,1,21102,1,452,1,21101,1885,0,0,1106,0,1234,99,1106,0,1885,109,-1,2105,1,0,1941,1947,1953,1958,1965,1972,1978,4083,3936,4362,4458,4463,4254,3769,4145,4116,3848,4384,3957,4371,4258,3951,4063,3935,4053,4163,4259,3817,4062,4500,3970,4331,4022,3969,4163,4483,4089,3810,4092,4196,2281,2468,2418,2450,2487,2125,2505,5,95,108,104,104,23,5,96,91,108,108,1,4,101,105,112,3,6,104,104,106,107,94,-1,6,109,104,109,107,94,-1,5,111,91,100,93,23,5,114,95,108,108,1,109,3,21102,1993,1,0,1106,0,2634,1006,1129,2010,21101,0,316,1,21101,0,2007,0,1106,0,1234,1106,0,2076,21101,0,0,-1,1201,-1,1894,2019,21001,0,0,1,21102,0,1,2,21102,1,0,3,21101,0,2037,0,1106,0,2525,1206,1,2054,1201,-1,1934,2050,21102,2051,1,0,106,0,0,1105,1,2076,21201,-1,1,-1,21207,-1,7,-2,1205,-2,2014,21101,0,177,1,21102,1,2076,0,1105,1,1234,109,-3,2105,1,0,109,3,2001,1128,-2,2088,21002,0,1,-1,1205,-1,2108,21101,201,0,1,21101,2105,0,0,1105,1,1234,1106,0,2119,22101,0,-1,1,21101,2119,0,0,1106,0,1424,109,-3,2105,1,0,0,109,1,1101,0,0,2124,21101,0,4601,1,21101,0,13,2,21101,0,4,3,21102,2173,1,4,21102,2154,1,0,1106,0,1130,1005,2124,2168,21102,226,1,1,21102,2168,1,0,1106,0,1234,109,-1,2106,0,0,109,3,1005,2124,2275,1201,-2,0,2183,20008,0,1128,-1,1206,-1,2275,1201,-2,1,2195,20102,1,0,-1,21202,-1,1,1,21102,5,1,2,21102,1,1,3,21102,2216,1,0,1106,0,2525,1206,1,2275,21102,1,258,1,21101,2230,0,0,1105,1,1234,21202,-1,1,1,21101,0,2241,0,1106,0,1234,104,46,104,10,1101,1,0,2124,1201,-2,0,2256,1101,0,-1,0,1201,-2,3,2262,21002,0,1,-1,1206,-1,2275,21101,2275,0,0,2105,1,-1,109,-3,2106,0,0,0,109,1,1101,0,0,2280,21101,4601,0,1,21101,0,13,2,21102,1,4,3,21102,1,2329,4,21102,1,2310,0,1106,0,1130,1005,2280,2324,21102,1,273,1,21102,1,2324,0,1105,1,1234,109,-1,2105,1,0,109,3,1005,2280,2413,1201,-2,0,2339,21008,0,-1,-1,1206,-1,2413,1201,-2,1,2351,20102,1,0,-1,22101,0,-1,1,21102,5,1,2,21101,1,0,3,21102,2372,1,0,1105,1,2525,1206,1,2413,21102,301,1,1,21102,2386,1,0,1106,0,1234,22102,1,-1,1,21102,2397,1,0,1106,0,1234,104,46,104,10,1102,1,1,2280,1201,-2,0,2412,101,0,1128,0,109,-3,2106,0,0,109,1,21101,0,-1,1,21102,1,2431,0,1105,1,1310,1205,1,2445,21102,1,133,1,21101,0,2445,0,1106,0,1234,109,-1,2106,0,0,109,1,21102,3,1,1,21101,2463,0,0,1106,0,2081,109,-1,2106,0,0,109,1,21101,4,0,1,21102,1,2481,0,1105,1,2081,109,-1,2106,0,0,70,109,1,21102,5,1,1,21102,2500,1,0,1105,1,2081,109,-1,2105,1,0,109,1,21102,6,1,1,21102,2518,1,0,1105,1,2081,109,-1,2106,0,0,0,0,109,5,2102,1,-3,2523,1101,0,1,2524,21202,-4,1,1,21101,0,2585,2,21101,2550,0,0,1105,1,1174,1206,-2,2576,2101,0,-4,2558,2001,0,-3,2566,101,3094,2566,2566,21008,0,-1,-1,1205,-1,2576,1102,0,1,2524,21001,2524,0,-4,109,-5,2105,1,0,109,5,22201,-4,-3,-4,22201,-4,-2,-4,21208,-4,10,-1,1206,-1,2606,21102,-1,1,-4,201,-3,2523,2615,1001,2615,3094,2615,21002,0,1,-1,22208,-4,-1,-1,1205,-1,2629,1101,0,0,2524,109,-5,2106,0,0,109,4,21101,0,3094,1,21102,30,1,2,21101,1,0,3,21102,1,2706,4,21102,1,2659,0,1105,1,1130,21101,0,0,-3,203,-2,21208,-2,10,-1,1205,-1,2701,21207,-2,0,-1,1205,-1,2663,21207,-3,29,-1,1206,-1,2663,2101,3094,-3,2693,2102,1,-2,0,21201,-3,1,-3,1106,0,2663,109,-4,2105,1,0,109,2,1201,-1,0,2715,1102,-1,1,0,109,-2,2105,1,0,0,109,5,2102,1,-2,2721,21207,-4,0,-1,1206,-1,2739,21102,1,0,-4,21202,-4,1,1,21202,-3,1,2,21102,1,1,3,21101,0,2758,0,1105,1,2763,109,-5,2106,0,0,109,6,21207,-4,1,-1,1206,-1,2786,22207,-5,-3,-1,1206,-1,2786,21201,-5,0,-5,1105,1,2858,22101,0,-5,1,21201,-4,-1,2,21202,-3,2,3,21101,0,2805,0,1105,1,2763,21202,1,1,-5,21101,0,1,-2,22207,-5,-3,-1,1206,-1,2824,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2850,22102,1,-2,1,21201,-4,-1,2,21101,0,2850,0,105,1,2721,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2105,1,0,109,3,21208,-2,0,-1,1205,-1,2902,21207,-2,0,-1,1205,-1,2882,1105,1,2888,104,45,21202,-2,-1,-2,21201,-2,0,1,21102,2899,1,0,1106,0,2909,1106,0,2904,104,48,109,-3,2106,0,0,109,4,22102,1,-3,1,21101,10,0,2,21101,0,2926,0,1105,1,3010,21201,1,0,-2,21201,2,0,-1,1206,-2,2948,22101,0,-2,1,21101,0,2948,0,1106,0,2909,22101,48,-1,-1,204,-1,109,-4,2105,1,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21101,0,0,-4,21101,0,0,-3,21102,1,51,-2,21201,-2,-1,-2,1201,-2,2959,3034,20101,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,3059,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,3078,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,3024,21202,-4,1,-7,21202,-3,1,-6,109,-8,2106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3131,3143,0,3252,3527,0,0,11,61,105,95,94,17,50,97,83,78,79,83,108,-19,2,7,-79,-9,-2,2,-83,-11,-7,-86,-3,-16,-7,-11,-6,-21,-21,-94,-30,-96,-25,-19,-23,-31,-101,-29,-25,-104,-21,-34,-38,-108,-39,-34,-32,-33,-31,-114,-43,-47,-35,-49,-105,-120,-69,-43,-123,-49,-56,-57,-47,-128,-40,-51,-46,-50,-133,-51,-63,-63,-57,-138,-69,-58,-62,-65,-143,-79,-69,-63,-68,-148,-79,-68,-82,-83,-63,-81,-77,-85,-145,-158,-75,-88,-92,-162,-91,-85,-89,-97,-167,-96,-104,-87,-171,-106,-104,-105,-97,-176,-94,-109,-114,-104,-112,-114,-169,3259,3267,0,3344,0,3124,0,7,65,89,99,98,108,85,108,76,8,27,27,36,-48,16,32,18,13,-53,18,10,27,-57,8,10,9,17,-62,16,16,19,7,10,5,21,-1,-3,-72,-3,5,7,-76,6,1,-2,-11,3,-10,-10,-6,-14,-59,-87,1,-10,-5,-84,-10,-24,-94,-21,-11,-14,-14,-99,-22,-22,-18,-103,-23,-20,-33,-23,-39,-109,-27,-26,-30,-44,-114,-28,-44,-52,-34,-105,3351,3359,0,0,3408,3252,0,7,76,108,102,104,86,91,88,48,36,55,51,-19,46,58,66,46,59,-25,48,58,55,55,-30,36,47,45,50,30,37,41,-38,38,39,41,27,-43,22,34,42,22,35,-35,-50,-51,-2,16,13,30,26,26,15,27,9,15,27,-49,3415,3423,0,0,3458,4392,3344,7,76,108,88,88,97,89,102,34,48,66,69,73,62,62,61,73,3,72,61,77,55,53,-2,-17,34,53,49,68,-15,59,45,-25,39,49,48,-29,39,46,48,51,55,-21,3465,3486,0,3584,0,4053,3408,20,51,84,80,93,8,62,88,70,84,83,75,79,71,-1,33,66,74,79,63,75,40,32,70,77,-11,57,63,69,54,-16,51,61,-19,69,58,63,-23,63,57,39,53,-28,51,52,38,51,36,44,49,47,-37,41,39,-40,43,30,26,-44,26,33,-16,3534,3548,0,0,0,0,3124,13,54,100,86,103,15,63,98,77,93,94,78,90,90,35,49,68,64,-6,59,61,59,73,-11,53,69,55,-15,49,59,58,-19,64,58,57,-23,59,52,39,49,48,-29,40,48,50,-33,55,44,49,-23,3591,3600,0,0,3732,3458,3673,8,75,96,89,96,20,53,83,106,72,11,44,38,37,35,37,38,36,-48,17,29,33,20,-53,-4,14,12,-44,-12,20,23,8,6,-63,-14,4,7,11,0,0,-1,11,-72,4,-5,-7,-3,-10,-5,-1,-11,-81,-17,-5,-16,-85,-4,-18,-17,-4,-14,-26,-10,-93,-12,-26,-23,-19,-30,-30,-31,-19,-102,-26,-35,-37,-33,-40,-35,-31,-41,-97,3680,3703,0,3901,3584,0,4241,22,50,88,92,7,41,77,83,70,81,77,65,83,67,-3,34,74,79,71,76,56,63,67,28,55,82,79,70,72,78,85,9,-4,68,78,0,75,-9,73,73,61,63,62,-15,71,62,64,56,53,57,49,-9,3739,3748,0,3828,0,3981,3584,8,59,102,104,103,93,87,97,99,79,5,24,20,-50,26,17,31,11,21,-56,30,7,17,16,22,-62,2,14,3,-66,17,4,0,-70,6,-3,11,-9,1,-76,-7,-2,0,-1,1,-82,-18,-2,-16,-86,-4,-12,-16,-19,-19,-8,-17,-5,-95,-28,-24,-28,-29,-31,-19,-33,-25,-20,-105,-39,-28,-32,-30,-28,-28,-98,-113,-67,-33,-116,-52,-36,-50,-120,-37,-50,-54,-35,-94,3835,3844,0,4166,0,3732,0,8,64,102,98,100,88,88,85,92,56,27,54,51,42,51,49,39,-31,51,36,35,42,47,-37,46,40,-40,31,23,43,25,-45,30,22,22,35,-50,22,32,-53,25,23,-56,27,14,10,-60,-22,11,2,14,19,-66,-28,14,4,-2,-71,11,-4,10,9,-3,1,-7,-65,3908,3920,0,0,0,3673,0,11,68,86,102,87,99,102,80,98,92,94,100,60,24,43,39,51,37,-33,31,47,33,-37,27,-39,30,28,45,-43,40,24,30,22,35,18,29,29,17,30,-27,-55,28,15,11,30,-53,21,7,-63,1,11,10,-67,-2,10,6,13,-3,-5,-74,-7,3,10,0,-67,-80,3,-10,-4,1,-14,-14,-73,3988,3997,0,3732,4095,0,0,8,72,88,105,104,85,90,87,100,55,29,48,44,63,-20,54,40,-30,34,-32,43,39,49,48,39,31,-39,44,46,31,40,40,44,-46,18,30,19,-50,32,32,12,28,29,17,21,13,-59,24,18,-62,13,15,14,9,-67,-3,7,6,-71,-7,3,-1,0,-7,-63,4060,4068,0,3458,0,0,0,7,68,97,107,89,93,89,97,26,43,91,73,85,91,85,72,72,76,68,3,78,-6,63,74,60,59,79,57,0,54,67,57,52,50,-5,4102,4114,0,0,0,4337,3981,11,58,98,90,91,95,85,84,96,86,90,82,51,38,59,64,-22,60,45,44,-26,38,-28,58,42,42,52,36,32,44,29,45,30,-39,47,32,42,29,-44,35,30,18,30,34,-50,19,27,29,-54,-4,24,25,15,19,11,7,20,16,9,3,-66,19,-50,-55,4173,4185,0,0,0,3828,0,11,72,87,92,87,95,83,84,14,57,77,77,55,34,55,60,-26,56,41,40,-30,38,54,40,34,34,42,30,31,-39,32,28,40,26,-44,34,24,-47,32,33,29,33,27,31,35,25,13,-57,22,20,16,28,15,6,18,-65,2,2,15,4,1,7,-72,14,5,7,-1,-63,4248,4259,0,0,3673,0,0,10,68,86,106,92,89,82,100,88,93,91,77,6,38,18,36,36,33,-25,-52,-2,30,27,9,21,10,10,8,-47,-62,-15,12,4,-1,16,1,-69,13,14,8,7,2,14,-76,0,-9,-14,3,4,0,-14,-7,-16,-8,-3,-5,-89,-20,-9,-13,-16,-94,-25,-23,-27,-14,-10,-100,-18,-18,-38,-22,-22,-106,-23,-29,-109,-28,-42,-45,-48,-38,-42,-50,-35,-53,-35,-51,-107,4344,4351,0,4095,0,0,0,6,59,107,91,88,90,90,40,38,70,68,58,-12,66,56,-15,68,55,51,-19,47,44,44,50,54,44,58,56,-28,54,39,38,45,-33,50,44,-36,35,27,47,29,-41,38,36,43,24,36,-33,4399,4422,0,3408,0,4457,0,22,65,74,90,87,6,41,86,76,88,70,0,44,63,70,74,79,63,71,57,69,57,58,34,39,81,-4,60,74,73,61,56,72,72,-12,71,65,-15,50,52,-18,68,59,61,53,50,54,46,-26,51,51,53,47,34,44,43,55,-21,4464,4484,0,4392,4556,0,0,19,64,81,78,95,91,81,91,95,5,39,75,71,68,75,79,77,70,74,79,71,2,38,-41,42,29,25,-45,32,22,40,35,-50,31,27,26,23,-43,-56,8,-58,21,22,8,21,20,21,17,3,-54,15,0,8,12,1,11,-1,11,-7,-77,-8,-3,-1,-2,0,-83,3,-12,-10,-11,-88,-3,-21,-9,-19,-23,-5,-95,-7,-18,-13,-17,-100,-28,-34,-34,-26,-21,-33,-23,-19,-95,4563,4588,1553,0,0,0,4457,24,56,89,75,88,87,88,84,70,13,50,67,75,79,68,78,66,78,60,-10,27,64,66,65,67,12,53,97,83,93,105,105,87,91,83,25,24,23,3981,4653,16777243,0,3344,4659,32796,0,4166,4672,67108893,0,3252,4683,46,0,3673,4699,31,1818,3527,4719,536870944,0,3408,4727,268435489,0,3584,4741,34,1829,3828,4755,35,1850,4241,4767,36,1796,4053,4778,1061,0,4337,4782,38,1872,3901,4790,41,0,5,110,98,94,100,99,12,95,95,87,90,94,15,80,92,96,95,86,78,10,106,86,97,85,97,102,98,88,92,82,15,104,85,80,98,85,81,93,10,86,73,74,78,78,82,72,19,84,85,76,88,93,8,76,82,74,71,87,84,80,77,64,69,75,65,79,7,90,102,107,91,99,98,84,13,102,98,96,95,91,14,92,82,11,77,74,92,29,13,92,96,87,89,93,87,97,81,11,86,88,87,87,11,98,99,95,102,86,94,15,90,78,98,76,10,91,104,87,84,98,86,16,95,93,81,3,106,113,98,7,105,96,102,106,100,98,102,4,95,92,101,94 diff --git a/src/bin/day_25.dot b/src/bin/day_25.dot new file mode 100644 index 0000000..58dc131 --- /dev/null +++ b/src/bin/day_25.dot @@ -0,0 +1,43 @@ +digraph { + Breach [label="Hull Breach"] + Crew [label="Crew Quarters (antenna)"] + Hallway [label="Hallway (weather machine)"] + Storage [label="Storage (klein bottle)"] + Stables [label="Stables (spool of cat6)"] + Warp [label="Warp Drive Maintenance"] + Security [label="Security Checkpoint"] + Pressure [label="Pressure-Sensitive Floor"] + Gift [label="Gift Wrapping Center"] + Sick [label="Sick Bay (infinite loop X)"] + Chocolate [label="Hot Chocolate Fountain (giant electromagnet X)"] + Observatory [label="Observatory (cake)"] + Navigation [label="Navigation (escape pod XX)"] + Corridor [label="Corridor"] + Holodeck [label="Holodeck (molten lava X)"] + Science [label="Science Lab (tambourine)"] + Passages [label="Passages (shell)"] + Engineering [label="Engineering"] + Arcade [label="Arcade (photons X)"] + Kitchen [label="Kitchen (mug)"] + + + Breach -> Crew [label=East] + Breach -> Hallway [label=North] + Hallway -> Storage [label=North] + Storage -> Stables [label=East] + Stables -> Warp [label=South] + Warp -> Security [label=South] + Security -> Pressure [label=East] + Stables -> Gift [label=East] + Gift -> Sick [label=North] + Sick -> Chocolate [label=West] + Chocolate -> Observatory [label=North] + Chocolate -> Navigation [label=West] + Corridor -> Holodeck [label=North] + Holodeck -> Science [label=North] + Sick -> Corridor [label=East] + Corridor -> Passages [label=South] + Passages -> Engineering [label=East] + Engineering -> Arcade [label=South] + Gift -> Kitchen [label=South] +} diff --git a/src/bin/day_25.rs b/src/bin/day_25.rs new file mode 100644 index 0000000..5c132cd --- /dev/null +++ b/src/bin/day_25.rs @@ -0,0 +1,110 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 25: Cryostasis")] +/// Pilots a robot to save Santa! +/// +/// See https://adventofcode.com/2019/day/25 for details. +struct Opt {} + +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::(); + + let input = vec![ + "east", + "take antenna", + "west", + "north", + "take weather machine", + "north", + "take klein bottle", + "east", + "take spool of cat6", + "east", + "south", + "take mug", + "north", + "north", + "west", + "north", + "take cake", + "south", + "east", + "east", + "north", + "north", + "take tambourine", + "south", + "south", + "south", + "take shell", + "north", + "west", + "south", + "west", + "south", + "south", + "inv", + //"drop mug", + //"drop weather machine", + "drop cake", + "drop shell", + "drop klein bottle", + "drop tambourine", + //"drop antenna", + //"drop spool of cat6", + "east", + ]; + + let result = exit_on_failed_assertion( + program + .with_input( + input + .iter() + .flat_map(|line| { + line.chars() + .map(|c| Intcode::from(c as u8)) + .chain(vec![Intcode::from(10)].into_iter()) + }) + .collect(), + ) + .run_to_termination_or_input() + .output_into_result(), + "Program failed", + ); + + println!( + "{}", + result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", result.last().unwrap()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 5df59f4..7a14d3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,6 +125,13 @@ impl IntcodeProgram { .unwrap() } + pub fn output_into_result(&self) -> Result, IntcodeProgramError> { + match self.error { + Some(ref error) => Err(error.clone()), + None => Ok(self.output.clone()), + } + } + fn with_instruction_pointer(&self, instruction_pointer: Intcode) -> IntcodeProgram { IntcodeProgram { instruction_pointer, @@ -170,13 +177,6 @@ impl IntcodeProgram { } } - fn output_into_result(&self) -> Result, IntcodeProgramError> { - match self.error { - Some(ref error) => Err(error.clone()), - None => Ok(self.output.clone()), - } - } - fn memory_0_into_result(&self) -> Result { match self.error { Some(ref error) => Err(error.clone()), -- cgit v1.2.3 From c6c98371c471cba796560164a25a5c4bd29862fa Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Sun, 19 Jan 2020 23:34:09 +0200 Subject: Replace custom debug with derivative --- Cargo.lock | 47 +++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/lib.rs | 26 ++++++++------------------ 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02e042e..52c69da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,7 @@ version = "0.1.0" dependencies = [ "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "cached 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derivative 1.0.3 (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)", "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -124,6 +125,16 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "derivative" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive_more" version = "0.99.2" @@ -280,6 +291,14 @@ dependencies = [ "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "1.0.6" @@ -288,6 +307,14 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "1.0.2" @@ -405,6 +432,16 @@ dependencies = [ "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "1.0.11" @@ -438,6 +475,11 @@ name = "unicode-width" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-xid" version = "0.2.0" @@ -486,6 +528,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" +"checksum derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "942ca430eef7a3806595a6737bc388bf51adb888d3fc0dd1b50f1c170167ee3a" "checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" @@ -504,7 +547,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" @@ -520,11 +565,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" "checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" diff --git a/Cargo.toml b/Cargo.toml index a5c6e6a..c5937b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] structopt = "0.3.5" derive_more = "0.99.2" +derivative = "1.0.3" im = "14.0.0" rpds = "0.7.0" archery = "0.3.0" diff --git a/src/lib.rs b/src/lib.rs index 7a14d3c..08082d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +use derivative::Derivative; use num::bigint::BigInt; use num::traits::identities::Zero; use rpds::RedBlackTreeMap; @@ -10,15 +11,21 @@ use std::iter::Iterator; pub type Intcode = BigInt; -#[derive(Clone)] +#[derive(Clone, Derivative)] +#[derivative(Debug)] pub struct IntcodeProgram { + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] instruction_pointer: Intcode, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] relative_base: Intcode, pub error: Option, pub halted: bool, pub awaiting_input: bool, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] memory: RedBlackTreeMap, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] pub input: List, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] pub output: Vector, } @@ -41,23 +48,6 @@ impl FromIterator for IntcodeProgram { } } -impl fmt::Debug for IntcodeProgram { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!( - f, - "IntcodeProgram {{ \nins: {}, base: {}, error: {:?}, halted: {}, awaiting_input: {} \nmemory: {}, \ninput: {}, \n output: {} \n}}", - self.instruction_pointer, - self.relative_base, - self.error, - self.halted, - self.awaiting_input, - format!("{:?}", self.memory.iter().map(|(k, v)| format!("{} -> {}", k, v)).collect::>()), - format!("{:?}", self.input.iter().map(|n| format!("{}", n)).collect::>()), - format!("{:?}", self.output.iter().map(|n| format!("{}", n)).collect::>()), - ) - } -} - pub fn intcode_to_bool(i: &Intcode) -> bool { *i != Intcode::from(0) } -- cgit v1.2.3 From cd651c866df78df8f050dcca1698d244ab0baee5 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 23 Jan 2020 00:49:30 +0200 Subject: Clean up unused imports --- src/bin/day_12.rs | 2 -- src/bin/day_18.rs | 1 - src/bin/day_19.rs | 3 --- src/bin/day_25.rs | 2 +- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/bin/day_12.rs b/src/bin/day_12.rs index fa0db20..7e42f4c 100644 --- a/src/bin/day_12.rs +++ b/src/bin/day_12.rs @@ -1,5 +1,3 @@ -use rpds::vector::Vector; -use std::fmt; use std::io; use std::io::prelude::*; use std::iter; diff --git a/src/bin/day_18.rs b/src/bin/day_18.rs index 34db7f9..255baa0 100644 --- a/src/bin/day_18.rs +++ b/src/bin/day_18.rs @@ -1,5 +1,4 @@ use rpds::rbt_set; -use rpds::vector; use rpds::vector::Vector; use rpds::RedBlackTreeMap; use rpds::RedBlackTreeSet; diff --git a/src/bin/day_19.rs b/src/bin/day_19.rs index d5ee7f2..73c8374 100644 --- a/src/bin/day_19.rs +++ b/src/bin/day_19.rs @@ -4,11 +4,8 @@ use cached::UnboundCache; use rpds::list; use rpds::list::List; use rpds::vector; -use rpds::vector::Vector; -use std::collections::HashMap; use std::io; use std::io::prelude::*; -use std::iter; use std::process; use structopt::StructOpt; diff --git a/src/bin/day_25.rs b/src/bin/day_25.rs index 5c132cd..522789e 100644 --- a/src/bin/day_25.rs +++ b/src/bin/day_25.rs @@ -13,7 +13,7 @@ struct Opt {} fn main() { let stdin = io::stdin(); - let opt = Opt::from_args(); + let _opt = Opt::from_args(); let program: IntcodeProgram = stdin .lock() -- cgit v1.2.3 From 48a9be141afadaa24182781a2db58594cb2ce522 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Thu, 23 Jan 2020 00:49:39 +0200 Subject: Removed redundant match statements left over from an old implementation The old version used to have error handling for out of range memory access. --- src/lib.rs | 96 +++++++++++++++++++++++--------------------------------------- 1 file changed, 36 insertions(+), 60 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 08082d8..a7dfc02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -198,98 +198,74 @@ impl IntcodeProgram { } fn add(&self, mode: &Intcode) -> IntcodeProgram { - match ( - self.get(1, mode), - self.get(2, mode), + self.with_instruction_pointer_offset(4).with_memory_set( self.get_literal(3, mode), - ) { - (in1, in2, out) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out, in1 + in2), - } + self.get(1, mode) + self.get(2, mode), + ) } fn multiply(&self, mode: &Intcode) -> IntcodeProgram { - match ( - self.get(1, mode), - self.get(2, mode), + self.with_instruction_pointer_offset(4).with_memory_set( self.get_literal(3, mode), - ) { - (in1, in2, out) => self - .with_instruction_pointer_offset(4) - .with_memory_set(out, in1 * in2), - } + self.get(1, mode) * self.get(2, mode), + ) } fn input(&self, mode: &Intcode) -> IntcodeProgram { - match (self.input.first().cloned(), self.get_literal(1, mode)) { - (Some(input), out) => self + match self.input.first().cloned() { + Some(input) => self .with_instruction_pointer_offset(2) - .with_memory_set(out, input) + .with_memory_set(self.get_literal(1, mode), input) .with_input_consumed(), - (None, _out) => self.await_input(), + None => self.await_input(), } } fn output(&self, mode: &Intcode) -> IntcodeProgram { - match self.get(1, mode) { - print => self.with_instruction_pointer_offset(2).with_output(print), - } + self.with_instruction_pointer_offset(2) + .with_output(self.get(1, mode)) } fn jump_if_true(&self, mode: &Intcode) -> IntcodeProgram { - match (self.get(1, mode), self.get(2, mode)) { - (ref pred, ref to) if !pred.is_zero() => self.with_instruction_pointer(to.clone()), - (_, _) => self.with_instruction_pointer_offset(3), + if !self.get(1, mode).is_zero() { + self.with_instruction_pointer(self.get(2, mode)) + } else { + self.with_instruction_pointer_offset(3) } } fn jump_if_false(&self, mode: &Intcode) -> IntcodeProgram { - match (self.get(1, mode), self.get(2, mode)) { - (ref pred, ref to) if pred.is_zero() => self.with_instruction_pointer(to.clone()), - (_, _) => self.with_instruction_pointer_offset(3), + if self.get(1, mode).is_zero() { + self.with_instruction_pointer(self.get(2, mode)) + } else { + self.with_instruction_pointer_offset(3) } } fn less_than(&self, mode: &Intcode) -> IntcodeProgram { - match ( - self.get(1, mode), - self.get(2, mode), + self.with_instruction_pointer_offset(4).with_memory_set( self.get_literal(3, mode), - ) { - (in1, in2, out) => self.with_instruction_pointer_offset(4).with_memory_set( - out, - if in1 < in2 { - Intcode::from(1) - } else { - Intcode::from(0) - }, - ), - } + if self.get(1, mode) < self.get(2, mode) { + Intcode::from(1) + } else { + Intcode::from(0) + }, + ) } fn equals(&self, mode: &Intcode) -> IntcodeProgram { - match ( - self.get(1, mode), - self.get(2, mode), + self.with_instruction_pointer_offset(4).with_memory_set( self.get_literal(3, mode), - ) { - (in1, in2, out) => self.with_instruction_pointer_offset(4).with_memory_set( - out, - if in1 == in2 { - Intcode::from(1) - } else { - Intcode::from(0) - }, - ), - } + if self.get(1, mode) == self.get(2, mode) { + Intcode::from(1) + } else { + Intcode::from(0) + }, + ) } fn set_relative_base(&self, mode: &Intcode) -> IntcodeProgram { - match self.get(1, mode) { - base_change => self - .with_instruction_pointer_offset(2) - .with_relative_base(self.relative_base.clone() + base_change), - } + self.with_instruction_pointer_offset(2) + .with_relative_base(self.relative_base.clone() + self.get(1, mode)) } fn halt(&self) -> IntcodeProgram { -- cgit v1.2.3 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/Cargo.lock | 580 ++++++++++++ 2019/Cargo.toml | 19 + 2019/inputs/day_1.txt | 100 ++ 2019/inputs/day_10.txt | 24 + 2019/inputs/day_11.txt | 1 + 2019/inputs/day_12.txt | 4 + 2019/inputs/day_13.txt | 1 + 2019/inputs/day_14.txt | 59 ++ 2019/inputs/day_15.txt | 1 + 2019/inputs/day_16.txt | 1 + 2019/inputs/day_17.txt | 1 + 2019/inputs/day_18.txt | 81 ++ 2019/inputs/day_18_2.txt | 81 ++ 2019/inputs/day_19.txt | 1 + 2019/inputs/day_2.txt | 1 + 2019/inputs/day_20.txt | 113 +++ 2019/inputs/day_21.txt | 1 + 2019/inputs/day_22.txt | 100 ++ 2019/inputs/day_23.txt | 1 + 2019/inputs/day_24.txt | 5 + 2019/inputs/day_25.txt | 1 + 2019/inputs/day_3.txt | 2 + 2019/inputs/day_4.txt | 2 + 2019/inputs/day_5.txt | 1 + 2019/inputs/day_6.txt | 2306 ++++++++++++++++++++++++++++++++++++++++++++++ 2019/inputs/day_7.txt | 1 + 2019/inputs/day_8.txt | 1 + 2019/inputs/day_9.txt | 1 + 2019/readme.org | 26 + 2019/src/bin/day_1.rs | 93 ++ 2019/src/bin/day_10.rs | 158 ++++ 2019/src/bin/day_11.rs | 205 +++++ 2019/src/bin/day_12.rs | 205 +++++ 2019/src/bin/day_13.rs | 149 +++ 2019/src/bin/day_14.rs | 221 +++++ 2019/src/bin/day_15.rs | 183 ++++ 2019/src/bin/day_16.rs | 112 +++ 2019/src/bin/day_17.rs | 78 ++ 2019/src/bin/day_18.rs | 365 ++++++++ 2019/src/bin/day_19.rs | 102 ++ 2019/src/bin/day_2.rs | 96 ++ 2019/src/bin/day_20.rs | 310 +++++++ 2019/src/bin/day_21.rs | 109 +++ 2019/src/bin/day_22.rs | 325 +++++++ 2019/src/bin/day_23.rs | 211 +++++ 2019/src/bin/day_24.rs | 239 +++++ 2019/src/bin/day_25.dot | 43 + 2019/src/bin/day_25.rs | 110 +++ 2019/src/bin/day_3.rs | 333 +++++++ 2019/src/bin/day_4.rs | 55 ++ 2019/src/bin/day_5.rs | 45 + 2019/src/bin/day_6.rs | 251 +++++ 2019/src/bin/day_7.rs | 175 ++++ 2019/src/bin/day_8.rs | 135 +++ 2019/src/bin/day_9.rs | 1 + 2019/src/lib.rs | 438 +++++++++ 2019/src/main.rs | 12 + Cargo.lock | 580 ------------ Cargo.toml | 19 - inputs/day_1.txt | 100 -- inputs/day_10.txt | 24 - inputs/day_11.txt | 1 - inputs/day_12.txt | 4 - inputs/day_13.txt | 1 - inputs/day_14.txt | 59 -- inputs/day_15.txt | 1 - inputs/day_16.txt | 1 - inputs/day_17.txt | 1 - inputs/day_18.txt | 81 -- inputs/day_18_2.txt | 81 -- inputs/day_19.txt | 1 - inputs/day_2.txt | 1 - inputs/day_20.txt | 113 --- inputs/day_21.txt | 1 - inputs/day_22.txt | 100 -- inputs/day_23.txt | 1 - inputs/day_24.txt | 5 - inputs/day_25.txt | 1 - inputs/day_3.txt | 2 - inputs/day_4.txt | 2 - inputs/day_5.txt | 1 - inputs/day_6.txt | 2306 ---------------------------------------------- inputs/day_7.txt | 1 - inputs/day_8.txt | 1 - inputs/day_9.txt | 1 - readme.org | 26 - src/bin/day_1.rs | 93 -- src/bin/day_10.rs | 158 ---- src/bin/day_11.rs | 205 ----- src/bin/day_12.rs | 205 ----- src/bin/day_13.rs | 149 --- src/bin/day_14.rs | 221 ----- src/bin/day_15.rs | 183 ---- src/bin/day_16.rs | 112 --- src/bin/day_17.rs | 78 -- src/bin/day_18.rs | 365 -------- src/bin/day_19.rs | 102 -- src/bin/day_2.rs | 96 -- src/bin/day_20.rs | 310 ------- src/bin/day_21.rs | 109 --- src/bin/day_22.rs | 325 ------- src/bin/day_23.rs | 211 ----- src/bin/day_24.rs | 239 ----- src/bin/day_25.dot | 43 - src/bin/day_25.rs | 110 --- src/bin/day_3.rs | 333 ------- src/bin/day_4.rs | 55 -- src/bin/day_5.rs | 45 - src/bin/day_6.rs | 251 ----- src/bin/day_7.rs | 175 ---- src/bin/day_8.rs | 135 --- src/bin/day_9.rs | 1 - src/lib.rs | 438 --------- src/main.rs | 12 - 114 files changed, 8275 insertions(+), 8275 deletions(-) create mode 100644 2019/Cargo.lock create mode 100644 2019/Cargo.toml create mode 100644 2019/inputs/day_1.txt create mode 100644 2019/inputs/day_10.txt create mode 100644 2019/inputs/day_11.txt create mode 100644 2019/inputs/day_12.txt create mode 100644 2019/inputs/day_13.txt create mode 100644 2019/inputs/day_14.txt create mode 100644 2019/inputs/day_15.txt create mode 100644 2019/inputs/day_16.txt create mode 100644 2019/inputs/day_17.txt create mode 100644 2019/inputs/day_18.txt create mode 100644 2019/inputs/day_18_2.txt create mode 100644 2019/inputs/day_19.txt create mode 100644 2019/inputs/day_2.txt create mode 100644 2019/inputs/day_20.txt create mode 100644 2019/inputs/day_21.txt create mode 100644 2019/inputs/day_22.txt create mode 100644 2019/inputs/day_23.txt create mode 100644 2019/inputs/day_24.txt create mode 100644 2019/inputs/day_25.txt create mode 100644 2019/inputs/day_3.txt create mode 100644 2019/inputs/day_4.txt create mode 100644 2019/inputs/day_5.txt create mode 100644 2019/inputs/day_6.txt create mode 100644 2019/inputs/day_7.txt create mode 100644 2019/inputs/day_8.txt create mode 100644 2019/inputs/day_9.txt create mode 100644 2019/readme.org create mode 100644 2019/src/bin/day_1.rs create mode 100644 2019/src/bin/day_10.rs create mode 100644 2019/src/bin/day_11.rs create mode 100644 2019/src/bin/day_12.rs create mode 100644 2019/src/bin/day_13.rs create mode 100644 2019/src/bin/day_14.rs create mode 100644 2019/src/bin/day_15.rs create mode 100644 2019/src/bin/day_16.rs create mode 100644 2019/src/bin/day_17.rs create mode 100644 2019/src/bin/day_18.rs create mode 100644 2019/src/bin/day_19.rs create mode 100644 2019/src/bin/day_2.rs create mode 100644 2019/src/bin/day_20.rs create mode 100644 2019/src/bin/day_21.rs create mode 100644 2019/src/bin/day_22.rs create mode 100644 2019/src/bin/day_23.rs create mode 100644 2019/src/bin/day_24.rs create mode 100644 2019/src/bin/day_25.dot create mode 100644 2019/src/bin/day_25.rs create mode 100644 2019/src/bin/day_3.rs create mode 100644 2019/src/bin/day_4.rs create mode 100644 2019/src/bin/day_5.rs create mode 100644 2019/src/bin/day_6.rs create mode 100644 2019/src/bin/day_7.rs create mode 100644 2019/src/bin/day_8.rs create mode 100644 2019/src/bin/day_9.rs create mode 100644 2019/src/lib.rs create mode 100644 2019/src/main.rs delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 inputs/day_1.txt delete mode 100644 inputs/day_10.txt delete mode 100644 inputs/day_11.txt delete mode 100644 inputs/day_12.txt delete mode 100644 inputs/day_13.txt delete mode 100644 inputs/day_14.txt delete mode 100644 inputs/day_15.txt delete mode 100644 inputs/day_16.txt delete mode 100644 inputs/day_17.txt delete mode 100644 inputs/day_18.txt delete mode 100644 inputs/day_18_2.txt delete mode 100644 inputs/day_19.txt delete mode 100644 inputs/day_2.txt delete mode 100644 inputs/day_20.txt delete mode 100644 inputs/day_21.txt delete mode 100644 inputs/day_22.txt delete mode 100644 inputs/day_23.txt delete mode 100644 inputs/day_24.txt delete mode 100644 inputs/day_25.txt delete mode 100644 inputs/day_3.txt delete mode 100644 inputs/day_4.txt delete mode 100644 inputs/day_5.txt delete mode 100644 inputs/day_6.txt delete mode 100644 inputs/day_7.txt delete mode 100644 inputs/day_8.txt delete mode 100644 inputs/day_9.txt delete mode 100644 readme.org delete mode 100644 src/bin/day_1.rs delete mode 100644 src/bin/day_10.rs delete mode 100644 src/bin/day_11.rs delete mode 100644 src/bin/day_12.rs delete mode 100644 src/bin/day_13.rs delete mode 100644 src/bin/day_14.rs delete mode 100644 src/bin/day_15.rs delete mode 100644 src/bin/day_16.rs delete mode 100644 src/bin/day_17.rs delete mode 100644 src/bin/day_18.rs delete mode 100644 src/bin/day_19.rs delete mode 100644 src/bin/day_2.rs delete mode 100644 src/bin/day_20.rs delete mode 100644 src/bin/day_21.rs delete mode 100644 src/bin/day_22.rs delete mode 100644 src/bin/day_23.rs delete mode 100644 src/bin/day_24.rs delete mode 100644 src/bin/day_25.dot delete mode 100644 src/bin/day_25.rs delete mode 100644 src/bin/day_3.rs delete mode 100644 src/bin/day_4.rs delete mode 100644 src/bin/day_5.rs delete mode 100644 src/bin/day_6.rs delete mode 100644 src/bin/day_7.rs delete mode 100644 src/bin/day_8.rs delete mode 100644 src/bin/day_9.rs delete mode 100644 src/lib.rs delete mode 100644 src/main.rs diff --git a/2019/Cargo.lock b/2019/Cargo.lock new file mode 100644 index 0000000..52c69da --- /dev/null +++ b/2019/Cargo.lock @@ -0,0 +1,580 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aoc2019" +version = "0.1.0" +dependencies = [ + "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cached 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derivative 1.0.3 (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)", + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "archery" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitmaps" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cached" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "derivative" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "derive_more" +version = "0.99.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hermit-abi" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "im" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.66" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memoffset" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-complex" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "once_cell" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro-error" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_xoshiro" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rpds" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sized-chunks" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "static_assertions" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d308d8fa3f687f7a7588fccc4812ed6914be09518232f00454693a7417273ad2" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" +"checksum cached 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b052fd10f32987c3bd028d91ef86190b36fba5c8fccb5515d42083f061e6104" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" +"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" +"checksum derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "942ca430eef7a3806595a6737bc388bf51adb888d3fc0dd1b50f1c170167ee3a" +"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" +"checksum im 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1f9b6540e530defef7f2df4ed330d45b739b10450548c74a9913f63ea1acc6b" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" +"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" +"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" +"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" +"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" +"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +"checksum rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1196a0a2f52d343bd32179834273eaac7d8739f7e3f8b700227d2fa06b9a423b" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62db64dd92b3b54314b1e216c274634ca2b3fe8da8b3873be670cb1ac4dad30f" +"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" +"checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/2019/Cargo.toml b/2019/Cargo.toml new file mode 100644 index 0000000..c5937b0 --- /dev/null +++ b/2019/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "aoc2019" +version = "0.1.0" +authors = ["Justin Wernick "] +edition = "2018" + +[dependencies] +structopt = "0.3.5" +derive_more = "0.99.2" +derivative = "1.0.3" +im = "14.0.0" +rpds = "0.7.0" +archery = "0.3.0" +num = "0.2" +rayon = "1.3.0" +cached = "0.11.0" + +[profile.release] +debug = true diff --git a/2019/inputs/day_1.txt b/2019/inputs/day_1.txt new file mode 100644 index 0000000..5c720ed --- /dev/null +++ b/2019/inputs/day_1.txt @@ -0,0 +1,100 @@ +66690 +86239 +75191 +140364 +95979 +106923 +95229 +123571 +84764 +89444 +98107 +89062 +109369 +146067 +124760 +76900 +139198 +111441 +74046 +84920 +54397 +143807 +121654 +93863 +73909 +104121 +58485 +119084 +126227 +142078 +79820 +132617 +108430 +98032 +107434 +127307 +105619 +57741 +53468 +63301 +137970 +136780 +80897 +133205 +79159 +89124 +94477 +56714 +143704 +122097 +117335 +108246 +75507 +101459 +101162 +146197 +121884 +66217 +57074 +142903 +140951 +64883 +124556 +67382 +142407 +121778 +57933 +94599 +87426 +143758 +64043 +65678 +90137 +61090 +77315 +102383 +146607 +139290 +85394 +149787 +125611 +106405 +91561 +135739 +54845 +68782 +111175 +61011 +125658 +70751 +85607 +75458 +75419 +124311 +66022 +122784 +129018 +54901 +73788 +108240 diff --git a/2019/inputs/day_10.txt b/2019/inputs/day_10.txt new file mode 100644 index 0000000..51520ab --- /dev/null +++ b/2019/inputs/day_10.txt @@ -0,0 +1,24 @@ +.###.#...#.#.##.#.####.. +.#....#####...#.######.. +#.#.###.###.#.....#.#### +##.###..##..####.#.####. +###########.#######.##.# +##########.#########.##. +.#.##.########.##...###. +###.#.##.#####.#.###.### +##.#####.##..###.#.##.#. +.#.#.#####.####.#..##### +.###.#####.#..#..##.#.## +########.##.#...######## +.####..##..#.###.###.#.# +....######.##.#.######.# +###.####.######.#....### +############.#.#.##.#### +##...##..####.####.#..## +.###.#########.###..#.## +#.##.#.#...##...#####..# +##.#..###############.## +##.###.#####.##.######.. +##.#####.#.#.##..####### +...#######.######...#### +#....#.#.#.####.#.#.#.## diff --git a/2019/inputs/day_11.txt b/2019/inputs/day_11.txt new file mode 100644 index 0000000..d6581e1 --- /dev/null +++ b/2019/inputs/day_11.txt @@ -0,0 +1 @@ +3,8,1005,8,320,1106,0,11,0,0,0,104,1,104,0,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,29,2,1005,1,10,1006,0,11,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,57,1,8,15,10,1006,0,79,1,6,3,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,90,2,103,18,10,1006,0,3,2,105,14,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,123,2,9,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,1001,8,0,150,1,2,2,10,2,1009,6,10,1,1006,12,10,1006,0,81,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,187,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,209,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,231,1,1008,11,10,1,1001,4,10,2,1104,18,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,264,1,8,14,10,1006,0,36,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,293,1006,0,80,1006,0,68,101,1,9,9,1007,9,960,10,1005,10,15,99,109,642,104,0,104,1,21102,1,846914232732,1,21102,1,337,0,1105,1,441,21102,1,387512115980,1,21101,348,0,0,1106,0,441,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21102,209533824219,1,1,21102,1,395,0,1106,0,441,21101,0,21477985303,1,21102,406,1,0,1106,0,441,3,10,104,0,104,0,3,10,104,0,104,0,21101,868494234468,0,1,21101,429,0,0,1106,0,441,21102,838429471080,1,1,21102,1,440,0,1106,0,441,99,109,2,21201,-1,0,1,21101,0,40,2,21102,472,1,3,21101,0,462,0,1106,0,505,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,467,468,483,4,0,1001,467,1,467,108,4,467,10,1006,10,499,1102,1,0,467,109,-2,2106,0,0,0,109,4,2101,0,-1,504,1207,-3,0,10,1006,10,522,21101,0,0,-3,21202,-3,1,1,22101,0,-2,2,21102,1,1,3,21102,541,1,0,1106,0,546,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,569,2207,-4,-2,10,1006,10,569,22102,1,-4,-4,1105,1,637,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21102,588,1,0,1105,1,546,22101,0,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,607,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,629,21201,-1,0,1,21102,629,1,0,105,1,504,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0 diff --git a/2019/inputs/day_12.txt b/2019/inputs/day_12.txt new file mode 100644 index 0000000..7e72a58 --- /dev/null +++ b/2019/inputs/day_12.txt @@ -0,0 +1,4 @@ + + + + diff --git a/2019/inputs/day_13.txt b/2019/inputs/day_13.txt new file mode 100644 index 0000000..c600ec1 --- /dev/null +++ b/2019/inputs/day_13.txt @@ -0,0 +1 @@ +1,380,379,385,1008,2689,888873,381,1005,381,12,99,109,2690,1102,0,1,383,1101,0,0,382,21001,382,0,1,20102,1,383,2,21101,0,37,0,1105,1,578,4,382,4,383,204,1,1001,382,1,382,1007,382,41,381,1005,381,22,1001,383,1,383,1007,383,25,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1101,-1,0,384,1106,0,119,1007,392,39,381,1006,381,161,1102,1,1,384,20101,0,392,1,21101,23,0,2,21102,0,1,3,21102,138,1,0,1105,1,549,1,392,384,392,21001,392,0,1,21101,23,0,2,21101,3,0,3,21102,1,161,0,1105,1,549,1101,0,0,384,20001,388,390,1,20101,0,389,2,21101,0,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,20101,0,389,2,21101,205,0,0,1105,1,393,1002,390,-1,390,1102,1,1,384,21001,388,0,1,20001,389,391,2,21101,228,0,0,1105,1,578,1206,1,261,1208,1,2,381,1006,381,253,20101,0,388,1,20001,389,391,2,21101,253,0,0,1106,0,393,1002,391,-1,391,1101,0,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21101,279,0,0,1106,0,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,0,304,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1101,0,1,384,1005,384,161,20102,1,388,1,20101,0,389,2,21101,0,0,3,21101,0,338,0,1106,0,549,1,388,390,388,1,389,391,389,21001,388,0,1,21002,389,1,2,21102,4,1,3,21101,0,365,0,1105,1,549,1007,389,24,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,230,18,20,1,1,20,109,3,21201,-2,0,1,22101,0,-1,2,21101,0,0,3,21102,1,414,0,1106,0,549,22102,1,-2,1,22102,1,-1,2,21101,0,429,0,1105,1,601,2102,1,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,22102,1,-3,-7,109,-8,2106,0,0,109,4,1202,-2,41,566,201,-3,566,566,101,639,566,566,2101,0,-1,0,204,-3,204,-2,204,-1,109,-4,2105,1,0,109,3,1202,-1,41,594,201,-2,594,594,101,639,594,594,20102,1,0,-2,109,-3,2106,0,0,109,3,22102,25,-2,1,22201,1,-1,1,21101,0,521,2,21102,1,1011,3,21102,1,1025,4,21102,630,1,0,1106,0,456,21201,1,1664,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,2,2,0,2,0,2,0,2,0,0,2,2,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,2,0,1,1,0,0,0,0,2,0,0,2,0,2,2,2,2,0,2,0,0,0,2,2,0,0,2,2,2,2,0,0,0,0,0,2,0,0,0,0,2,2,0,1,1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,2,2,0,2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2,2,2,0,0,1,1,0,0,2,2,2,0,0,0,2,0,0,0,0,0,2,2,0,0,2,0,2,0,0,0,2,2,0,0,0,2,0,0,0,2,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,2,0,0,2,0,0,0,0,2,0,0,2,0,2,0,2,0,2,0,0,1,1,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0,0,2,2,0,0,0,2,2,0,0,2,0,0,0,2,2,2,2,2,0,2,0,1,1,0,0,0,0,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,2,2,2,0,0,0,0,0,2,0,0,2,0,0,1,1,0,2,0,0,2,0,0,0,0,2,0,0,0,0,2,2,0,2,0,0,0,0,2,0,0,0,0,0,2,0,2,0,0,2,0,0,2,0,0,1,1,0,2,2,2,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,2,0,0,2,0,2,0,2,2,0,2,2,0,2,0,2,0,0,1,1,0,0,2,0,0,2,0,2,0,0,2,0,0,2,0,0,0,2,0,0,0,0,2,0,0,2,0,0,2,2,0,2,0,0,0,0,2,2,0,1,1,0,0,2,2,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,2,2,2,0,0,2,0,2,0,2,2,0,0,2,0,2,0,0,1,1,0,0,2,2,2,0,0,2,2,0,2,2,2,0,0,0,2,2,2,0,2,0,0,0,0,0,2,0,0,2,0,2,0,0,0,0,0,0,0,1,1,0,2,0,0,0,2,2,0,2,0,0,2,0,2,2,2,0,0,2,2,0,2,0,0,0,0,0,0,2,2,0,2,2,0,2,0,0,2,0,1,1,0,0,2,0,0,2,2,0,0,0,0,0,2,2,0,2,2,2,0,2,0,2,2,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,1,1,0,2,0,2,0,2,2,2,2,0,0,0,2,0,0,0,2,2,0,0,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,2,0,0,0,1,1,0,0,0,0,2,0,0,2,0,0,2,2,0,2,0,0,0,2,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,0,2,0,1,1,0,2,0,0,0,2,0,0,0,2,2,0,2,0,0,2,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,0,0,2,0,0,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,34,58,37,19,14,62,51,10,28,52,86,20,39,30,61,36,77,73,19,11,17,74,7,54,40,59,20,92,18,13,85,72,83,58,18,68,10,22,94,22,25,40,67,96,55,96,42,16,80,80,96,35,19,79,81,63,91,5,72,68,80,93,79,36,91,47,71,82,45,29,51,36,10,62,57,29,17,16,4,88,75,81,70,77,32,2,38,37,35,86,41,35,61,71,72,22,14,33,12,10,10,56,30,3,90,71,24,62,69,31,47,2,18,77,43,20,64,85,50,43,43,73,16,23,98,4,23,53,82,15,88,1,39,78,43,57,65,8,45,79,17,44,32,76,31,3,25,71,45,16,42,61,89,21,93,4,98,66,68,5,13,19,48,65,29,5,24,59,29,49,57,39,21,96,10,8,25,82,17,42,46,49,83,4,81,32,14,7,76,62,31,74,55,19,39,63,89,41,38,28,34,34,88,7,77,43,87,10,47,85,39,31,88,69,40,72,51,49,64,46,64,14,66,95,95,58,38,88,82,35,6,58,3,21,33,58,9,95,43,52,13,22,22,10,11,47,35,33,31,58,93,83,13,14,55,71,88,42,73,83,91,84,62,78,80,15,26,50,8,15,6,91,89,3,12,53,47,47,82,67,12,77,6,63,88,94,53,19,97,36,34,59,91,27,37,45,44,31,8,58,16,7,74,76,83,17,28,42,85,19,1,61,73,84,37,15,43,52,80,48,51,98,70,77,28,55,78,85,64,32,22,82,69,7,82,55,78,24,5,89,55,4,34,28,71,76,81,90,96,2,2,77,41,32,24,60,10,11,26,64,66,19,11,77,11,82,81,1,52,2,79,43,47,87,63,73,3,81,69,66,53,4,83,88,13,5,62,94,55,58,4,93,96,58,40,69,64,56,80,71,85,44,45,24,80,59,53,15,85,92,89,95,69,77,53,27,72,3,54,49,9,35,10,85,43,86,9,42,69,29,64,96,17,72,47,24,2,13,40,45,62,19,41,85,28,68,73,20,52,56,19,57,1,36,64,18,26,41,94,81,45,35,29,32,28,87,86,53,71,54,67,68,47,53,17,40,61,58,74,2,51,43,23,62,54,13,80,67,88,94,1,62,85,7,12,87,51,4,69,25,57,6,79,94,15,75,93,46,19,28,84,72,84,59,60,59,59,14,11,30,57,53,75,83,72,61,65,50,26,49,23,40,82,11,67,8,55,13,22,41,32,33,89,37,69,11,24,24,8,21,89,11,46,89,88,59,3,7,43,85,74,92,72,60,85,82,33,82,71,14,21,41,4,78,88,4,22,81,30,92,17,9,62,69,84,47,6,86,49,94,11,96,21,1,5,1,45,19,60,59,17,85,67,42,21,11,79,39,27,72,54,19,69,50,52,78,78,6,16,96,86,37,58,79,9,45,10,73,29,53,75,63,50,66,6,69,8,74,68,88,9,88,87,50,34,45,12,43,43,58,14,29,32,77,77,97,45,29,41,94,21,91,52,22,74,44,48,11,20,68,9,51,7,85,93,74,59,16,34,60,12,3,18,17,4,71,44,49,79,68,54,96,74,21,74,60,59,16,77,65,97,84,54,52,37,95,9,3,41,9,72,82,82,95,31,71,56,50,59,93,57,79,16,9,74,72,47,1,9,5,55,63,64,80,40,93,54,11,57,26,76,19,85,41,80,90,92,27,61,24,83,93,96,95,28,68,80,11,60,65,36,2,46,75,59,52,11,36,74,62,52,6,23,85,93,61,36,26,70,2,13,97,52,92,96,87,63,63,31,2,50,25,34,79,46,4,48,51,74,96,74,7,43,82,84,50,59,53,13,51,8,81,36,93,10,31,10,50,76,69,33,3,71,1,1,65,68,57,69,15,64,81,59,38,38,89,79,80,52,44,59,26,96,21,38,38,79,2,96,2,92,73,49,14,71,74,66,94,98,63,28,59,26,30,67,1,61,84,92,47,24,27,41,57,95,89,6,96,48,43,7,82,42,5,27,15,32,89,53,3,35,63,84,97,92,77,50,38,73,10,50,89,95,96,77,61,51,90,22,75,41,77,1,14,72,68,91,10,80,28,25,10,86,54,10,87,55,40,79,16,35,8,82,51,70,84,12,72,74,4,88,71,69,83,9,55,10,57,9,3,40,74,72,61,75,64,54,32,61,26,53,48,45,22,6,83,21,21,9,4,7,65,98,78,17,54,35,95,79,36,53,59,84,53,14,20,94,12,31,54,86,39,95,82,38,8,22,58,50,27,32,53,79,49,71,76,18,64,75,64,88,58,88,27,62,31,54,11,59,11,3,42,66,85,41,888873 diff --git a/2019/inputs/day_14.txt b/2019/inputs/day_14.txt new file mode 100644 index 0000000..dac9757 --- /dev/null +++ b/2019/inputs/day_14.txt @@ -0,0 +1,59 @@ +2 RWPCH => 9 PVTL +1 FHFH => 4 BLPJK +146 ORE => 5 VJNBT +8 KDFNZ, 1 ZJGH, 1 GSCG => 5 LKPQG +11 NWDZ, 2 WBQR, 1 VRQR => 2 BMJR +3 GSCG => 4 KQDVM +5 QVNKN, 6 RPWKC => 3 BCNV +10 QMBM, 4 RBXB, 2 VRQR => 1 JHXBM +15 RPWKC => 6 MGCQ +1 QWKRZ => 4 FHFH +10 RWPCH => 6 MZKG +11 JFKGV, 5 QVNKN, 1 CTVK => 4 VQDT +1 SXKT => 5 RPWKC +1 VQDT, 25 ZVMCB => 2 RBXB +6 LGLNV, 4 XSNKB => 3 WBQR +199 ORE => 2 SXKT +1 XSNKB, 6 CWBNX, 1 HPKB, 5 PVTL, 1 JNKH, 9 SXKT, 3 KQDVM => 3 ZKTX +7 FDSX => 6 WJDF +7 JLRM => 4 CWBNX +167 ORE => 5 PQZXH +13 JHXBM, 2 NWDZ, 4 RFLX, 12 VRQR, 10 FJRFG, 14 PVTL, 2 JLRM => 6 DGFG +12 HPKB, 3 WHVXC => 9 ZJGH +1 JLRM, 2 ZJGH, 2 QVNKN => 9 FJRFG +129 ORE => 7 KZFPJ +2 QMBM => 1 RWPCH +7 VJMWM => 4 JHDW +7 PQZXH, 7 SXKT => 9 BJVQM +1 VJMWM, 4 JHDW, 1 MQXF => 7 FDSX +1 RPWKC => 7 WHVXC +1 ZJGH => 1 ZVMCB +1 RWPCH => 3 MPKR +187 ORE => 8 VJMWM +15 CTVK => 5 GSCG +2 XSNKB, 15 ZVMCB, 3 KDFNZ => 2 RFLX +18 QVNKN => 8 XLFZJ +4 CWBNX => 8 ZSCX +2 ZJGH, 1 JLRM, 1 MGCQ => 9 NPRST +13 BJVQM, 2 BCNV => 2 QWKRZ +2 QWKRZ, 2 BLPJK, 5 XSNKB => 2 VRQR +13 HPKB, 3 VQDT => 9 JLRM +2 SXKT, 1 VJNBT, 5 VLWQB => 6 CTVK +2 MPKR, 2 LMNCH, 24 VRQR => 8 DZFNW +2 VQDT => 1 KDFNZ +1 CTVK, 6 FDSX => 6 QVNKN +3 CTVK, 1 QVNKN => 4 HPKB +3 NPRST, 1 KGSDJ, 1 CTVK => 2 QMBM +4 KZFPJ, 1 PQZXH => 5 VLWQB +2 VQDT => 7 KGSDJ +3 MPKR => 2 JNKH +1 KQDVM => 5 XQBS +3 ZKGMX, 1 XQBS, 11 MZKG, 11 NPRST, 1 DZFNW, 5 VQDT, 2 FHFH => 6 JQNF +2 FJRFG, 17 BMJR, 3 BJVQM, 55 JQNF, 8 DGFG, 13 ZJGH, 29 ZKTX => 1 FUEL +27 KZFPJ, 5 VJNBT => 5 MQXF +11 FDSX, 1 WHVXC, 1 WJDF => 4 ZKGMX +1 ZVMCB => 4 NWDZ +1 XLFZJ => 6 LGLNV +13 ZSCX, 4 XLFZJ => 8 LMNCH +1 RPWKC, 1 FDSX, 2 BJVQM => 8 JFKGV +1 WJDF, 1 LKPQG => 4 XSNKB diff --git a/2019/inputs/day_15.txt b/2019/inputs/day_15.txt new file mode 100644 index 0000000..ca5836c --- /dev/null +++ b/2019/inputs/day_15.txt @@ -0,0 +1 @@ +3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1002,1034,1,1039,102,1,1036,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,1001,1035,0,1040,1002,1038,1,1043,101,0,1037,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,102,1,1035,1040,1001,1038,0,1043,101,0,1037,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,1,1032,1006,1032,165,1008,1040,9,1032,1006,1032,165,1102,1,2,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1102,1,1,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,35,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,102,1,1039,1034,1002,1040,1,1035,1002,1041,1,1036,102,1,1043,1038,101,0,1042,1037,4,1044,1105,1,0,1,5,41,19,22,1,39,81,29,20,15,82,33,18,45,30,32,55,28,26,70,13,56,32,28,18,3,59,90,11,95,15,85,8,61,25,59,24,34,1,85,5,25,54,57,18,20,54,80,91,28,65,36,12,44,36,13,92,24,56,13,39,69,29,79,10,41,27,23,25,72,20,3,61,15,51,11,12,12,48,10,45,13,29,49,90,30,17,9,41,21,18,7,30,48,17,83,71,4,10,31,10,96,81,77,9,50,39,21,36,33,72,12,3,23,79,18,4,75,17,58,64,8,7,97,60,72,72,1,94,55,42,2,94,2,21,88,19,82,57,96,19,25,27,41,62,15,40,23,61,86,27,73,61,13,46,52,81,12,34,23,73,23,59,1,30,47,9,99,10,37,17,28,98,5,92,73,8,63,4,86,76,79,7,30,68,28,91,12,12,98,74,4,22,44,10,23,45,37,16,90,76,23,74,75,12,21,38,14,15,76,28,49,71,7,6,6,71,53,33,12,87,15,92,66,21,38,13,53,92,34,49,25,6,67,21,27,89,24,61,25,30,41,30,99,28,19,41,90,51,74,14,33,54,48,10,14,42,2,67,76,10,21,2,67,43,27,69,11,16,78,7,36,9,24,48,63,81,53,29,94,34,25,99,66,47,17,97,33,52,11,62,22,52,30,23,89,95,15,13,50,48,26,10,6,69,78,13,6,94,1,28,67,10,70,16,50,19,24,15,79,50,27,3,19,62,4,31,83,20,17,83,67,5,80,26,36,62,87,3,10,80,22,65,60,10,78,4,20,60,30,11,7,83,10,13,72,81,37,22,14,55,63,51,27,32,77,52,20,50,16,48,2,55,10,53,26,84,6,87,43,37,26,3,85,62,25,78,50,16,10,37,22,54,5,80,24,7,32,49,18,27,12,41,70,82,20,34,91,15,98,77,22,6,79,3,8,54,17,32,4,44,2,97,14,15,65,30,97,14,79,75,11,77,5,61,37,20,91,20,45,74,19,40,2,41,89,12,34,44,18,62,57,17,68,22,96,7,59,63,2,60,70,2,26,75,26,3,53,19,80,16,97,7,34,58,52,66,24,75,25,30,75,42,13,12,89,13,3,84,92,1,75,30,54,43,2,56,15,1,15,84,99,6,98,42,17,29,1,18,26,70,71,29,91,23,21,87,66,18,38,32,18,81,65,2,58,99,12,4,84,24,32,88,30,67,49,29,59,64,18,70,10,24,56,5,27,97,50,4,28,85,65,16,67,83,15,16,61,18,86,8,36,25,36,29,97,45,19,81,41,29,45,30,69,26,57,93,27,72,34,30,99,61,2,48,16,12,76,98,28,14,32,32,90,48,10,30,57,23,39,2,8,39,33,13,88,34,31,74,15,60,8,47,60,31,5,79,1,98,86,33,3,99,33,62,11,96,25,22,38,98,84,3,56,70,49,3,8,56,87,4,29,59,65,26,34,77,7,14,78,26,25,70,49,3,31,45,92,24,95,17,4,9,4,96,64,92,27,67,4,99,6,44,7,16,86,2,75,1,6,68,81,4,1,44,49,7,92,8,40,36,25,81,13,56,99,10,2,30,72,6,43,30,12,43,93,19,20,23,95,10,19,66,63,28,96,40,50,8,15,56,38,13,93,42,71,12,18,87,8,4,21,85,9,2,66,77,10,80,26,61,9,43,20,88,10,39,67,55,31,49,17,58,26,80,20,84,54,49,5,73,11,52,15,63,7,62,24,57,92,61,25,87,56,37,31,38,14,99,0,0,21,21,1,10,1,0,0,0,0,0,0 diff --git a/2019/inputs/day_16.txt b/2019/inputs/day_16.txt new file mode 100644 index 0000000..357965c --- /dev/null +++ b/2019/inputs/day_16.txt @@ -0,0 +1 @@ +59723517898690342336085619027921111260000667417052529433894092649779685557557996383085708903241535436786723718804155370155263736632861535632645335233170435646844328735934063129720822438983948765830873108060969395372667944081201020154126736565212455403582565814037568332106043336657972906297306993727714730061029321153984390658949013821918352341503629705587666779681013358053312990709423156110291835794179056432958537796855287734217125615700199928915524410743382078079059706420865085147514027374485354815106354367548002650415494525590292210440827027951624280115914909910917047084328588833201558964370296841789611989343040407348115608623432403085634084 diff --git a/2019/inputs/day_17.txt b/2019/inputs/day_17.txt new file mode 100644 index 0000000..49131d4 --- /dev/null +++ b/2019/inputs/day_17.txt @@ -0,0 +1 @@ +1,330,331,332,109,3974,1102,1182,1,15,1101,1475,0,24,1001,0,0,570,1006,570,36,101,0,571,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,15,1,15,1008,15,1475,570,1006,570,14,21102,1,58,0,1105,1,786,1006,332,62,99,21101,333,0,1,21102,73,1,0,1105,1,579,1102,0,1,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,1002,574,1,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21102,340,1,1,1105,1,177,21101,0,477,1,1106,0,177,21102,1,514,1,21101,0,176,0,1106,0,579,99,21102,184,1,0,1105,1,579,4,574,104,10,99,1007,573,22,570,1006,570,165,1002,572,1,1182,21101,0,375,1,21101,0,211,0,1105,1,579,21101,1182,11,1,21102,1,222,0,1106,0,979,21102,1,388,1,21102,1,233,0,1106,0,579,21101,1182,22,1,21101,0,244,0,1105,1,979,21101,0,401,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21102,1,266,0,1106,0,979,21102,414,1,1,21102,277,1,0,1105,1,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21102,1182,1,1,21102,1,313,0,1106,0,622,1005,575,327,1101,1,0,575,21101,327,0,0,1105,1,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,50,26,0,109,4,1201,-3,0,587,20102,1,0,-1,22101,1,-3,-3,21102,0,1,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1106,0,597,109,-4,2106,0,0,109,5,2101,0,-4,630,20101,0,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,653,20101,0,0,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21102,702,1,0,1106,0,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21102,731,1,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21101,756,0,0,1105,1,786,1106,0,774,21202,-1,-11,1,22101,1182,1,1,21102,774,1,0,1105,1,622,21201,-3,1,-3,1106,0,640,109,-5,2105,1,0,109,7,1005,575,802,20102,1,576,-6,20101,0,577,-5,1105,1,814,21101,0,0,-1,21101,0,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,51,-3,22201,-6,-3,-3,22101,1475,-3,-3,2102,1,-3,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1105,1,924,1205,-2,873,21102,1,35,-4,1106,0,924,1202,-3,1,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1101,0,2,0,2101,0,-3,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21002,0,1,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,51,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,49,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1102,1,1,575,21101,973,0,0,1105,1,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,0,1,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1105,1,1041,21102,1,-4,-2,1106,0,1041,21101,0,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,2102,1,-2,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,2102,1,-2,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1106,0,989,21101,0,439,1,1105,1,1150,21101,477,0,1,1106,0,1150,21102,1,514,1,21102,1,1149,0,1105,1,579,99,21101,1157,0,0,1106,0,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,2101,0,-5,1176,2102,1,-4,0,109,-6,2106,0,0,32,5,46,1,3,1,46,1,3,1,46,1,3,1,46,1,3,1,46,1,3,1,40,11,40,1,5,1,44,1,5,1,44,1,5,1,44,1,5,1,44,1,5,1,40,11,40,1,3,1,46,1,3,1,46,1,3,1,46,1,3,9,38,1,11,1,26,1,11,1,11,1,26,1,11,1,11,1,26,1,11,5,7,1,26,1,15,1,7,1,26,1,15,1,7,1,26,1,15,1,7,1,26,1,11,7,5,1,26,1,11,1,3,1,1,1,5,1,26,1,9,13,1,1,3,13,10,1,9,1,1,1,3,1,1,1,3,1,1,1,3,1,22,5,5,1,1,13,3,1,26,1,5,1,5,1,1,1,3,1,5,1,26,1,5,1,5,7,5,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,11,26,1,5,1,34,11,5,1,34,1,15,1,34,1,5,9,1,9,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,22,11,7,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,5,13,11,22 diff --git a/2019/inputs/day_18.txt b/2019/inputs/day_18.txt new file mode 100644 index 0000000..3cb4307 --- /dev/null +++ b/2019/inputs/day_18.txt @@ -0,0 +1,81 @@ +################################################################################# +#.............#.....#.................#.#.....#...#.......#...................#a# +#.#####.#######.#.###.#########.#####.#.#.###Y###.#.#####.#.#####.###########.#.# +#.#...#.#.....#.#..c#.........#...#.#...#...#.#...#.#.#...#.#.#...#...#...#.....# +#.#.###.#.###.#.###.#.###########.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.####### +#.#...#...#.#...#.#...#...........#.#...#.#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.....# +#.#.#.#####.#####.#####.###.#######.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.###.# +#.#.#.............#.#...#.#.#..e..#.....#.#...........#...#.#...#...#...#.....#.# +#.#########.#####.#.#.###.#.#.###.#####.#.###############.#T#.#.###############.# +#...#..k....#.....#.#.Z.#...#...#.....#.#.........#.#.....#.#.#.....#.L.....#...# +###.#.#.#######.###.###.#######.#####.#.#########.#.#.###.#.#.###.#.###.###.#.### +#...#.#.#.....#.#...#...#.....#.....#.#.#...#...#.#.#.#...#.#.#...#...#.#...#...# +#.###.#.#.###.#.#.###.###.###.#####.#.#.#.#.#.#.#.#.#.###.#.###.#####.#.#.#####.# +#.#...#.#.#...#.#...#.....#.#.....#.#.#.#.#...#...#.#...#.#.#...#.#...#.#.#.....# +#.###.#.#.#.###.###.#######.#.#####.#.#.#.#########.###.###.#.###.#.###.#.#.###.# +#...#.#.#.#...#...#.........#.#.....#.#.#.............#.......#...#.#...#.#...#.# +###.#.###.###.###.###.#.#####.#.#####.###############.#########.#.#.###.#.###.#.# +#.....#...#...#.J...#.#.#.....#.....#...#...........#.#...#...#.#.......#...#.#.# +#######.###.#######.#.###.#####.#######.#########.#.#.###.#.#.#########.#####.#.# +#.......#.#...#...#...#...#...#.#.......#.....O.#.#.#.#...#.#.......#...#.....#s# +#.#######.###.#.#.#####.###.#.#.#.#######.#####.#.#.#.#.###.#####.#.#.###.#####.# +#...#...#...#...#...#.#.#...#...#.......#.....#.#.#.#.#...#.#...#.#.#...#...#...# +###.#.#.#.#########.#.#.#.#######.#####.#.#####.#.###.###.#.###.###.#.#####.#.### +#.#...#.#.........#...#...#....d#.....#.#.#.....#.#...#...#.#.#...#.#.#.....#.#.# +#.#####.#######.#######.###.###.#####.#.#.#.#####.#.###.#.#.#.###.#.#.#.#####.#.# +#...#.#.......#.......#...#.#...#.....#.#.#.....#.......#.#.....#.#.#.#.#.......# +#.#.#.#######.#.#.#####.###.#.#####.###.#.#####.#############.###.#.#.#.#######.# +#.#...#.....#.#.#...#...#...#.....#...#.#.#...#.#...........#.#...#.#.#.#...#.#.# +#.###.###.#.#.#.###.#.###.#######.#####.#.###.#.#.#########.#.#.###.#.#.#.#.#.#.# +#...#.....#.#.#...#...#...#.......#.....#...#.#.#.....#...#...#...#.#.#...#.#...# +#.#.#######.#.###.#####.###.#######.#######.#.#.#####.###.#######.#.#####.#.#.### +#.#.#.....#.#.#.#.#.#...#.#.#...#...#...#...#.#.....#...#.....#...#.....#.#.#w#.# +#.#.#.###.#.#.#.#.#.#.###.#.#.#.###.#.#.#.###.#.###.###.#.###.#.###.###.###.#.#.# +#.#.#.#.#.#.#.#.#.#.#.#m..#...#...#...#.#.#...#...#...#.#...#.#.#.....#.#...#.#.# +###.#.#.#.###W#.#.#.#.#.#########.#####.#.#.#.###.#####.###.#.#.#######.#.###.#.# +#...#...#.#...#.....#.#.......#...#...#.#.#.#.#.#.....#.....#.#.........#.#.#...# +#.###.###.#.###.#####.#.###.###.###.#.#.#.#.#.#.#####.#######.###########.#.###.# +#.#...#...#.#...#.S...#...#.....#...#.#.#...#.....#.#.........#...#...#...#.....# +#.#.###.###.#####.#######.#######.###.#.#########.#.###########.#.#.#.#.###.##### +#.....#...........#.......F.......#..................f..........#...#...#.......# +#######################################.@.####################################### +#.....#.#...........#.....#.........................#...#.....#.M.......#.....#.# +###P#.#.#.#######.###.###.#.#######.###.#.#########.#.#.#.###.###.#####.###.#.#.# +#...#...#...#.#...#.....#.#.#.......#...#...#.........#...#.......#...#.....#.#.# +#.#.#######.#.#.###.#####.#.#.#######.#####.###############.#########.#######.#.# +#.#.#.....#.#.#.#...#...#.#.#.#.........#...#.......#...#.....#.....#.#.......#.# +#.###.###.#.#.#.#.###.#.#.#.#.###########.###.#####.#.#.#######.###.#.#.#######.# +#...#.#.#.#...#.#.#...#...#.#...........#...#...#.#...#.......#.#.#.#.#.........# +#.#.#.#.#.#.###.#.#.#####.#######.#####.###.###.#.###########.#.#.#.#.#.#######.# +#.#.#...#...#...#.#r#.....#.....#.....#.#...#.#.#.......#...#.....#.#...#.....#.# +#.#.###.#####.###.#.#######.###.#####.#.#.#.#.#.###.#####.#.#######.#.###.###.#.# +#.#...#.#...#...#.#.........#...#...#.#.#.#...#...#.#.....#.#......p#...#.#.#.#.# +###.#.#.#.#.###.#.###########.###.#.#.#.#.###.###.#.#.#####.#.###.#######.#.#.### +#...#.#.#.#...#.......#.....#.#...#...#.#...#.#...#.....#...#.#...#.K...#.#.#...# +#.#####.#.###.#######.#.###Q#.#.#######.###.#.#.#####.###.###.#.###.###.#.#.###.# +#.....#...#...#.#...#.#.#.#...#...#.....#...#.#.....#.#...#...#.#...#.#..j#.#...# +#.###.#####.###.#.#.###.#.#########.###.#.#########.###.#.#.###.#.###.#####.#.### +#...#.#.....#...#.#.B...#...#...#...#...#.#.......#.....#.#...#.#...........#.R.# +#.###.#.#######.#.#######.#.#.#.#.###.###.#.#.###.#######.###.###.#############.# +#.#...#.......#.#n....#...#.#.#...#...#.#...#...#.....#...#.#.....#..u..#.....#.# +###.#.#######.#.#####.#.###.#.#####.###.#.#####.###.###.###.###.###.###.#.###.#.# +#...#.#...#...#.....#.#.#...#...#.#...#.#...#...#...#...#...#.#.#...#...#.#...#.# +#.#####.#.#.###.#.#####.#.###.#.#.###.#.#####.#######.#####.#.###.###.###.###.#.# +#...#...#.#.#...#.......#.#...#.#...#...#.....#.......#.....#.U...#.#...#...#...# +#.#.#.###.#.#.#########.#.#####.###.###.#.#.###.#######.###########.###X#.#.###.# +#.#..l#...#.#...#.......#.....#...#...#.#.#o#...#.#.....#...#......x....#.#.#...# +#.#####C###.#.###.###########.###.#.###.#.###.###.#.###.#.#.#I#############.#.### +#.....#...#.#.#...#...#.....#.#...#.#...#.#...#.....#...#.#...#v......G.#...#..q# +###.#####.#.###.###.#.#.###.#.#.###.#.###.#.###.#####.#.#.#####.#######.#.#####.# +#.#y#...#.#...#.#...#.#...#.#...#...#...#.#.#...#.....#.#..i..#...#.....#...#...# +#.#.#.#.#.###.#.#.###.#.#.#.#####.#.###.#.#.###.#.###########H#.#.#.#####.#.#.### +#...#.#.#...#.#.....#.#.#.#.#...#.#.....#.#...#.#...........#.#.#.#g..#...#.#...# +#.###.#.###A#.#######.#.#.#.#.###.#######.###.#.#########.#.#.#.#.###.#####.###.# +#.#...#.....#.........#.#.#.#.#...#.....#...#.#.......#...#.#.#.#.#.#.#...#...#.# +###.#####################.#.#.#.#####.###.#.#.#########.###.#.###.#.#.#.#.###.#.# +#...#.......#.............#..t#.#...#...#.#.#.#.......#.#...#...#.#.#.N.#.....#.# +#.###.#####.#.#########.#######.#.#D#.#.#.#.#.#.#####.#.#.#####.#.#.###########.# +#.#...#...#..z#.#.......#.....#...#.#.#.#.#.#...#...#...#.#.#..h#.#.....#......b# +#.#.###.#.#####.#.#######.###.#####.###.#.#.#####.#.#####.#.#.###.#.###.#.####### +#.......#.......#...........#...........#.#.....E.#.........#...V.#...#.........# +################################################################################# diff --git a/2019/inputs/day_18_2.txt b/2019/inputs/day_18_2.txt new file mode 100644 index 0000000..8fda759 --- /dev/null +++ b/2019/inputs/day_18_2.txt @@ -0,0 +1,81 @@ +################################################################################# +#.............#.....#.................#.#.....#...#.......#...................#a# +#.#####.#######.#.###.#########.#####.#.#.###Y###.#.#####.#.#####.###########.#.# +#.#...#.#.....#.#..c#.........#...#.#...#...#.#...#.#.#...#.#.#...#...#...#.....# +#.#.###.#.###.#.###.#.###########.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.####### +#.#...#...#.#...#.#...#...........#.#...#.#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.....# +#.#.#.#####.#####.#####.###.#######.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.###.# +#.#.#.............#.#...#.#.#..e..#.....#.#...........#...#.#...#...#...#.....#.# +#.#########.#####.#.#.###.#.#.###.#####.#.###############.#T#.#.###############.# +#...#..k....#.....#.#.Z.#...#...#.....#.#.........#.#.....#.#.#.....#.L.....#...# +###.#.#.#######.###.###.#######.#####.#.#########.#.#.###.#.#.###.#.###.###.#.### +#...#.#.#.....#.#...#...#.....#.....#.#.#...#...#.#.#.#...#.#.#...#...#.#...#...# +#.###.#.#.###.#.#.###.###.###.#####.#.#.#.#.#.#.#.#.#.###.#.###.#####.#.#.#####.# +#.#...#.#.#...#.#...#.....#.#.....#.#.#.#.#...#...#.#...#.#.#...#.#...#.#.#.....# +#.###.#.#.#.###.###.#######.#.#####.#.#.#.#########.###.###.#.###.#.###.#.#.###.# +#...#.#.#.#...#...#.........#.#.....#.#.#.............#.......#...#.#...#.#...#.# +###.#.###.###.###.###.#.#####.#.#####.###############.#########.#.#.###.#.###.#.# +#.....#...#...#.J...#.#.#.....#.....#...#...........#.#...#...#.#.......#...#.#.# +#######.###.#######.#.###.#####.#######.#########.#.#.###.#.#.#########.#####.#.# +#.......#.#...#...#...#...#...#.#.......#.....O.#.#.#.#...#.#.......#...#.....#s# +#.#######.###.#.#.#####.###.#.#.#.#######.#####.#.#.#.#.###.#####.#.#.###.#####.# +#...#...#...#...#...#.#.#...#...#.......#.....#.#.#.#.#...#.#...#.#.#...#...#...# +###.#.#.#.#########.#.#.#.#######.#####.#.#####.#.###.###.#.###.###.#.#####.#.### +#.#...#.#.........#...#...#....d#.....#.#.#.....#.#...#...#.#.#...#.#.#.....#.#.# +#.#####.#######.#######.###.###.#####.#.#.#.#####.#.###.#.#.#.###.#.#.#.#####.#.# +#...#.#.......#.......#...#.#...#.....#.#.#.....#.......#.#.....#.#.#.#.#.......# +#.#.#.#######.#.#.#####.###.#.#####.###.#.#####.#############.###.#.#.#.#######.# +#.#...#.....#.#.#...#...#...#.....#...#.#.#...#.#...........#.#...#.#.#.#...#.#.# +#.###.###.#.#.#.###.#.###.#######.#####.#.###.#.#.#########.#.#.###.#.#.#.#.#.#.# +#...#.....#.#.#...#...#...#.......#.....#...#.#.#.....#...#...#...#.#.#...#.#...# +#.#.#######.#.###.#####.###.#######.#######.#.#.#####.###.#######.#.#####.#.#.### +#.#.#.....#.#.#.#.#.#...#.#.#...#...#...#...#.#.....#...#.....#...#.....#.#.#w#.# +#.#.#.###.#.#.#.#.#.#.###.#.#.#.###.#.#.#.###.#.###.###.#.###.#.###.###.###.#.#.# +#.#.#.#.#.#.#.#.#.#.#.#m..#...#...#...#.#.#...#...#...#.#...#.#.#.....#.#...#.#.# +###.#.#.#.###W#.#.#.#.#.#########.#####.#.#.#.###.#####.###.#.#.#######.#.###.#.# +#...#...#.#...#.....#.#.......#...#...#.#.#.#.#.#.....#.....#.#.........#.#.#...# +#.###.###.#.###.#####.#.###.###.###.#.#.#.#.#.#.#####.#######.###########.#.###.# +#.#...#...#.#...#.S...#...#.....#...#.#.#...#.....#.#.........#...#...#...#.....# +#.#.###.###.#####.#######.#######.###.#.#########.#.###########.#.#.#.#.###.##### +#.....#...........#.......F.......#....@#@...........f..........#...#...#.......# +################################################################################# +#.....#.#...........#.....#............@#@..........#...#.....#.M.......#.....#.# +###P#.#.#.#######.###.###.#.#######.###.#.#########.#.#.#.###.###.#####.###.#.#.# +#...#...#...#.#...#.....#.#.#.......#...#...#.........#...#.......#...#.....#.#.# +#.#.#######.#.#.###.#####.#.#.#######.#####.###############.#########.#######.#.# +#.#.#.....#.#.#.#...#...#.#.#.#.........#...#.......#...#.....#.....#.#.......#.# +#.###.###.#.#.#.#.###.#.#.#.#.###########.###.#####.#.#.#######.###.#.#.#######.# +#...#.#.#.#...#.#.#...#...#.#...........#...#...#.#...#.......#.#.#.#.#.........# +#.#.#.#.#.#.###.#.#.#####.#######.#####.###.###.#.###########.#.#.#.#.#.#######.# +#.#.#...#...#...#.#r#.....#.....#.....#.#...#.#.#.......#...#.....#.#...#.....#.# +#.#.###.#####.###.#.#######.###.#####.#.#.#.#.#.###.#####.#.#######.#.###.###.#.# +#.#...#.#...#...#.#.........#...#...#.#.#.#...#...#.#.....#.#......p#...#.#.#.#.# +###.#.#.#.#.###.#.###########.###.#.#.#.#.###.###.#.#.#####.#.###.#######.#.#.### +#...#.#.#.#...#.......#.....#.#...#...#.#...#.#...#.....#...#.#...#.K...#.#.#...# +#.#####.#.###.#######.#.###Q#.#.#######.###.#.#.#####.###.###.#.###.###.#.#.###.# +#.....#...#...#.#...#.#.#.#...#...#.....#...#.#.....#.#...#...#.#...#.#..j#.#...# +#.###.#####.###.#.#.###.#.#########.###.#.#########.###.#.#.###.#.###.#####.#.### +#...#.#.....#...#.#.B...#...#...#...#...#.#.......#.....#.#...#.#...........#.R.# +#.###.#.#######.#.#######.#.#.#.#.###.###.#.#.###.#######.###.###.#############.# +#.#...#.......#.#n....#...#.#.#...#...#.#...#...#.....#...#.#.....#..u..#.....#.# +###.#.#######.#.#####.#.###.#.#####.###.#.#####.###.###.###.###.###.###.#.###.#.# +#...#.#...#...#.....#.#.#...#...#.#...#.#...#...#...#...#...#.#.#...#...#.#...#.# +#.#####.#.#.###.#.#####.#.###.#.#.###.#.#####.#######.#####.#.###.###.###.###.#.# +#...#...#.#.#...#.......#.#...#.#...#...#.....#.......#.....#.U...#.#...#...#...# +#.#.#.###.#.#.#########.#.#####.###.###.#.#.###.#######.###########.###X#.#.###.# +#.#..l#...#.#...#.......#.....#...#...#.#.#o#...#.#.....#...#......x....#.#.#...# +#.#####C###.#.###.###########.###.#.###.#.###.###.#.###.#.#.#I#############.#.### +#.....#...#.#.#...#...#.....#.#...#.#...#.#...#.....#...#.#...#v......G.#...#..q# +###.#####.#.###.###.#.#.###.#.#.###.#.###.#.###.#####.#.#.#####.#######.#.#####.# +#.#y#...#.#...#.#...#.#...#.#...#...#...#.#.#...#.....#.#..i..#...#.....#...#...# +#.#.#.#.#.###.#.#.###.#.#.#.#####.#.###.#.#.###.#.###########H#.#.#.#####.#.#.### +#...#.#.#...#.#.....#.#.#.#.#...#.#.....#.#...#.#...........#.#.#.#g..#...#.#...# +#.###.#.###A#.#######.#.#.#.#.###.#######.###.#.#########.#.#.#.#.###.#####.###.# +#.#...#.....#.........#.#.#.#.#...#.....#...#.#.......#...#.#.#.#.#.#.#...#...#.# +###.#####################.#.#.#.#####.###.#.#.#########.###.#.###.#.#.#.#.###.#.# +#...#.......#.............#..t#.#...#...#.#.#.#.......#.#...#...#.#.#.N.#.....#.# +#.###.#####.#.#########.#######.#.#D#.#.#.#.#.#.#####.#.#.#####.#.#.###########.# +#.#...#...#..z#.#.......#.....#...#.#.#.#.#.#...#...#...#.#.#..h#.#.....#......b# +#.#.###.#.#####.#.#######.###.#####.###.#.#.#####.#.#####.#.#.###.#.###.#.####### +#.......#.......#...........#...........#.#.....E.#.........#...V.#...#.........# +################################################################################# diff --git a/2019/inputs/day_19.txt b/2019/inputs/day_19.txt new file mode 100644 index 0000000..e85881e --- /dev/null +++ b/2019/inputs/day_19.txt @@ -0,0 +1 @@ +109,424,203,1,21102,11,1,0,1106,0,282,21101,0,18,0,1106,0,259,1201,1,0,221,203,1,21102,1,31,0,1106,0,282,21101,0,38,0,1106,0,259,20102,1,23,2,21202,1,1,3,21101,1,0,1,21101,0,57,0,1105,1,303,2101,0,1,222,20101,0,221,3,21001,221,0,2,21102,1,259,1,21101,0,80,0,1105,1,225,21101,185,0,2,21102,91,1,0,1106,0,303,1202,1,1,223,21001,222,0,4,21102,259,1,3,21101,225,0,2,21102,1,225,1,21101,0,118,0,1106,0,225,20102,1,222,3,21102,1,131,2,21101,133,0,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1105,1,259,2101,0,1,223,21002,221,1,4,21002,222,1,3,21101,0,16,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21101,0,195,0,106,0,109,20207,1,223,2,20101,0,23,1,21102,1,-1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,1201,-4,0,249,22101,0,-3,1,22101,0,-2,2,21201,-1,0,3,21101,0,250,0,1106,0,225,21201,1,0,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22102,1,-2,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,21201,-2,0,3,21101,343,0,0,1106,0,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,22101,0,-4,1,21102,384,1,0,1106,0,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21201,1,0,-4,109,-5,2106,0,0 diff --git a/2019/inputs/day_2.txt b/2019/inputs/day_2.txt new file mode 100644 index 0000000..dd34cff --- /dev/null +++ b/2019/inputs/day_2.txt @@ -0,0 +1 @@ +1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,9,1,19,1,19,5,23,1,23,6,27,2,9,27,31,1,5,31,35,1,35,10,39,1,39,10,43,2,43,9,47,1,6,47,51,2,51,6,55,1,5,55,59,2,59,10,63,1,9,63,67,1,9,67,71,2,71,6,75,1,5,75,79,1,5,79,83,1,9,83,87,2,87,10,91,2,10,91,95,1,95,9,99,2,99,9,103,2,10,103,107,2,9,107,111,1,111,5,115,1,115,2,119,1,119,6,0,99,2,0,14,0 diff --git a/2019/inputs/day_20.txt b/2019/inputs/day_20.txt new file mode 100644 index 0000000..09d6330 --- /dev/null +++ b/2019/inputs/day_20.txt @@ -0,0 +1,113 @@ + K Z V U I F + Q T Y Y E E + ###################################.#####.###.###########.#####.#.##################################### + #.......#.#.............#.........#.#.......#.#.#.........#.....#...#...#...........#...#.....#.#.....# + ###.#####.###.###.###.###########.#.###.#####.#.###.#.#.#.###.###.###.#####.#######.###.#####.#.###.### + #.#...#.#.#.#.#.#.#.#.....#...........#.....#.#...#.#.#.#...#.#.#.#.....#.#.#...#.#.#...#.#.#.....#...# + #.#.###.#.#.###.###.#.#########.###.#######.#.#.#.#######.#.#.#.#.#.###.#.#.#.###.#####.#.#.#.#####.### + #.....#...#...............#.#.#.#.#.#.....#.#.#.#...#.....#.#.#.#.#...#.....#.#.#.........#...#.#...#.# + #.#######.###########.###.#.#.###.#.###.#.#.#.#.###.###.###.#.#.#.#.###.#.###.#.#.#.#######.###.###.#.# + #...#.......#...#.#...#...#...#.#.#.#...#...#.....#.#.#.#...#...#...#...#.........#.#.#.#...#.......#.# + #.#######.#.###.#.#######.###.#.#.#.#.#.###.###.#####.#####.###.#.#####.#####.#.#.###.#.###.#.#######.# + #.#.#...#.#...#.......#.......#.#...#.#...#.#.#...#.#.......#...#.#.........#.#.#...............#.....# + #.#.#.#######.#####.#####.###.#.###.#.#####.#.#.###.#####.###.#####.###.###########.###############.### + #.#...#...#.......#...#...#.#.......#.....#.#.....#.#.......#.#...#.#.#.#.......#.......#...#...#.#...# + #.###.###.#####.#.###.#####.#####.#.###.#######.#.#.#######.#.#.#####.#.#.###########.#####.###.#.#.### + #.#.#.#...#...#.#.#...#.#.#.#.#.#.#.#...#.......#.#.#.#.....#.....#...............#...#.#...#.........# + #.#.#.#.#####.#.#####.#.#.#.#.#.###.#.#####.###.###.#.#####.#.#######.#.#######.#######.#.#.###.#####.# + #.......#.#.#...#.#...............#.#...#.#.#.......#...#...#.......#.#.#.#.#...#.#.....#.#.#...#.#...# + #.#######.#.###.#.#.###.#.#.#.###.#.###.#.###.#.###.#.###.#.#.#.#######.#.#.#####.#.#######.#.###.###.# + #.#.#.#.#.#.......#.#.#.#.#.#.#.#.#.#...#...#.#.#.#.#.....#.#.#.#.#.#...#.......#.#.#.#...#.#.#...#.#.# + #.#.#.#.#.#####.#####.#.#####.#.#.#.#.###.#.#.###.#####.#####.#.#.#.#.#####.#.###.#.#.#.###.#.###.#.### + #.#.#.#.#.#.....#.#.....#.......#.#.#.#...#.#...#...#.......#.#.#.#.........#.#...#.......#.#.#.#.#.#.# + #.#.#.#.#.#.###.#.#.#####.###.#.#.#.#.#.###.#.###.#.###.#######.#.#.###.###.#####.#.#.#.###.#.#.#.#.#.# + #.......#.#.#.#.#.#.#...#.#.#.#.#...#...#...#...#.#.#.....#.#...#...#...#.......#...#.#...#.#.#.#...#.# + #####.###.#.#.###.#####.###.###.###.#####.#####.#.#.#.#####.#.#.#####.#######.#####.#######.#.#.#.###.# + #.#...#.........#...#.#.......#...#...#.....#...#.#.#.....#...#.#...........#.#.#.#...#.#.........#...# + #.###.#.#.#######.#.#.#.#########.#########.#.###.#.#.#.###.#.#########.###.###.#.#.###.###.#######.### + #.#.....#...#...#.#...#.....#.......#.......#.....#.#.#...#.#.....#.....#.....#...#.#...#.........#...# + #.###.#.#.#####.###.###.#######.#####.#############.#.#########.###.###########.###.#.#.#.###.#.###.#.# + #...#.#.#.#.#...#.#.#.....# U N Q W Z N #.......#.#...#...#...#.#.# + ###.###.###.###.#.#.###.### Y D P L W J #####.#########.#######.### + #.#.#.#.#...#...#.#...#.#.# #.....#...#...........#.#.# + #.#.#.#.###.###.#.#.###.#.# ###.#.###.###.###.#####.#.# + #...................#.#...# #.#.#.........#...#........CB + #.###.#######.#.###.#.#.#.# #.#.#.###.#####.###.#.#.#.# + #.#.........#.#...#.....#.# #...#.#.....#...#...#.#.#..AA + #######.#######.###.#####.# #.#######.#.###.#.#.###.### + #.....#.......#...#...#...# QJ..#.#...#.#.#.#...#...#.#.# + ###.#.#.###.###########.### ###.#.#######.###########.# +YG....#.....#.#.......#......TY #.........#...........#...# + #.#.#.###########.#.#.##### #.#####.###.#########.#.#.# + #.#.#.#...#...#...#.#.#...# CB..#.#.......#.#.#.#.....#..DN + #######.#####.#.#.#####.### ###.#########.#.#.######### + #.....#...#...#.#.#...#.#.# #...#.........#...#.......# + #.###.#.#.#.#.#.#.#.#.#.#.# ###.###.#####.#.#.#.#####.# +SP..#.....#...#...#...#......YG #.......#...#...#.#.#.....# + ########################### #.#.###.###.#.###.#.#.##### +NJ....#.................#.#.# KQ..#.#.......#.#...#.#.....# + #.#.#.#####.#.#.#####.#.#.# ###.###.###.###.#.#.###.#.# + #.#.#.....#.#.#.#.....#...# #.#...#.#.#.#.#.#.....#.#..IT + ###.#####.###.#####.#####.# #.#.#####.###.############# + #.#.....#...#.....#........WE IE..#.#.#.#...............#.# + #.#.#.#.#.#########.#.###.# #.#.#.#.#.###.###.###.###.# + #...#.#...#.#.#.#...#.#...# #.#.#...#.#.#...#.#...#.#.# + #.#######.#.#.#.#####.##### #.#####.#.#.#.#.#####.#.#.# + #.#.....#.#.........#.#...# #...........#.#.#.#...#....QJ + #######.###.#.#.###.#####.# #######.#.#######.#.#.###.# + #.#.....#...#.#.#.........# #.....#.#.#...#.#...#.....# + #.###.#.#.#######.#.#####.# ###.#########.#.########### +YV..#...#.#...#.#.#.#.#.....# #.......#.........#.#.....# + #.#.###.#.#.#.#.#.###.#.### #.#####.###.#####.#.#.#.#.# + #.....#...#.#...#.#.#.#....QX #.#...#.........#.#...#.#..QP + ###.###.#######.###.###.#.# #.###.#.###.#####.#.#####.# + #.#.#.....#.....#.....#.#.# #.#.#.#.#...#.....#...#...# + #.#####.#######.###.#.##### #.#.#.#####.#.###.###.#.#.# + #.#...#.#.....#.#.#.#...#..DM FE..#.#...#.#.#.#.......#.#.# + #.#.#####.#.###.#.#.###.#.# #.#.#.#.#.###############.# + #.#.......#...#.#.....#...# #.#...#.#.#.....#.......#.# + #.#.#.#.#.###.#.#####.###.# #######.#.#.#######.#.##### +QX....#.#.#.#.............#.# #.......#.#.......#.#.....# + #####.#.#.#.#.#.########### ###.###.#.#.#.###.#.#####.# + #.#.#.#.#.#.#.#.#.........# GX..#.#.......#.#.#.......#..DM + #.#.###############.###.#.# #.#.#####.#.###.###.###.#.# + #.#.#.........#...#...#.#..CS #.....#.#.#.#.#...#.#.#.#.# + #.#.#######.#####.###.#.### #######.#.###.#.#####.##### +WE........#.#.#.#.#.#...#...# MX........#.#.........#......CS + #####.###.#.#.#.#.#.#.##### #####.###.###.#####.###.### + #...#...............#.#.#.# #.#.....#.#.......#...#...# + ###.###################.#.# #.#.###########.#.###.#.#.# + #...............#.#........ME #.#.#.#...#...#.#.#...#.#.# + #.#.#####.#####.#.#.###.#.# #.#.#####.#######.#.#####.# +GX..#...#.#.#...........#.#.# #.................#.......# + #.#.###.#######.###.#####.# J D Z V S I Y #.###.###.#.###.###.#.#.#.# + #.#.......#.......#.....#.# I N T Y P T V #...#...#.#.#.#.#.#.#.#.#.# + #.#.#.#########.#.#.#############.#########.###.#.#.#############.###.###########.###.#.#.#.#.#.#####.# + #.#.#.....#.....#.#...#.......#.....#.......#.....#.#.#.#.#...#...#.........#.....#...#.#.....#...#...# + #.#############.###.#######.#.#####.#.###.###.#####.#.#.#.###.#.#####.#.#.#####.#.#.#.#.#####.###.##### + #...........#.....#.....#...#.......#...#.#.#.....#.#.....#.#.......#.#.#...#...#.#.#.#.#.....#.#.....# + ###.#######.#######.#####.###.#######.#.###.###.#.#.#.###.#.#.#######.#############.#.#######.#.#.###.# + #.#.....#.#.#.#.......#.#.#.#...#...#.#...#...#.#.#.....#...#.......#.....#.#...#...#...#.......#.#...# + #.#.#.###.#.#.#.#.###.#.###.###.#.#.###.#.###.#.#########.#####.#.###.#.###.#.#########.#####.#####.#.# + #...#...#.....#.#.#...#...#.#...#.#...#.#.#.....#.#.#.....#...#.#.#...#.............#.....#.....#...#.# + #####.###########.#####.###.#.###.#.###.#####.#.#.#.###.#.#.#.###.#.#######.###.#########.#.#.######### + #.........#.....#.#...........#...#.#...#.#...#.#...#...#.#.#.....#.......#...#.#.....#.#.#.#.....#.#.# + ###.###.#.###.#####.#.#.#.#.#.#.###.###.#.###.#####.#.#####.#.###.###.#####.#####.#####.#####.#####.#.# + #...#.#.#.#.........#.#.#.#.#...#...#.....#.....#.......#...#.#.#.#.......#.#.#...#.....#.#.#.........# + #.#.#.#.###.###.###########.###.#.###.#.#####.#.#.#.#.#.#.#.###.###.#.###.###.###.#.#.#.#.#.#.###.#.#.# + #.#.#...#...#.....#.........#.#.#...#.#.#.#...#.#.#.#.#.#.#.......#.#...#.#.....#...#.#.#.......#.#.#.# + #.#.###.#.#.#.#.#.#####.#####.#.###.#.###.###.#####.#######.###.###.#########.###.#######.#.#.#####.#.# + #.#.#...#.#.#.#.#.#.#.#.#.......#...#...#...#...#.....#.#.....#.#.#.......#...#.....#.#.#.#.#.#.#...#.# + #.#####.#.#####.###.#.#######.#.#.#.###.###.#.#.###.###.###.#####.#.#.#####.#####.#.#.#.###.#.#.#####.# + #...#...#.#.....#.#.....#.#...#.#.#.#...#.#...#.#.......#.#.#.#.#...#...........#.#.#...#.#.#.....#.#.# + ###.###.#########.#####.#.###.#####.#.###.###.#####.#####.#.#.#.#.#######.#######.###.###.#####.#.#.### + #.....#.#.....................#...#.#.......#.#.....#.....#.....#.#...........#.....#.#.#.#.#...#.#...# + #.###.#####.#.#.#.###.#.#.#.###.###.###.#.###.#####.###.#.#.#########.###########.###.#.#.#.###.###.### + #...#...#...#.#.#.#...#.#.#.#.......#.#.#...#.....#.#...#.#.......#.#.........#.............#.........# + ###.#.#####.#############.#####.#.###.#.###.#####.#.#.###.###.#.#.#.#####.#.###.###.###.###.#.#####.### + #...#.#.#.#...#.#...#.......#...#.....#.#...#.....#...#.#.#.#.#.#...#.....#.....#.....#...#.#...#.....# + #.###.#.#.###.#.###.###.#####.#####.#####.###.#########.#.#.#####.#######.#####.###.#####.#.#.###.###.# + #.#.........#.#.........#.....#.....#.....#.........#.....#.......#...........#...#...#...#.#...#.#...# + ###################################.###.#######.#.###.###.###.#######.################################# + N J W Z Z M M T + D I L W Z X E Y diff --git a/2019/inputs/day_21.txt b/2019/inputs/day_21.txt new file mode 100644 index 0000000..cafb613 --- /dev/null +++ b/2019/inputs/day_21.txt @@ -0,0 +1 @@ +109,2050,21102,1,966,1,21101,0,13,0,1106,0,1378,21101,20,0,0,1105,1,1337,21101,27,0,0,1105,1,1279,1208,1,65,748,1005,748,73,1208,1,79,748,1005,748,110,1208,1,78,748,1005,748,132,1208,1,87,748,1005,748,169,1208,1,82,748,1005,748,239,21101,0,1041,1,21102,73,1,0,1106,0,1421,21101,0,78,1,21101,0,1041,2,21101,88,0,0,1106,0,1301,21101,68,0,1,21102,1041,1,2,21102,103,1,0,1106,0,1301,1101,0,1,750,1105,1,298,21101,0,82,1,21101,0,1041,2,21102,1,125,0,1105,1,1301,1102,1,2,750,1105,1,298,21102,79,1,1,21102,1,1041,2,21101,147,0,0,1106,0,1301,21102,1,84,1,21102,1,1041,2,21101,0,162,0,1106,0,1301,1101,0,3,750,1106,0,298,21101,0,65,1,21101,1041,0,2,21101,0,184,0,1106,0,1301,21101,76,0,1,21102,1,1041,2,21101,199,0,0,1106,0,1301,21102,75,1,1,21102,1,1041,2,21101,214,0,0,1105,1,1301,21101,221,0,0,1106,0,1337,21101,10,0,1,21102,1041,1,2,21102,236,1,0,1105,1,1301,1106,0,553,21102,1,85,1,21102,1,1041,2,21101,254,0,0,1105,1,1301,21101,78,0,1,21101,0,1041,2,21102,1,269,0,1106,0,1301,21102,276,1,0,1105,1,1337,21101,10,0,1,21102,1,1041,2,21101,0,291,0,1105,1,1301,1101,1,0,755,1105,1,553,21101,32,0,1,21102,1,1041,2,21102,313,1,0,1106,0,1301,21102,1,320,0,1106,0,1337,21102,327,1,0,1105,1,1279,1202,1,1,749,21102,65,1,2,21101,0,73,3,21102,1,346,0,1106,0,1889,1206,1,367,1007,749,69,748,1005,748,360,1101,0,1,756,1001,749,-64,751,1106,0,406,1008,749,74,748,1006,748,381,1102,1,-1,751,1105,1,406,1008,749,84,748,1006,748,395,1102,1,-2,751,1105,1,406,21102,1100,1,1,21101,0,406,0,1105,1,1421,21101,32,0,1,21102,1,1100,2,21101,421,0,0,1105,1,1301,21102,1,428,0,1106,0,1337,21102,435,1,0,1105,1,1279,2102,1,1,749,1008,749,74,748,1006,748,453,1102,1,-1,752,1106,0,478,1008,749,84,748,1006,748,467,1101,0,-2,752,1105,1,478,21101,1168,0,1,21101,0,478,0,1106,0,1421,21102,485,1,0,1105,1,1337,21102,1,10,1,21101,1168,0,2,21101,0,500,0,1105,1,1301,1007,920,15,748,1005,748,518,21101,0,1209,1,21102,1,518,0,1106,0,1421,1002,920,3,529,1001,529,921,529,101,0,750,0,1001,529,1,537,101,0,751,0,1001,537,1,545,1001,752,0,0,1001,920,1,920,1105,1,13,1005,755,577,1006,756,570,21102,1100,1,1,21101,570,0,0,1105,1,1421,21102,1,987,1,1105,1,581,21101,1001,0,1,21102,1,588,0,1106,0,1378,1101,0,758,593,1001,0,0,753,1006,753,654,21001,753,0,1,21101,610,0,0,1106,0,667,21101,0,0,1,21101,621,0,0,1106,0,1463,1205,1,647,21101,1015,0,1,21101,635,0,0,1106,0,1378,21101,1,0,1,21101,646,0,0,1105,1,1463,99,1001,593,1,593,1106,0,592,1006,755,664,1101,0,0,755,1105,1,647,4,754,99,109,2,1102,1,726,757,21202,-1,1,1,21101,9,0,2,21102,1,697,3,21102,692,1,0,1105,1,1913,109,-2,2105,1,0,109,2,101,0,757,706,1201,-1,0,0,1001,757,1,757,109,-2,2106,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,255,63,95,191,159,223,127,0,155,123,163,249,179,110,200,117,68,60,61,190,197,250,196,186,111,187,99,158,244,217,222,246,94,205,35,54,115,239,218,243,62,241,229,168,79,199,215,178,182,118,43,228,125,203,214,113,231,120,77,153,141,157,253,143,87,102,86,207,213,177,57,181,156,85,78,204,247,174,109,172,248,92,98,53,93,232,69,242,212,237,152,70,216,183,47,49,124,121,116,122,230,114,100,103,201,51,55,84,171,234,254,238,233,76,185,34,50,175,219,140,42,189,136,38,226,169,39,184,198,166,137,220,251,245,202,142,56,139,167,206,126,252,106,107,71,162,235,236,101,108,119,58,173,170,46,221,227,59,154,188,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,73,110,112,117,116,32,105,110,115,116,114,117,99,116,105,111,110,115,58,10,13,10,87,97,108,107,105,110,103,46,46,46,10,10,13,10,82,117,110,110,105,110,103,46,46,46,10,10,25,10,68,105,100,110,39,116,32,109,97,107,101,32,105,116,32,97,99,114,111,115,115,58,10,10,58,73,110,118,97,108,105,100,32,111,112,101,114,97,116,105,111,110,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,78,68,44,32,79,82,44,32,111,114,32,78,79,84,67,73,110,118,97,108,105,100,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,44,32,66,44,32,67,44,32,68,44,32,74,44,32,111,114,32,84,40,73,110,118,97,108,105,100,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,74,32,111,114,32,84,52,79,117,116,32,111,102,32,109,101,109,111,114,121,59,32,97,116,32,109,111,115,116,32,49,53,32,105,110,115,116,114,117,99,116,105,111,110,115,32,99,97,110,32,98,101,32,115,116,111,114,101,100,0,109,1,1005,1262,1270,3,1262,20101,0,1262,0,109,-1,2106,0,0,109,1,21102,1,1288,0,1106,0,1263,21001,1262,0,0,1102,0,1,1262,109,-1,2106,0,0,109,5,21102,1310,1,0,1105,1,1279,22102,1,1,-2,22208,-2,-4,-1,1205,-1,1332,22101,0,-3,1,21101,1332,0,0,1106,0,1421,109,-5,2106,0,0,109,2,21101,1346,0,0,1105,1,1263,21208,1,32,-1,1205,-1,1363,21208,1,9,-1,1205,-1,1363,1105,1,1373,21102,1,1370,0,1106,0,1279,1106,0,1339,109,-2,2105,1,0,109,5,1202,-4,1,1386,20101,0,0,-2,22101,1,-4,-4,21102,0,1,-3,22208,-3,-2,-1,1205,-1,1416,2201,-4,-3,1408,4,0,21201,-3,1,-3,1106,0,1396,109,-5,2106,0,0,109,2,104,10,22102,1,-1,1,21101,0,1436,0,1106,0,1378,104,10,99,109,-2,2105,1,0,109,3,20002,593,753,-1,22202,-1,-2,-1,201,-1,754,754,109,-3,2105,1,0,109,10,21102,5,1,-5,21102,1,1,-4,21102,1,0,-3,1206,-9,1555,21101,3,0,-6,21101,5,0,-7,22208,-7,-5,-8,1206,-8,1507,22208,-6,-4,-8,1206,-8,1507,104,64,1105,1,1529,1205,-6,1527,1201,-7,716,1515,21002,0,-11,-8,21201,-8,46,-8,204,-8,1105,1,1529,104,46,21201,-7,1,-7,21207,-7,22,-8,1205,-8,1488,104,10,21201,-6,-1,-6,21207,-6,0,-8,1206,-8,1484,104,10,21207,-4,1,-8,1206,-8,1569,21102,1,0,-9,1105,1,1689,21208,-5,21,-8,1206,-8,1583,21102,1,1,-9,1106,0,1689,1201,-5,716,1588,21002,0,1,-2,21208,-4,1,-1,22202,-2,-1,-1,1205,-2,1613,21201,-5,0,1,21102,1613,1,0,1105,1,1444,1206,-1,1634,22101,0,-5,1,21101,0,1627,0,1106,0,1694,1206,1,1634,21101,2,0,-3,22107,1,-4,-8,22201,-1,-8,-8,1206,-8,1649,21201,-5,1,-5,1206,-3,1663,21201,-3,-1,-3,21201,-4,1,-4,1106,0,1667,21201,-4,-1,-4,21208,-4,0,-1,1201,-5,716,1676,22002,0,-1,-1,1206,-1,1686,21101,1,0,-4,1105,1,1477,109,-10,2106,0,0,109,11,21102,0,1,-6,21101,0,0,-8,21101,0,0,-7,20208,-6,920,-9,1205,-9,1880,21202,-6,3,-9,1201,-9,921,1724,21002,0,1,-5,1001,1724,1,1733,20101,0,0,-4,21202,-4,1,1,21101,1,0,2,21101,9,0,3,21101,1754,0,0,1105,1,1889,1206,1,1772,2201,-10,-4,1767,1001,1767,716,1767,20102,1,0,-3,1105,1,1790,21208,-4,-1,-9,1206,-9,1786,22101,0,-8,-3,1105,1,1790,22101,0,-7,-3,1001,1733,1,1795,21001,0,0,-2,21208,-2,-1,-9,1206,-9,1812,21201,-8,0,-1,1105,1,1816,22101,0,-7,-1,21208,-5,1,-9,1205,-9,1837,21208,-5,2,-9,1205,-9,1844,21208,-3,0,-1,1106,0,1855,22202,-3,-1,-1,1106,0,1855,22201,-3,-1,-1,22107,0,-1,-1,1106,0,1855,21208,-2,-1,-9,1206,-9,1869,21201,-1,0,-8,1105,1,1873,22101,0,-1,-7,21201,-6,1,-6,1105,1,1708,22102,1,-8,-10,109,-11,2106,0,0,109,7,22207,-6,-5,-3,22207,-4,-6,-2,22201,-3,-2,-1,21208,-1,0,-6,109,-7,2105,1,0,0,109,5,2102,1,-2,1912,21207,-4,0,-1,1206,-1,1930,21102,1,0,-4,22101,0,-4,1,21202,-3,1,2,21102,1,1,3,21102,1949,1,0,1105,1,1954,109,-5,2105,1,0,109,6,21207,-4,1,-1,1206,-1,1977,22207,-5,-3,-1,1206,-1,1977,21202,-5,1,-5,1105,1,2045,22102,1,-5,1,21201,-4,-1,2,21202,-3,2,3,21102,1,1996,0,1105,1,1954,22102,1,1,-5,21102,1,1,-2,22207,-5,-3,-1,1206,-1,2015,21101,0,0,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2037,21202,-2,1,1,21101,2037,0,0,106,0,1912,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2106,0,0 diff --git a/2019/inputs/day_22.txt b/2019/inputs/day_22.txt new file mode 100644 index 0000000..b61e760 --- /dev/null +++ b/2019/inputs/day_22.txt @@ -0,0 +1,100 @@ +deal with increment 34 +deal into new stack +cut 1712 +deal into new stack +cut 1984 +deal with increment 62 +deal into new stack +deal with increment 13 +deal into new stack +deal with increment 67 +cut -5590 +deal with increment 63 +cut -1086 +deal with increment 52 +cut 7894 +deal with increment 71 +cut -864 +deal into new stack +cut 239 +deal with increment 17 +cut -7187 +deal with increment 62 +deal into new stack +cut -7380 +deal with increment 14 +cut 3842 +deal into new stack +cut -5258 +deal with increment 40 +deal into new stack +deal with increment 45 +cut -6026 +deal with increment 21 +cut 3600 +deal with increment 56 +cut 2329 +deal into new stack +deal with increment 13 +cut -2409 +deal with increment 49 +cut 294 +deal into new stack +cut 4776 +deal with increment 17 +cut 5801 +deal with increment 43 +cut 8999 +deal with increment 46 +cut -8527 +deal with increment 4 +deal into new stack +cut -6767 +deal into new stack +deal with increment 33 +cut -532 +deal with increment 29 +deal into new stack +deal with increment 56 +cut 6867 +deal with increment 70 +cut 4276 +deal into new stack +cut -5621 +deal with increment 56 +cut -2966 +deal with increment 70 +deal into new stack +deal with increment 51 +cut -4097 +deal with increment 42 +deal into new stack +cut -5180 +deal with increment 61 +deal into new stack +cut 5367 +deal with increment 50 +cut 3191 +deal with increment 75 +cut 915 +deal with increment 72 +cut -3893 +deal with increment 22 +cut -3405 +deal with increment 30 +cut -6509 +deal with increment 31 +cut -7220 +deal with increment 45 +cut 6489 +deal with increment 70 +cut -4047 +deal into new stack +deal with increment 75 +cut 3980 +deal with increment 10 +cut 9677 +deal into new stack +deal with increment 45 +cut -6969 +deal into new stack diff --git a/2019/inputs/day_23.txt b/2019/inputs/day_23.txt new file mode 100644 index 0000000..e4f8887 --- /dev/null +++ b/2019/inputs/day_23.txt @@ -0,0 +1 @@ +3,62,1001,62,11,10,109,2215,105,1,0,1846,1780,1120,1959,571,2182,1083,631,1485,1306,1157,2153,1654,1592,1454,664,1815,951,2124,794,695,2023,1378,1248,1518,984,1887,2058,823,1019,891,1277,1685,2089,1341,1922,1186,765,1751,1413,602,922,858,1623,1217,1559,1050,1990,734,1720,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1106,0,73,3,65,20101,0,64,1,21001,66,0,2,21101,105,0,0,1105,1,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,133,1,133,68,133,101,0,0,62,1001,133,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1101,1,0,0,1001,161,1,169,101,0,65,0,1101,0,1,61,1101,0,0,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1105,1,178,21102,1,210,0,105,1,69,2101,0,1,70,1102,0,1,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1105,1,218,1105,1,73,109,4,21101,0,0,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1106,0,263,22102,1,-3,-3,109,-4,2106,0,0,109,4,21101,0,1,-3,21101,0,0,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,21202,-3,1,-3,109,-4,2106,0,0,109,1,101,1,68,358,21001,0,0,1,101,3,68,366,21001,0,0,2,21102,1,376,0,1106,0,436,22101,0,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21102,1,0,-4,21102,1,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,385,471,20102,1,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1106,0,547,21102,-1,1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1106,0,529,21201,-4,0,-7,109,-8,2106,0,0,109,1,101,1,68,564,20102,1,0,0,109,-1,2106,0,0,1102,97571,1,66,1101,1,0,67,1101,598,0,68,1101,556,0,69,1101,0,1,71,1101,0,600,72,1105,1,73,1,-1605712,28,112719,1102,1,48679,66,1102,1,1,67,1102,1,629,68,1102,556,1,69,1101,0,0,71,1102,631,1,72,1106,0,73,1,1782,1102,1,7877,66,1102,1,2,67,1101,658,0,68,1101,302,0,69,1102,1,1,71,1102,1,662,72,1105,1,73,0,0,0,0,26,81559,1101,0,22453,66,1101,1,0,67,1102,1,691,68,1101,0,556,69,1102,1,1,71,1102,1,693,72,1105,1,73,1,125,35,19959,1101,0,21493,66,1101,0,5,67,1102,1,722,68,1101,0,302,69,1102,1,1,71,1101,0,732,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,2,56893,1102,77191,1,66,1101,1,0,67,1102,1,761,68,1101,556,0,69,1101,1,0,71,1101,763,0,72,1105,1,73,1,1037327,8,179734,1101,57977,0,66,1101,0,1,67,1101,792,0,68,1102,556,1,69,1101,0,0,71,1101,0,794,72,1105,1,73,1,1430,1102,57173,1,66,1101,0,1,67,1101,0,821,68,1102,1,556,69,1101,0,0,71,1101,0,823,72,1106,0,73,1,1128,1101,0,37573,66,1102,1,3,67,1102,1,850,68,1102,253,1,69,1102,1,1,71,1101,856,0,72,1105,1,73,0,0,0,0,0,0,17,209158,1101,0,17569,66,1102,1,1,67,1101,0,885,68,1102,556,1,69,1101,2,0,71,1101,887,0,72,1106,0,73,1,8329,20,85972,34,54146,1101,84653,0,66,1101,1,0,67,1101,0,918,68,1102,1,556,69,1102,1,1,71,1101,0,920,72,1105,1,73,1,3167,20,64479,1101,0,88657,66,1102,1,1,67,1101,0,949,68,1101,556,0,69,1102,0,1,71,1102,1,951,72,1105,1,73,1,1419,1101,0,104579,66,1101,2,0,67,1101,0,978,68,1101,0,302,69,1101,0,1,71,1102,982,1,72,1105,1,73,0,0,0,0,6,76316,1102,33797,1,66,1101,0,1,67,1102,1011,1,68,1101,556,0,69,1102,1,3,71,1101,0,1013,72,1105,1,73,1,5,35,13306,35,26612,39,113194,1102,75781,1,66,1101,0,1,67,1102,1,1046,68,1102,1,556,69,1101,0,1,71,1101,1048,0,72,1106,0,73,1,1777,20,42986,1101,32183,0,66,1102,1,1,67,1102,1,1077,68,1102,556,1,69,1102,1,2,71,1102,1,1079,72,1105,1,73,1,10,35,6653,39,169791,1101,19079,0,66,1101,0,4,67,1102,1,1110,68,1102,253,1,69,1101,0,1,71,1102,1118,1,72,1105,1,73,0,0,0,0,0,0,0,0,7,7877,1102,1,56893,66,1101,0,4,67,1102,1147,1,68,1101,253,0,69,1102,1,1,71,1101,0,1155,72,1105,1,73,0,0,0,0,0,0,0,0,45,73189,1102,104651,1,66,1101,1,0,67,1102,1,1184,68,1101,556,0,69,1101,0,0,71,1101,0,1186,72,1105,1,73,1,1351,1101,0,43661,66,1101,1,0,67,1102,1213,1,68,1101,0,556,69,1102,1,1,71,1101,1215,0,72,1105,1,73,1,763676,28,75146,1101,16963,0,66,1102,1,1,67,1102,1,1244,68,1102,1,556,69,1102,1,1,71,1102,1246,1,72,1106,0,73,1,11,26,163118,1101,461,0,66,1101,1,0,67,1102,1275,1,68,1101,556,0,69,1101,0,0,71,1102,1,1277,72,1106,0,73,1,1263,1102,101483,1,66,1101,1,0,67,1102,1304,1,68,1102,556,1,69,1102,0,1,71,1102,1306,1,72,1106,0,73,1,1607,1101,0,14251,66,1101,0,3,67,1102,1333,1,68,1101,302,0,69,1102,1,1,71,1102,1,1339,72,1105,1,73,0,0,0,0,0,0,2,170679,1101,0,27073,66,1101,0,4,67,1102,1,1368,68,1102,1,302,69,1101,1,0,71,1101,0,1376,72,1106,0,73,0,0,0,0,0,0,0,0,1,154743,1101,0,15583,66,1101,0,1,67,1102,1,1405,68,1102,556,1,69,1101,0,3,71,1101,0,1407,72,1106,0,73,1,1,33,14998,21,302361,34,81219,1101,0,56597,66,1101,0,6,67,1102,1440,1,68,1102,1,302,69,1102,1,1,71,1101,1452,0,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,45,146378,1102,6991,1,66,1101,0,1,67,1102,1,1481,68,1102,1,556,69,1101,0,1,71,1102,1,1483,72,1106,0,73,1,902,21,201574,1102,1,89867,66,1101,2,0,67,1101,1512,0,68,1101,0,302,69,1101,1,0,71,1102,1516,1,72,1106,0,73,0,0,0,0,5,10798,1102,1,61553,66,1102,1,1,67,1102,1,1545,68,1102,556,1,69,1101,0,6,71,1101,0,1547,72,1106,0,73,1,2,20,21493,17,104579,7,15754,26,244677,39,282985,39,339582,1101,73189,0,66,1102,2,1,67,1101,0,1586,68,1101,0,351,69,1102,1,1,71,1101,0,1590,72,1105,1,73,0,0,0,0,255,60251,1101,0,91463,66,1102,1,1,67,1101,1619,0,68,1101,556,0,69,1102,1,1,71,1101,0,1621,72,1105,1,73,1,6467743,28,37573,1102,1,34369,66,1101,0,1,67,1101,1650,0,68,1102,556,1,69,1102,1,1,71,1101,1652,0,72,1105,1,73,1,8933,21,100787,1102,1,77081,66,1101,0,1,67,1101,1681,0,68,1102,1,556,69,1102,1,1,71,1101,1683,0,72,1105,1,73,1,2310,33,7499,1101,0,44699,66,1101,0,1,67,1102,1712,1,68,1101,556,0,69,1101,3,0,71,1101,1714,0,72,1105,1,73,1,3,8,89867,5,5399,34,108292,1101,97387,0,66,1102,1,1,67,1102,1747,1,68,1102,556,1,69,1102,1,1,71,1102,1749,1,72,1105,1,73,1,4,20,107465,1101,0,13463,66,1101,1,0,67,1101,1778,0,68,1101,0,556,69,1102,0,1,71,1102,1,1780,72,1106,0,73,1,1250,1102,51581,1,66,1102,1,3,67,1102,1807,1,68,1101,302,0,69,1101,0,1,71,1102,1,1813,72,1105,1,73,0,0,0,0,0,0,2,113786,1102,1,73679,66,1102,1,1,67,1102,1842,1,68,1102,556,1,69,1101,1,0,71,1102,1,1844,72,1105,1,73,1,160,39,56597,1101,0,60251,66,1101,0,1,67,1101,1873,0,68,1102,556,1,69,1102,6,1,71,1101,1875,0,72,1106,0,73,1,22677,47,94099,1,51581,1,103162,9,14251,9,28502,9,42753,1101,0,81559,66,1101,0,3,67,1102,1914,1,68,1101,0,302,69,1101,1,0,71,1102,1920,1,72,1105,1,73,0,0,0,0,0,0,47,188198,1101,0,6653,66,1101,4,0,67,1102,1949,1,68,1101,302,0,69,1101,0,1,71,1101,0,1957,72,1106,0,73,0,0,0,0,0,0,0,0,39,226388,1101,63659,0,66,1101,0,1,67,1101,0,1986,68,1102,556,1,69,1102,1,1,71,1102,1,1988,72,1105,1,73,1,-2,34,27073,1101,94099,0,66,1101,2,0,67,1101,0,2017,68,1101,0,302,69,1102,1,1,71,1102,2021,1,72,1106,0,73,0,0,0,0,2,227572,1101,100787,0,66,1101,0,3,67,1101,2050,0,68,1102,1,302,69,1101,1,0,71,1101,0,2056,72,1105,1,73,0,0,0,0,0,0,6,19079,1101,0,47599,66,1102,1,1,67,1101,0,2085,68,1102,556,1,69,1102,1,1,71,1101,2087,0,72,1105,1,73,1,2677,33,22497,1102,1,7499,66,1101,0,3,67,1101,2116,0,68,1102,1,302,69,1101,0,1,71,1101,0,2122,72,1105,1,73,0,0,0,0,0,0,6,38158,1101,0,101359,66,1102,1,1,67,1101,2151,0,68,1102,1,556,69,1102,1,0,71,1102,1,2153,72,1105,1,73,1,1752,1101,48091,0,66,1101,1,0,67,1102,1,2180,68,1101,0,556,69,1101,0,0,71,1101,0,2182,72,1106,0,73,1,1463,1102,5399,1,66,1101,0,2,67,1102,1,2209,68,1101,0,302,69,1102,1,1,71,1101,0,2213,72,1106,0,73,0,0,0,0,6,57237 diff --git a/2019/inputs/day_24.txt b/2019/inputs/day_24.txt new file mode 100644 index 0000000..ba900ad --- /dev/null +++ b/2019/inputs/day_24.txt @@ -0,0 +1,5 @@ +##.#. +.##.. +##.#. +.#### +###.. diff --git a/2019/inputs/day_25.txt b/2019/inputs/day_25.txt new file mode 100644 index 0000000..5351575 --- /dev/null +++ b/2019/inputs/day_25.txt @@ -0,0 +1 @@ +109,4795,21102,1,3124,1,21102,1,13,0,1106,0,1424,21102,1,166,1,21101,24,0,0,1105,1,1234,21102,31,1,0,1106,0,1984,1106,0,13,6,4,3,2,52,51,21,4,28,56,55,3,19,-9,-10,47,89,88,90,90,6,77,73,85,71,1,76,68,63,65,22,-27,70,76,81,87,5,105,105,107,108,95,4,97,92,109,109,5,110,105,110,108,95,4,115,96,109,109,13,-3,59,101,85,92,97,13,84,80,92,78,34,-15,26,-16,46,88,72,79,84,0,72,76,-3,85,74,79,75,-8,64,68,75,57,65,70,64,66,72,8,-41,32,-22,56,77,82,-4,60,76,62,70,-2,74,-11,55,52,68,67,73,56,60,52,-20,44,56,66,-24,48,58,42,49,54,-16,-53,10,0,56,99,96,95,82,94,83,45,-9,23,-13,61,85,88,74,71,82,73,79,73,89,67,65,-4,62,73,70,69,56,68,57,2,-35,24,-14,64,85,90,4,70,67,79,7,83,-2,68,75,-5,78,65,57,75,-10,76,53,76,0,-37,31,-21,57,78,83,-3,64,74,72,0,76,-9,73,58,57,-13,70,57,49,67,-18,54,64,48,55,-23,48,44,56,42,-14,-51,14,-4,74,95,100,14,97,77,86,79,9,92,79,75,5,27,-17,61,82,87,1,68,78,76,4,80,-5,66,58,78,60,-10,73,60,52,70,-15,57,67,51,58,-6,-43,14,-4,74,95,100,14,81,94,90,90,9,92,79,75,5,60,-50,23,42,38,-32,38,39,30,42,47,-38,30,36,28,25,41,38,34,31,18,23,29,19,33,-52,20,29,-55,27,27,27,8,15,-61,22,16,-64,24,13,18,-54,-69,-70,-14,7,12,-74,-8,-11,1,-71,5,-80,-4,-3,3,-15,-84,-85,-109,29,-19,59,80,85,-1,82,62,71,64,-6,77,64,60,-10,62,66,57,59,63,57,67,51,-19,56,58,57,57,-10,-47,44,-34,39,58,54,-16,60,61,57,64,48,56,-23,52,40,60,38,-28,44,53,-31,55,32,55,-35,48,42,41,-39,32,38,42,-42,-44,12,33,38,-48,28,19,25,32,-52,-76,-77,59,-49,13,55,-30,42,51,-33,49,50,32,31,31,39,36,48,-42,24,35,32,34,29,21,35,19,25,37,-53,14,10,26,18,-57,-59,-3,18,23,-63,1,17,3,-67,1,-4,14,-2,6,-73,-8,14,-76,-12,-78,-40,2,4,-13,-82,-106,-107,35,-25,53,74,79,0,74,60,-10,65,53,72,64,52,56,52,50,-19,53,57,62,56,-24,58,54,38,39,40,-29,-31,2,56,35,-34,-58,-59,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-94,-98,-103,-83,-97,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-90,-94,-97,-97,-86,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,263,-253,-199,-233,-158,-156,-151,-169,-226,-239,-158,-162,-176,-164,-160,-172,-179,-247,-162,-170,-177,-184,-183,-253,-171,-190,-167,-174,-258,-257,-227,-183,-197,-187,-175,-182,-193,-184,-268,-202,-191,-194,-192,-197,-205,-191,-207,-276,-278,-222,-201,-196,-282,-206,-219,-196,-286,-207,-206,-210,-223,-222,-223,-225,-280,-293,-296,-232,-220,-231,-300,-212,-223,-218,-304,-236,-228,-223,-239,-227,-310,-227,-240,-244,-314,-248,-237,-250,-243,-239,-247,-237,-308,-345,-273,-260,-248,-243,-263,-329,-252,-252,-248,-260,-267,-266,-253,-337,-249,-260,-255,-259,-342,-260,-267,-280,-270,-271,-348,-281,-268,-272,-279,-285,-342,-355,-280,-278,-279,-284,-277,-361,-282,-278,-274,-275,-290,-298,-300,-369,-300,-292,-290,-373,-309,-375,-299,-298,-301,-310,-302,-297,-370,-383,-302,-316,-321,-311,-315,-299,-321,-308,-392,-306,-322,-330,-312,-397,-326,-334,-317,-401,-330,-338,-324,-325,-337,-329,-339,-341,-398,-411,-347,-335,-346,-415,-334,-352,-350,-346,-341,-338,-422,-334,-345,-340,-344,-427,-345,-357,-357,-351,-432,-365,-361,-353,-367,-370,-354,-363,-351,-427,-464,-441,-397,-373,-434,-447,-376,-380,-374,-375,-373,-452,-454,-398,-377,-372,-458,-376,-388,-382,-377,-387,-396,-465,-400,-398,-468,-404,-404,-395,-403,-473,-390,-396,-476,-406,-409,-395,-480,-408,-404,-483,-418,-396,-486,-403,-399,-409,-417,-413,-421,-493,37,-5,73,71,-8,75,62,58,-12,62,55,74,64,48,50,-19,45,63,-22,61,48,44,-26,50,37,44,48,-31,33,40,48,41,43,30,37,-25,-38,-63,0,0,109,7,21101,0,0,-2,22208,-2,-5,-1,1205,-1,1169,22202,-2,-4,1,22201,1,-6,1,21202,-2,1,2,21102,1162,1,0,2105,1,-3,21201,-2,1,-2,1106,0,1136,109,-7,2106,0,0,109,6,2101,0,-5,1182,20101,0,0,-2,21102,0,1,-3,21201,-5,1,-5,22208,-3,-2,-1,1205,-1,1229,2201,-5,-3,1205,20101,0,0,1,22102,1,-3,2,21202,-2,1,3,21102,1,1222,0,2105,1,-4,21201,-3,1,-3,1105,1,1192,109,-6,2106,0,0,109,2,21202,-1,1,1,21101,1256,0,2,21102,1251,1,0,1106,0,1174,109,-2,2105,1,0,109,5,22201,-4,-3,-1,22201,-2,-1,-1,204,-1,109,-5,2106,0,0,109,3,1202,-2,1,1280,1006,0,1303,104,45,104,32,1201,-1,66,1291,21002,0,1,1,21101,1301,0,0,1105,1,1234,104,10,109,-3,2105,1,0,0,0,109,2,2101,0,-1,1309,1102,1,0,1308,21102,1,4601,1,21102,13,1,2,21101,4,0,3,21102,1,1353,4,21101,1343,0,0,1105,1,1130,20102,1,1308,-1,109,-2,2106,0,0,63,109,3,1201,-2,0,1360,20008,0,1309,-1,1206,-1,1419,1005,1308,1398,1102,1,1,1308,21008,1309,-1,-1,1206,-1,1387,21102,106,1,1,1106,0,1391,21101,0,92,1,21102,1,1398,0,1106,0,1234,104,45,104,32,1201,-2,1,1407,21002,0,1,1,21102,1417,1,0,1105,1,1234,104,10,109,-3,2105,1,0,109,3,1202,-2,1,1128,21102,1,34,1,21101,0,1441,0,1106,0,1234,1001,1128,0,1447,20101,0,0,1,21102,1,1456,0,1105,1,1234,21102,1,41,1,21101,1467,0,0,1105,1,1234,1001,1128,1,1472,21002,0,1,1,21101,1482,0,0,1105,1,1234,21102,46,1,1,21102,1493,1,0,1105,1,1234,21001,1128,3,1,21102,4,1,2,21102,1,1,3,21102,1,1273,4,21101,1516,0,0,1106,0,1130,21001,1128,0,1,21102,1,1527,0,1105,1,1310,1001,1128,2,1532,21002,0,1,-1,1206,-1,1545,21101,0,1545,0,2105,1,-1,109,-3,2106,0,0,109,0,99,109,2,1102,1,0,1550,21101,0,4601,1,21102,13,1,2,21101,4,0,3,21101,1664,0,4,21102,1,1582,0,1105,1,1130,2,2486,1352,1551,1102,0,1,1552,21001,1550,0,1,21102,1,33,2,21101,0,1702,3,21102,1,1609,0,1106,0,2722,21007,1552,0,-1,1205,-1,1630,20107,0,1552,-1,1205,-1,1637,21102,1,1630,0,1106,0,1752,21101,0,548,1,1106,0,1641,21101,687,0,1,21101,0,1648,0,1105,1,1234,21101,0,4457,1,21101,1659,0,0,1106,0,1424,109,-2,2105,1,0,109,4,21202,-2,-1,-2,2102,1,-3,1675,21008,0,-1,-1,1206,-1,1697,1201,-3,2,1687,20101,-27,0,-3,22201,-3,-2,-3,2001,1550,-3,1550,109,-4,2105,1,0,109,5,21008,1552,0,-1,1206,-1,1747,1201,-3,1901,1717,20101,0,0,-2,1205,-4,1736,20207,-2,1551,-1,1205,-1,1747,1102,-1,1,1552,1105,1,1747,22007,1551,-2,-1,1205,-1,1747,1102,1,1,1552,109,-5,2105,1,0,109,1,21101,826,0,1,21102,1765,1,0,1105,1,1234,21002,1550,1,1,21102,1776,1,0,1105,1,2863,21102,1090,1,1,21102,1787,1,0,1106,0,1234,99,1106,0,1787,109,-1,2106,0,0,109,1,21101,512,0,1,21101,0,1809,0,1106,0,1234,99,1105,1,1809,109,-1,2105,1,0,109,1,1102,1,1,1129,109,-1,2106,0,0,109,1,21102,1,377,1,21101,0,1842,0,1105,1,1234,1106,0,1831,109,-1,2106,0,0,109,1,21101,407,0,1,21101,1863,0,0,1105,1,1234,99,1106,0,1863,109,-1,2106,0,0,109,1,21102,1,452,1,21101,1885,0,0,1106,0,1234,99,1106,0,1885,109,-1,2105,1,0,1941,1947,1953,1958,1965,1972,1978,4083,3936,4362,4458,4463,4254,3769,4145,4116,3848,4384,3957,4371,4258,3951,4063,3935,4053,4163,4259,3817,4062,4500,3970,4331,4022,3969,4163,4483,4089,3810,4092,4196,2281,2468,2418,2450,2487,2125,2505,5,95,108,104,104,23,5,96,91,108,108,1,4,101,105,112,3,6,104,104,106,107,94,-1,6,109,104,109,107,94,-1,5,111,91,100,93,23,5,114,95,108,108,1,109,3,21102,1993,1,0,1106,0,2634,1006,1129,2010,21101,0,316,1,21101,0,2007,0,1106,0,1234,1106,0,2076,21101,0,0,-1,1201,-1,1894,2019,21001,0,0,1,21102,0,1,2,21102,1,0,3,21101,0,2037,0,1106,0,2525,1206,1,2054,1201,-1,1934,2050,21102,2051,1,0,106,0,0,1105,1,2076,21201,-1,1,-1,21207,-1,7,-2,1205,-2,2014,21101,0,177,1,21102,1,2076,0,1105,1,1234,109,-3,2105,1,0,109,3,2001,1128,-2,2088,21002,0,1,-1,1205,-1,2108,21101,201,0,1,21101,2105,0,0,1105,1,1234,1106,0,2119,22101,0,-1,1,21101,2119,0,0,1106,0,1424,109,-3,2105,1,0,0,109,1,1101,0,0,2124,21101,0,4601,1,21101,0,13,2,21101,0,4,3,21102,2173,1,4,21102,2154,1,0,1106,0,1130,1005,2124,2168,21102,226,1,1,21102,2168,1,0,1106,0,1234,109,-1,2106,0,0,109,3,1005,2124,2275,1201,-2,0,2183,20008,0,1128,-1,1206,-1,2275,1201,-2,1,2195,20102,1,0,-1,21202,-1,1,1,21102,5,1,2,21102,1,1,3,21102,2216,1,0,1106,0,2525,1206,1,2275,21102,1,258,1,21101,2230,0,0,1105,1,1234,21202,-1,1,1,21101,0,2241,0,1106,0,1234,104,46,104,10,1101,1,0,2124,1201,-2,0,2256,1101,0,-1,0,1201,-2,3,2262,21002,0,1,-1,1206,-1,2275,21101,2275,0,0,2105,1,-1,109,-3,2106,0,0,0,109,1,1101,0,0,2280,21101,4601,0,1,21101,0,13,2,21102,1,4,3,21102,1,2329,4,21102,1,2310,0,1106,0,1130,1005,2280,2324,21102,1,273,1,21102,1,2324,0,1105,1,1234,109,-1,2105,1,0,109,3,1005,2280,2413,1201,-2,0,2339,21008,0,-1,-1,1206,-1,2413,1201,-2,1,2351,20102,1,0,-1,22101,0,-1,1,21102,5,1,2,21101,1,0,3,21102,2372,1,0,1105,1,2525,1206,1,2413,21102,301,1,1,21102,2386,1,0,1106,0,1234,22102,1,-1,1,21102,2397,1,0,1106,0,1234,104,46,104,10,1102,1,1,2280,1201,-2,0,2412,101,0,1128,0,109,-3,2106,0,0,109,1,21101,0,-1,1,21102,1,2431,0,1105,1,1310,1205,1,2445,21102,1,133,1,21101,0,2445,0,1106,0,1234,109,-1,2106,0,0,109,1,21102,3,1,1,21101,2463,0,0,1106,0,2081,109,-1,2106,0,0,109,1,21101,4,0,1,21102,1,2481,0,1105,1,2081,109,-1,2106,0,0,70,109,1,21102,5,1,1,21102,2500,1,0,1105,1,2081,109,-1,2105,1,0,109,1,21102,6,1,1,21102,2518,1,0,1105,1,2081,109,-1,2106,0,0,0,0,109,5,2102,1,-3,2523,1101,0,1,2524,21202,-4,1,1,21101,0,2585,2,21101,2550,0,0,1105,1,1174,1206,-2,2576,2101,0,-4,2558,2001,0,-3,2566,101,3094,2566,2566,21008,0,-1,-1,1205,-1,2576,1102,0,1,2524,21001,2524,0,-4,109,-5,2105,1,0,109,5,22201,-4,-3,-4,22201,-4,-2,-4,21208,-4,10,-1,1206,-1,2606,21102,-1,1,-4,201,-3,2523,2615,1001,2615,3094,2615,21002,0,1,-1,22208,-4,-1,-1,1205,-1,2629,1101,0,0,2524,109,-5,2106,0,0,109,4,21101,0,3094,1,21102,30,1,2,21101,1,0,3,21102,1,2706,4,21102,1,2659,0,1105,1,1130,21101,0,0,-3,203,-2,21208,-2,10,-1,1205,-1,2701,21207,-2,0,-1,1205,-1,2663,21207,-3,29,-1,1206,-1,2663,2101,3094,-3,2693,2102,1,-2,0,21201,-3,1,-3,1106,0,2663,109,-4,2105,1,0,109,2,1201,-1,0,2715,1102,-1,1,0,109,-2,2105,1,0,0,109,5,2102,1,-2,2721,21207,-4,0,-1,1206,-1,2739,21102,1,0,-4,21202,-4,1,1,21202,-3,1,2,21102,1,1,3,21101,0,2758,0,1105,1,2763,109,-5,2106,0,0,109,6,21207,-4,1,-1,1206,-1,2786,22207,-5,-3,-1,1206,-1,2786,21201,-5,0,-5,1105,1,2858,22101,0,-5,1,21201,-4,-1,2,21202,-3,2,3,21101,0,2805,0,1105,1,2763,21202,1,1,-5,21101,0,1,-2,22207,-5,-3,-1,1206,-1,2824,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2850,22102,1,-2,1,21201,-4,-1,2,21101,0,2850,0,105,1,2721,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2105,1,0,109,3,21208,-2,0,-1,1205,-1,2902,21207,-2,0,-1,1205,-1,2882,1105,1,2888,104,45,21202,-2,-1,-2,21201,-2,0,1,21102,2899,1,0,1106,0,2909,1106,0,2904,104,48,109,-3,2106,0,0,109,4,22102,1,-3,1,21101,10,0,2,21101,0,2926,0,1105,1,3010,21201,1,0,-2,21201,2,0,-1,1206,-2,2948,22101,0,-2,1,21101,0,2948,0,1106,0,2909,22101,48,-1,-1,204,-1,109,-4,2105,1,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21101,0,0,-4,21101,0,0,-3,21102,1,51,-2,21201,-2,-1,-2,1201,-2,2959,3034,20101,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,3059,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,3078,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,3024,21202,-4,1,-7,21202,-3,1,-6,109,-8,2106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3131,3143,0,3252,3527,0,0,11,61,105,95,94,17,50,97,83,78,79,83,108,-19,2,7,-79,-9,-2,2,-83,-11,-7,-86,-3,-16,-7,-11,-6,-21,-21,-94,-30,-96,-25,-19,-23,-31,-101,-29,-25,-104,-21,-34,-38,-108,-39,-34,-32,-33,-31,-114,-43,-47,-35,-49,-105,-120,-69,-43,-123,-49,-56,-57,-47,-128,-40,-51,-46,-50,-133,-51,-63,-63,-57,-138,-69,-58,-62,-65,-143,-79,-69,-63,-68,-148,-79,-68,-82,-83,-63,-81,-77,-85,-145,-158,-75,-88,-92,-162,-91,-85,-89,-97,-167,-96,-104,-87,-171,-106,-104,-105,-97,-176,-94,-109,-114,-104,-112,-114,-169,3259,3267,0,3344,0,3124,0,7,65,89,99,98,108,85,108,76,8,27,27,36,-48,16,32,18,13,-53,18,10,27,-57,8,10,9,17,-62,16,16,19,7,10,5,21,-1,-3,-72,-3,5,7,-76,6,1,-2,-11,3,-10,-10,-6,-14,-59,-87,1,-10,-5,-84,-10,-24,-94,-21,-11,-14,-14,-99,-22,-22,-18,-103,-23,-20,-33,-23,-39,-109,-27,-26,-30,-44,-114,-28,-44,-52,-34,-105,3351,3359,0,0,3408,3252,0,7,76,108,102,104,86,91,88,48,36,55,51,-19,46,58,66,46,59,-25,48,58,55,55,-30,36,47,45,50,30,37,41,-38,38,39,41,27,-43,22,34,42,22,35,-35,-50,-51,-2,16,13,30,26,26,15,27,9,15,27,-49,3415,3423,0,0,3458,4392,3344,7,76,108,88,88,97,89,102,34,48,66,69,73,62,62,61,73,3,72,61,77,55,53,-2,-17,34,53,49,68,-15,59,45,-25,39,49,48,-29,39,46,48,51,55,-21,3465,3486,0,3584,0,4053,3408,20,51,84,80,93,8,62,88,70,84,83,75,79,71,-1,33,66,74,79,63,75,40,32,70,77,-11,57,63,69,54,-16,51,61,-19,69,58,63,-23,63,57,39,53,-28,51,52,38,51,36,44,49,47,-37,41,39,-40,43,30,26,-44,26,33,-16,3534,3548,0,0,0,0,3124,13,54,100,86,103,15,63,98,77,93,94,78,90,90,35,49,68,64,-6,59,61,59,73,-11,53,69,55,-15,49,59,58,-19,64,58,57,-23,59,52,39,49,48,-29,40,48,50,-33,55,44,49,-23,3591,3600,0,0,3732,3458,3673,8,75,96,89,96,20,53,83,106,72,11,44,38,37,35,37,38,36,-48,17,29,33,20,-53,-4,14,12,-44,-12,20,23,8,6,-63,-14,4,7,11,0,0,-1,11,-72,4,-5,-7,-3,-10,-5,-1,-11,-81,-17,-5,-16,-85,-4,-18,-17,-4,-14,-26,-10,-93,-12,-26,-23,-19,-30,-30,-31,-19,-102,-26,-35,-37,-33,-40,-35,-31,-41,-97,3680,3703,0,3901,3584,0,4241,22,50,88,92,7,41,77,83,70,81,77,65,83,67,-3,34,74,79,71,76,56,63,67,28,55,82,79,70,72,78,85,9,-4,68,78,0,75,-9,73,73,61,63,62,-15,71,62,64,56,53,57,49,-9,3739,3748,0,3828,0,3981,3584,8,59,102,104,103,93,87,97,99,79,5,24,20,-50,26,17,31,11,21,-56,30,7,17,16,22,-62,2,14,3,-66,17,4,0,-70,6,-3,11,-9,1,-76,-7,-2,0,-1,1,-82,-18,-2,-16,-86,-4,-12,-16,-19,-19,-8,-17,-5,-95,-28,-24,-28,-29,-31,-19,-33,-25,-20,-105,-39,-28,-32,-30,-28,-28,-98,-113,-67,-33,-116,-52,-36,-50,-120,-37,-50,-54,-35,-94,3835,3844,0,4166,0,3732,0,8,64,102,98,100,88,88,85,92,56,27,54,51,42,51,49,39,-31,51,36,35,42,47,-37,46,40,-40,31,23,43,25,-45,30,22,22,35,-50,22,32,-53,25,23,-56,27,14,10,-60,-22,11,2,14,19,-66,-28,14,4,-2,-71,11,-4,10,9,-3,1,-7,-65,3908,3920,0,0,0,3673,0,11,68,86,102,87,99,102,80,98,92,94,100,60,24,43,39,51,37,-33,31,47,33,-37,27,-39,30,28,45,-43,40,24,30,22,35,18,29,29,17,30,-27,-55,28,15,11,30,-53,21,7,-63,1,11,10,-67,-2,10,6,13,-3,-5,-74,-7,3,10,0,-67,-80,3,-10,-4,1,-14,-14,-73,3988,3997,0,3732,4095,0,0,8,72,88,105,104,85,90,87,100,55,29,48,44,63,-20,54,40,-30,34,-32,43,39,49,48,39,31,-39,44,46,31,40,40,44,-46,18,30,19,-50,32,32,12,28,29,17,21,13,-59,24,18,-62,13,15,14,9,-67,-3,7,6,-71,-7,3,-1,0,-7,-63,4060,4068,0,3458,0,0,0,7,68,97,107,89,93,89,97,26,43,91,73,85,91,85,72,72,76,68,3,78,-6,63,74,60,59,79,57,0,54,67,57,52,50,-5,4102,4114,0,0,0,4337,3981,11,58,98,90,91,95,85,84,96,86,90,82,51,38,59,64,-22,60,45,44,-26,38,-28,58,42,42,52,36,32,44,29,45,30,-39,47,32,42,29,-44,35,30,18,30,34,-50,19,27,29,-54,-4,24,25,15,19,11,7,20,16,9,3,-66,19,-50,-55,4173,4185,0,0,0,3828,0,11,72,87,92,87,95,83,84,14,57,77,77,55,34,55,60,-26,56,41,40,-30,38,54,40,34,34,42,30,31,-39,32,28,40,26,-44,34,24,-47,32,33,29,33,27,31,35,25,13,-57,22,20,16,28,15,6,18,-65,2,2,15,4,1,7,-72,14,5,7,-1,-63,4248,4259,0,0,3673,0,0,10,68,86,106,92,89,82,100,88,93,91,77,6,38,18,36,36,33,-25,-52,-2,30,27,9,21,10,10,8,-47,-62,-15,12,4,-1,16,1,-69,13,14,8,7,2,14,-76,0,-9,-14,3,4,0,-14,-7,-16,-8,-3,-5,-89,-20,-9,-13,-16,-94,-25,-23,-27,-14,-10,-100,-18,-18,-38,-22,-22,-106,-23,-29,-109,-28,-42,-45,-48,-38,-42,-50,-35,-53,-35,-51,-107,4344,4351,0,4095,0,0,0,6,59,107,91,88,90,90,40,38,70,68,58,-12,66,56,-15,68,55,51,-19,47,44,44,50,54,44,58,56,-28,54,39,38,45,-33,50,44,-36,35,27,47,29,-41,38,36,43,24,36,-33,4399,4422,0,3408,0,4457,0,22,65,74,90,87,6,41,86,76,88,70,0,44,63,70,74,79,63,71,57,69,57,58,34,39,81,-4,60,74,73,61,56,72,72,-12,71,65,-15,50,52,-18,68,59,61,53,50,54,46,-26,51,51,53,47,34,44,43,55,-21,4464,4484,0,4392,4556,0,0,19,64,81,78,95,91,81,91,95,5,39,75,71,68,75,79,77,70,74,79,71,2,38,-41,42,29,25,-45,32,22,40,35,-50,31,27,26,23,-43,-56,8,-58,21,22,8,21,20,21,17,3,-54,15,0,8,12,1,11,-1,11,-7,-77,-8,-3,-1,-2,0,-83,3,-12,-10,-11,-88,-3,-21,-9,-19,-23,-5,-95,-7,-18,-13,-17,-100,-28,-34,-34,-26,-21,-33,-23,-19,-95,4563,4588,1553,0,0,0,4457,24,56,89,75,88,87,88,84,70,13,50,67,75,79,68,78,66,78,60,-10,27,64,66,65,67,12,53,97,83,93,105,105,87,91,83,25,24,23,3981,4653,16777243,0,3344,4659,32796,0,4166,4672,67108893,0,3252,4683,46,0,3673,4699,31,1818,3527,4719,536870944,0,3408,4727,268435489,0,3584,4741,34,1829,3828,4755,35,1850,4241,4767,36,1796,4053,4778,1061,0,4337,4782,38,1872,3901,4790,41,0,5,110,98,94,100,99,12,95,95,87,90,94,15,80,92,96,95,86,78,10,106,86,97,85,97,102,98,88,92,82,15,104,85,80,98,85,81,93,10,86,73,74,78,78,82,72,19,84,85,76,88,93,8,76,82,74,71,87,84,80,77,64,69,75,65,79,7,90,102,107,91,99,98,84,13,102,98,96,95,91,14,92,82,11,77,74,92,29,13,92,96,87,89,93,87,97,81,11,86,88,87,87,11,98,99,95,102,86,94,15,90,78,98,76,10,91,104,87,84,98,86,16,95,93,81,3,106,113,98,7,105,96,102,106,100,98,102,4,95,92,101,94 diff --git a/2019/inputs/day_3.txt b/2019/inputs/day_3.txt new file mode 100644 index 0000000..504e9fe --- /dev/null +++ b/2019/inputs/day_3.txt @@ -0,0 +1,2 @@ +R995,D882,R144,U180,L638,U282,L907,D326,R731,D117,R323,U529,R330,U252,R73,U173,R345,U552,R230,U682,R861,U640,L930,U590,L851,D249,R669,D878,R951,D545,L690,U392,R609,D841,R273,D465,R546,U858,L518,U567,L474,D249,L463,D390,L443,U392,L196,U418,R433,U651,R520,D450,R763,U714,R495,D716,L219,D289,L451,D594,R874,U451,R406,U662,R261,D242,R821,D951,R808,D862,L871,U133,R841,D465,R710,U300,R879,D497,R85,U173,R941,U953,R705,U972,R260,D315,L632,U182,L26,D586,R438,U275,L588,U956,L550,D576,R738,U974,R648,D880,R595,D510,L789,U455,R627,U709,R7,D486,L184,U999,L404,U329,L852,D154,L232,U398,L587,U881,R938,D40,L657,D164,R45,D917,R106,U698,L824,D426,R879,U700,R847,D891,L948,U625,R663,D814,R217,U30,R610,D781,L415,D435,L904,U815,R152,U587,R287,U141,R866,D636,L290,D114,L751,D660,R6,U383,L263,U799,R330,U96,L6,U542,L449,D361,R486,U278,L990,U329,L519,U605,R501,D559,R916,U198,L499,D174,R513,U396,L473,D565,R337,D770,R211,D10,L591,D920,R367,D748,L330,U249,L307,D645,R661,U266,R234,D403,L513,U443,L989,D1,L674,D210,L537,D872,L607,D961,R894,U632,L195,U744,L426,U531,R337,D821,R113,U436,L700,U779,R555,U891,R268,D30,R958,U411,R904,U24,R760,D958,R231,U229,L561,D134,L382,D961,L237,U676,L223,U324,R663,D186,R833,U188,R419,D349,L721,U152,L912,U490,R10,D995,L98,U47,R140,D815,R826,U730,R808,U256,R479,D322,L504,D891,L413,D848,L732,U375,L307,U7,R682,U270,L495,D248,R691,D945,L70,U220,R635,D159,R269,D15,L161,U214,R814,D3,R354,D632,R469,D36,R85,U215,L243,D183,R140,U179,R812,U180,L905,U136,L34,D937,L875 +L999,D22,L292,U843,R390,U678,R688,D492,L489,U488,R305,U951,L636,U725,R402,U84,L676,U171,L874,D201,R64,D743,R372,U519,R221,U986,L393,D793,R72,D184,L553,D137,L187,U487,L757,U880,L535,U887,R481,U236,L382,D195,L388,D90,R125,U414,R512,D382,R972,U935,L172,D1,R957,U593,L151,D158,R396,D42,L30,D178,R947,U977,R67,D406,R744,D64,L677,U23,R792,U864,R259,U315,R314,U17,L37,D658,L642,U135,R624,U601,L417,D949,R203,D122,R76,D493,L569,U274,L330,U933,R815,D30,L630,D43,R86,U926,L661,D491,L541,D96,R868,D565,R664,D935,L336,D152,R63,U110,L782,U14,R172,D945,L732,D870,R404,U767,L907,D558,R748,U591,R461,D153,L635,D457,R241,U478,L237,U218,R393,U468,L182,D745,L388,D360,L222,D642,L151,U560,R437,D326,R852,U525,R717,U929,L470,U621,R421,U408,L540,D176,L69,U753,L200,U251,R742,U628,R534,U542,R85,D71,R283,U905,L418,D755,L593,U335,L114,D684,L576,D645,R652,D49,R86,D991,L838,D309,L73,U847,L418,U675,R991,U463,R314,D618,L433,U173,R869,D115,L18,U233,R541,U516,L570,U340,R264,D442,L259,U276,R433,D348,R524,D353,R336,D883,R580,U157,R79,D27,L134,D161,L748,D278,R322,D581,R654,D156,L930,D293,L156,U311,R807,D618,R408,U719,R366,D632,R307,D565,R478,D620,R988,D821,R365,D581,L946,D138,L943,U69,R620,U208,L407,U188,L122,U353,L751,U565,R849,D874,R668,D794,L140,D474,R289,D773,R344,D220,L55,D385,L394,U208,R305,U736,L896,D376,R331,D855,L466,U516,L741,U124,L825,U467,L525,D911,R76,U220,L610,U102,L261,D891,L585,U397,L152,U753,R822,D252,R106,U145,L7,U524,R343,U352,L357,D399,L446,D140,L723,U46,R687,D409,R884 diff --git a/2019/inputs/day_4.txt b/2019/inputs/day_4.txt new file mode 100644 index 0000000..f62320b --- /dev/null +++ b/2019/inputs/day_4.txt @@ -0,0 +1,2 @@ +138241 +674034 diff --git a/2019/inputs/day_5.txt b/2019/inputs/day_5.txt new file mode 100644 index 0000000..f8c2724 --- /dev/null +++ b/2019/inputs/day_5.txt @@ -0,0 +1 @@ +3,225,1,225,6,6,1100,1,238,225,104,0,1102,57,23,224,101,-1311,224,224,4,224,1002,223,8,223,101,6,224,224,1,223,224,223,1102,57,67,225,102,67,150,224,1001,224,-2613,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,2,179,213,224,1001,224,-469,224,4,224,102,8,223,223,101,7,224,224,1,223,224,223,1001,188,27,224,101,-119,224,224,4,224,1002,223,8,223,1001,224,7,224,1,223,224,223,1,184,218,224,1001,224,-155,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1101,21,80,224,1001,224,-101,224,4,224,102,8,223,223,1001,224,1,224,1,224,223,223,1101,67,39,225,1101,89,68,225,101,69,35,224,1001,224,-126,224,4,224,1002,223,8,223,1001,224,1,224,1,224,223,223,1102,7,52,225,1102,18,90,225,1101,65,92,225,1002,153,78,224,101,-6942,224,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,1101,67,83,225,1102,31,65,225,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1007,226,226,224,102,2,223,223,1005,224,329,1001,223,1,223,108,677,226,224,1002,223,2,223,1005,224,344,1001,223,1,223,1007,677,677,224,1002,223,2,223,1005,224,359,1001,223,1,223,1107,677,226,224,102,2,223,223,1006,224,374,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,389,101,1,223,223,8,677,677,224,102,2,223,223,1006,224,404,1001,223,1,223,1008,226,226,224,102,2,223,223,1006,224,419,1001,223,1,223,107,677,226,224,102,2,223,223,1006,224,434,101,1,223,223,7,226,226,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,226,226,224,1002,223,2,223,1006,224,464,1001,223,1,223,1107,226,677,224,1002,223,2,223,1005,224,479,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,494,1001,223,1,223,1108,226,677,224,1002,223,2,223,1006,224,509,101,1,223,223,1008,677,677,224,1002,223,2,223,1006,224,524,1001,223,1,223,1008,677,226,224,102,2,223,223,1006,224,539,1001,223,1,223,1108,677,677,224,102,2,223,223,1005,224,554,101,1,223,223,108,677,677,224,102,2,223,223,1006,224,569,101,1,223,223,1108,677,226,224,102,2,223,223,1005,224,584,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,599,1001,223,1,223,1007,226,677,224,102,2,223,223,1005,224,614,1001,223,1,223,7,226,677,224,102,2,223,223,1006,224,629,1001,223,1,223,107,226,226,224,102,2,223,223,1005,224,644,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,659,101,1,223,223,107,677,677,224,1002,223,2,223,1005,224,674,1001,223,1,223,4,223,99,226 diff --git a/2019/inputs/day_6.txt b/2019/inputs/day_6.txt new file mode 100644 index 0000000..49d849c --- /dev/null +++ b/2019/inputs/day_6.txt @@ -0,0 +1,2306 @@ +21X)BWV +YZJ)YLQ +FQS)PZW +R64)71F +ZH4)QVZ +LWB)H4Q +4HQ)PVJ +TZ5)VBV +LF1)FKZ +GKS)BGN +45B)2NS +14W)2JY +1XY)FJ8 +ZRC)WR9 +GCL)6PB +LP4)GQ8 +26V)HTK +3M8)1GJ +47Q)JYK +WDB)N2R +KH8)TGY +LFX)N2X +VSZ)7PC +M6W)4WL +HH9)8PC +L59)8Y8 +Q49)LWH +CJ5)XDG +K51)FGH +H31)2RJ +39M)Y4M +12C)VLF +PZW)7DW +MP2)19Q +R76)CHH +N6J)KBW +WR9)W25 +T99)ZF1 +1TS)8SM +8WW)YX7 +PW6)B2J +7KX)YM5 +HM6)GVX +DNB)2YP +6WC)2LW +BG5)SB6 +KK1)JTF +YDT)244 +GGQ)2DJ +GCP)Q8H +S1Y)J69 +LBV)DYG +ZKN)JBS +8XY)Y8Z +XMH)NHD +XVM)2LX +SYP)BC8 +PXH)YYG +F29)G9Y +BYX)4QS +8MY)S1D +N2Y)BZK +FRC)72W +S2K)YH5 +7JF)K65 +DJ9)K4L +P26)WXT +DW9)1DJ +NP4)3SB +XS7)CDL +6XH)4ZT +2DJ)GCP +2K4)VV1 +Q6P)NNN +HQW)ZR9 +9G2)FNB +H9N)5ZJ +13Z)GKD +9MW)37Y +VDY)BG9 +BL3)12C +LNN)JST +Z3V)T39 +XS3)WYG +8J5)QFQ +7DW)DXY +JMV)DM4 +VL3)V7Q +GZC)ZHV +3N6)R2H +FQ6)7LG +SR9)D66 +1M8)K2L +24N)M94 +JST)WM9 +7SB)99Q +58J)YN7 +WWH)5KS +C39)X9J +58S)KBP +TVF)VNG +TKC)Y34 +KKP)4S6 +XSP)939 +N6J)DZP +JXP)N6R +KNJ)7FS +N3V)LMJ +JVF)R94 +21C)R4Z +NYK)5GN +GVJ)Q6C +R69)NRS +GLS)C7D +T4J)46R +5GB)51S +9WD)7PN +HHX)KK2 +H2P)ZML +DWD)Q9F +FKZ)LC3 +Q9F)M8N +CRZ)LM1 +6DP)YML +NSR)L2X +PMX)Q7K +37R)1GF +L4G)P4W +17N)X6D +JTF)89B +JGJ)DVJ +VF9)GMW +NHD)DJ3 +TRY)F6S +J11)BVW +95X)XB5 +3XD)HPM +7BB)1LW +FJ8)TV4 +JV3)M9W +T7L)6SS +R48)LSB +F2P)9D2 +PTY)QBY +KXM)6G1 +N1H)Q2R +P27)SR9 +1S2)N3G +V7Q)642 +891)TW7 +B9Y)BRL +GW4)3XZ +QWM)G46 +WVK)S6N +N82)317 +8PG)S21 +NT3)1VX +QB5)Y3H +PTT)639 +G8M)WM8 +B36)LX9 +M9M)4P3 +3F9)Q3R +DND)TJL +VQB)6N3 +PJT)JTK +BBN)T4L +LYP)M3V +T9R)HH9 +XBR)3X5 +MX3)SWF +SF1)MXT +X67)6DQ +82Z)FQ4 +L64)FNG +CDG)5D9 +JKZ)XZ5 +MH1)1KD +5NW)ZH4 +P3T)76Z +2M4)CKW +54L)8P7 +JSH)5H5 +LGR)P2V +QNV)SJ7 +KPS)XMQ +F2H)49M +8NJ)KKP +XZ1)LRZ +RVK)J5Z +QT9)NGQ +1TK)P7X +39M)595 +DN9)HKY +HK1)ZRH +SH1)JV5 +B25)GQ6 +QZC)WYC +6CJ)F5D +5R1)HQ7 +FNT)P4J +4R6)P49 +LG4)QT9 +GWH)RY1 +1FX)ZK8 +HK4)G2N +4WL)GPR +SQT)KK1 +RT4)FCN +NRF)P84 +DQW)4L4 +52N)T4J +69D)2FV +RMV)J7N +S9J)1WM +B88)9GT +5M7)GXN +3XF)6FX +FL9)8VZ +X88)JZR +ZVZ)8J2 +Q83)94V +82Y)HT7 +7Y7)7X3 +KNK)R1W +469)PMG +D9Z)GD1 +Z62)WR1 +YDF)6B6 +5KS)6GW +57T)ML7 +GXC)R89 +S2N)99C +JFH)RP9 +KPH)R26 +DZX)93P +CWT)C2H +VKN)5M7 +VNG)SH1 +G2N)F6Q +NFV)FK3 +R65)TQL +Z6T)4NG +RQN)KPR +972)9TB +KZ1)6TY +8K2)HKL +KHJ)H1W +6N3)XTR +25Q)T49 +8HF)K9M +GQX)PHP +5ZJ)9S7 +C7D)VMJ +JXV)SJD +J17)64C +5XN)WN7 +PH9)WQH +43T)Q9V +Z5F)NZ8 +VHQ)D95 +244)7KX +6N7)JPH +HC8)HND +ZF1)39F +24X)ZPF +BWV)HQW +R3N)5R1 +QB9)6XY +KHW)KFZ +S2V)DRQ +S21)1RQ +C9V)TSD +Q1Y)LC2 +93Y)W5C +8ST)T4P +R5Z)CL4 +424)WNZ +R7M)5JS +4R6)H97 +ZXZ)S62 +FRH)SBJ +ZK8)N82 +6FX)MTK +Z5M)BRQ +YYP)FX8 +RZJ)DRK +V8G)TKQ +5L9)J1G +RZG)69H +R9G)X79 +WFS)ZJQ +4P8)GXC +TYW)S54 +R2H)QH7 +6HX)F2H +BBD)DC5 +DDB)6WC +2G3)4JN +FKC)K7V +XTK)8BD +Z7X)QGY +8CG)3F9 +F39)MM9 +F1L)1R7 +ZVH)JDC +BVW)PXM +PRV)BF7 +FX8)1XR +FB2)XN6 +R9L)Z1V +YDT)H52 +6Z5)XZ1 +QD2)Z7Y +TLS)6T3 +54C)DL7 +KPR)4TY +19N)415 +1QG)GNN +S6N)4MK +4L8)LD2 +5Z7)PRY +5C4)2MC +94B)DY3 +CVK)GTS +7N7)P27 +5MW)GGH +2HQ)JYL +L9J)HLP +5Y4)NGN +2BZ)GWN +HD8)CZS +HQ7)M9D +DC5)RK6 +66W)2VT +3D4)GHZ +T49)VTP +PL4)ZS9 +SJ7)TRC +NKT)G5Y +K1G)3GN +37V)4LG +KWL)VDZ +7XF)1P8 +64C)FX4 +DY4)J3F +RV8)8KF +DRQ)KQ7 +HND)2N7 +HQS)HMW +J24)9VX +7DK)3PM +467)VBK +Q6C)TZC +SZY)9TC +BMM)4S4 +HFH)2S6 +K5K)4QP +N6W)RZG +TKQ)489 +4R1)F22 +J1G)YDF +FVW)9WD +CV7)TMC +R6K)H31 +GDL)X14 +H1B)NKT +XTR)PL6 +BSC)SM7 +MLT)S7B +22S)R7T +X8Y)4WX +NR9)NK9 +FSM)J3S +WHF)VSG +ZBG)Q3D +RMY)7KM +XBX)1M8 +MHY)1C2 +GSS)X9G +86F)Y4W +VL6)6H9 +1VH)L3B +SF8)CDG +GTK)45F +49M)NLL +FN6)PN3 +KSC)R3Z +6TN)3QN +FNG)742 +X45)WWH +SF5)2WH +JSJ)B1H +95L)M8F +L59)C4Y +93P)M89 +K1C)6ZZ +21T)8M6 +X9M)7NX +WPK)LNG +393)F6N +M4L)JXP +VKN)X88 +NFK)ZVZ +LKV)C2V +SWX)TM8 +V7F)8ZN +3RW)FD8 +9SM)H27 +TP3)1YB +6MG)D8X +8S7)345 +9SV)X67 +25P)JDD +BFX)TNG +36J)VBH +HN7)WVK +ZR3)3NR +M3V)GPY +52M)MFV +MZB)CJ5 +MX3)XLQ +LCG)PHS +HZD)RNC +GWN)DWD +XBM)WP4 +2FV)YXW +ZTP)QD2 +R1G)JY6 +KY4)8CG +H54)RVK +5HG)WYQ +BVC)SK1 +948)P3T +SV8)5MW +V4D)YLT +69X)LNZ +BL3)Y97 +DXG)WLZ +VV1)SS3 +ZCD)VXB +X6D)XL2 +B9H)2NB +KHK)WPK +YLT)KFT +P49)CC5 +KBW)CRH +8KQ)LJ4 +8JJ)VTJ +TKM)428 +3SB)273 +GPY)R2Z +WTX)P6W +LB1)3PR +Y1R)DJM +25P)CY5 +SVB)PJM +56N)S2V +H82)8D5 +CYB)GP4 +HJ2)BSH +2J1)F1T +C4Y)PRM +TZC)PM5 +K55)NBJ +X43)LPP +WYG)3FW +WFG)N2Y +Q37)5L9 +WSF)KSH +V2H)S9J +HN2)DW9 +3LL)PFH +6X3)XVM +8XZ)991 +26L)WTX +Y97)5C5 +XXL)79Y +NK9)RR8 +L7W)83Q +8TX)45B +GMJ)1H4 +ZRW)58J +36X)PRS +8B2)HTL +8JZ)L94 +PRY)QTW +PL4)X8Y +89N)1RJ +DFJ)62K +5QZ)CN3 +RYQ)SL6 +1H4)PGZ +B1H)J88 +JCC)111 +V6W)GG7 +BZK)97X +49J)WVY +1WM)21X +TCN)KSC +RRD)26V +VC6)WPS +Y5S)YJS +DVR)2J8 +LJF)839 +64D)GZC +79Y)SZY +JHT)D6J +K4K)L59 +YHB)QWM +6H9)MRR +X79)M62 +LW7)GGB +469)TRQ +14K)951 +L9Y)K51 +W7C)Y73 +XD1)CYL +1XQ)HYK +Q19)PWG +F4M)KHW +SM1)J3Q +MV1)1X9 +NMV)3SM +8ZD)L61 +VWX)6R6 +S4Z)JK4 +9GT)R13 +F66)89X +DLT)K6R +H4C)NW9 +R3D)6Z5 +MKN)M5V +H4C)22S +BFM)J2V +KQW)G8D +V61)6HG +JX4)LH3 +PHS)P68 +V9M)56X +1Q6)Y8V +319)KX2 +M8F)881 +974)KSL +LRP)XXL +M3Y)Q39 +LC3)B9H +4T8)ZRW +KYB)T7L +DXJ)72V +SRP)D3M +BRN)NGD +43S)NJ1 +KWJ)VGZ +DNY)F2J +DKW)YT1 +6B4)6N5 +GRQ)RYT +4KV)WFG +6PG)T9R +Q3T)V2P +4M5)HLG +WKZ)9ZP +XTP)JMC +PVZ)JN1 +5F2)26L +76Z)R5P +FVW)NS1 +MWS)PXD +Z7Z)8S7 +CTH)7C2 +837)48K +3SM)HYY +J2B)1TS +Y8V)BS6 +YYD)3XH +4F7)BFM +6S1)95D +4KN)JV3 +GSZ)HVF +9CP)GPZ +BFN)LB1 +N72)741 +K6R)3WF +P4J)QQW +54G)469 +36T)GJ4 +HXM)X6W +MR9)M29 +XMQ)SP9 +71F)TJR +95X)DLT +1ZX)QVK +F1L)1SY +B7X)XDB +FJW)ZCR +43X)1XH +D5H)93V +FQH)5RJ +CLW)1RG +X4Y)X9M +CRH)DWH +XWX)GWZ +36J)TKC +YFN)YJ6 +15X)MBT +6T3)NDG +8SY)4R7 +XMG)HR5 +KSZ)WKZ +PM5)3K8 +BR4)J1T +F72)GV7 +317)P1W +CV7)SPK +H53)PMX +NDG)56N +N68)ZXZ +X3W)XGJ +JRJ)S7X +MKN)DBW +8CM)953 +M2K)3XL +95K)95X +58S)4HL +D95)L9Y +FRH)KQW +NLL)C3D +X1H)FM1 +R1M)GGQ +Y8Z)W1B +KLD)G1V +6CJ)R5X +5C5)HN7 +T7M)ZXT +SZF)B5W +RPW)6TG +3VP)2W9 +X2J)RXH +DWG)C9V +9FB)524 +1PZ)8ZD +ZKZ)6S1 +L36)ZKN +F1J)2D4 +LWC)6SW +SWF)Y4V +51L)MWS +KFZ)52N +GD1)HFH +LFK)L36 +KPZ)ZQ6 +3NT)W48 +2CD)G3D +345)JXV +2LW)SWX +9ZY)XTJ +VWR)576 +STH)NHY +L4X)M4L +ZML)RN7 +RDF)7PB +7FK)3KR +GVX)DCF +1WX)DD2 +971)H6W +H6H)BPX +BWQ)Z4J +JPL)3SV +QWJ)TR8 +376)H9P +Q3D)1YS +1N2)FQ6 +2LM)53K +VSG)6DP +KNM)8B7 +S7B)YXF +YHB)JHP +Y7N)CPB +M29)3FB +J37)C8B +MK3)WHL +MRG)TQ8 +BFM)DLH +H4Q)9HF +D81)R7M +LRQ)ZKZ +C1B)413 +BKC)PW6 +GP4)6MX +C39)JSH +BW8)TL2 +71Q)3YP +415)H2V +DBH)BR4 +JJ7)J2H +G52)87N +YV2)JN3 +7PR)Z3V +999)G8M +S7Y)JRJ +G3D)88H +SR3)NTR +JY5)FC8 +MYL)B7X +K7V)HM6 +FXY)L47 +NNN)GYH +8JJ)Y5S +3G5)37V +FLP)4B2 +839)83S +H27)CV7 +X4F)RXV +S3P)WMZ +LD2)SF8 +DYG)77S +LGR)2LM +7BX)G2K +KNF)9S5 +JBS)R45 +T6C)CGH +CNV)2BZ +356)1KP +P93)54J +VGZ)31Y +GNG)HDL +RHW)222 +4T4)4T8 +WVY)M5Z +KQ7)XMG +K7F)S2N +X6Z)Z9S +XYH)WFC +7BM)J2B +H9F)LKV +WDJ)HWH +MWM)83M +YM5)7J5 +Z62)8NR +99Q)TVF +VDP)C2N +9VX)B5T +YS6)KNF +35R)ZH5 +JN5)Y4H +MSN)XSP +776)CJ4 +3FB)HXT +HZV)6HY +Q6N)HXS +MBT)FTN +3JP)YJ2 +4DC)KSD +8PG)5QZ +YSP)CNV +THM)CST +3X5)BPC +ZG9)4KY +8M6)MZ5 +FDF)XNB +H4X)N72 +ZH5)J79 +KN7)ZXV +1GP)R76 +K5R)CLZ +W8G)XVF +YJQ)HB8 +BWC)TB6 +WFH)T6C +DPB)VYF +K8N)KWJ +C2V)HMF +H93)HF3 +TR8)MFW +RJ4)F66 +BS6)FVW +QFW)5B2 +ML7)FB2 +TGY)X9Z +PRM)ZV3 +4YX)4YV +36D)N6X +XLQ)TLS +WMZ)NRF +BCM)2CV +M74)CHT +JYL)LQ4 +RSN)KXR +KNK)3Y2 +89X)BJK +C2H)4YQ +YYQ)VMB +164)11H +WYQ)WSF +1RG)DRH +GKD)LLT +H53)T2F +X2Q)F82 +B5D)5F8 +JK1)4F7 +1YB)P26 +B6F)552 +RTD)883 +ZPF)DWG +JRV)DL1 +MLQ)S1Y +TX8)5QV +NDT)2MF +HFS)61F +HD8)TCN +8BL)F2X +4MK)R6Z +WVN)RMY +GGX)JCC +GQ8)J11 +H4V)5FJ +3JD)VNC +7KS)9SM +NTR)YV2 +4LG)JK1 +3XZ)GGX +SVZ)P96 +4WG)N3V +QY7)8N9 +XMP)LKL +T4P)RLM +J7C)JJZ +7PC)Y23 +LPP)M6T +F82)9KL +9XR)VT4 +SF1)4T3 +FW6)N66 +QBY)D49 +BCM)17Y +H1W)R6K +ZVN)7QK +BRH)7JF +LKL)39C +LV1)BJS +8PC)FN6 +CHB)TBS +ZLR)3XD +8BD)BSC +NVC)9FB +Z9L)HK1 +FT3)BWL +446)S8V +LM1)D8G +KH3)Q6P +J8C)WFH +YT1)SDH +CGZ)X3V +77B)V9M +2RJ)H4V +NHY)H47 +89B)HM7 +Z1V)58S +17Y)1Q7 +J3F)891 +WDG)VSZ +PJM)21T +3YL)74D +8XJ)15N +Z2X)VHH +N6R)R93 +5QV)8XY +KSD)RYF +6DQ)X8F +Z2Q)MZB +ZFG)972 +5LK)FT3 +D25)1CF +RMQ)2HQ +85N)HDY +952)WFS +T4J)B88 +2MC)JFH +BRL)D64 +GJ4)65N +ZC2)QLQ +69T)3WV +W4F)WMG +74D)NCN +3YY)19K +JKG)6CJ +S68)GGZ +6N6)H2P +3XL)ZVG +S1D)14K +GMK)DW3 +HJF)1D5 +9DP)P9D +18K)Z2Q +248)YD2 +DTK)MR3 +LH8)1GZ +7ZC)RZJ +YJ2)ZVN +JN1)1FX +3WV)289 +53D)GJX +883)FXW +79K)ZXD +DLH)9X5 +BRQ)KHK +2XW)R65 +RGD)GCY +RNC)TR9 +HYV)54C +SJF)BBD +T81)F2T +GZ2)KBQ +G2K)48L +PL6)B5D +R76)Z4Z +QVK)TDX +F6N)M6X +8XQ)3JP +HXD)WNB +CLZ)37R +K6R)SY1 +X9G)8CM +2W9)W4X +ZXV)JC5 +HKY)1Q4 +KV1)QZC +LMT)CLW +Y4M)P57 +1YS)SJF +NGV)N1R +VLF)RGD +FJ5)8WN +PWG)V4K +XDC)KY2 +3DJ)RV8 +1RJ)2GN +WXT)MP2 +R89)JLR +GGB)RDG +Z6L)GQX +ZJQ)TLG +3WF)FQH +5YP)5Z3 +C1B)CCD +SBW)BQB +41C)W4H +1P5)YYP +R5X)36J +DZL)KNW +P57)CN4 +C85)78L +6YB)S7R +CYB)LNN +881)Z5X +642)B5K +X9J)SQT +BJK)M39 +BMW)SHT +2NS)VKN +1C2)JHT +H46)ZGD +JY6)RF8 +V1D)82Y +Z4Z)FW6 +CRP)JRG +1VX)77V +M2F)MHH +B7X)JJV +H29)7JR +Z4C)N13 +HN2)PRV +FTN)5FY +8HS)Z4M +JTP)GLS +JST)8XZ +4GX)T2P +1GZ)V8W +5MW)RT4 +9G2)QPQ +X6C)NGV +GP8)8SY +J67)ZBL +R45)BWC +DDF)S37 +31R)PHR +V4K)2L6 +J69)SYP +DVF)R29 +DLS)1BQ +72W)JKH +JPV)FL9 +TSK)69T +93V)T9M +CST)WPW +37Y)BJ8 +JR2)V4Z +B7C)X1V +WN7)GCD +K65)TM5 +HFS)KYB +1XR)TX8 +7L2)NXY +57Z)M6W +WMG)5HG +F6S)3YF +FMB)N6Q +HS4)QNV +XN6)X2C +56X)Z5F +NJ1)3M8 +65K)S2S +MSJ)Z3P +3RW)YJQ +YRB)L4G +5DZ)5YP +TB6)TGV +PDM)H9F +MTR)B36 +GGH)2LS +4S6)4KV +SVB)MV1 +JQN)18K +SRN)ZFK +ZFX)HXD +YNR)GCL +8QM)GDK +17G)B9Y +JKZ)19N +MJD)5BH +NSR)24N +T48)CF2 +Q3R)3TZ +741)T7M +P2C)G9Q +V8G)17G +GCC)54L +53K)TC8 +ZGD)F7V +J5Z)Z7X +4YV)HZV +GPZ)69X +RYT)RTK +Z6T)7ZC +FMT)ZVJ +56X)7KS +M89)YDR +F6Q)V8G +Y4V)MY7 +1Q7)17N +YV7)HQS +YLQ)GJ2 +5WT)VQB +YN7)DR2 +MPX)JBC +LFL)DPB +TNG)5Q1 +LW7)HC8 +HBR)Q6N +9K2)DNB +GXN)MHW +SGZ)1HF +WFS)N4R +3GN)2K4 +5Y4)1MH +M9W)7PR +WCK)DMQ +COM)TKH +6XY)LTM +WQF)1S2 +Z6N)3BD +CF2)LFL +GDX)ZQ4 +PGZ)1VH +X5D)6CP +TDX)MKV +3XX)BHR +SPL)DXS +GM5)TZR +M8W)DBH +PFH)KGJ +W4H)MKN +SPK)LRQ +V4P)63V +5LQ)WDG +L2G)49J +HB2)6Q9 +YV4)NTM +H47)9MW +ZB8)Y8J +C3D)HTQ +9HF)9K2 +XDG)GDX +FMS)239 +JJP)PKV +6C1)BL3 +FNX)JX4 +SN2)237 +TSD)PNN +RY1)JL3 +TX5)B2R +BS5)HJK +TBS)JNC +1BQ)PR5 +NRS)FX1 +5GX)BKC +8Y8)FRH +GP1)KFR +H1W)ZLJ +FX1)WT6 +HJK)WFT +7Z4)GT9 +FD8)RGG +8VZ)5PJ +1LW)PTY +PTT)15X +QVZ)6LR +Q9V)WMP +BLW)4DX +554)35D +YML)DND +997)CTW +L2L)6WB +PR9)K5K +6TY)5Y4 +2RQ)DVF +5PL)NK7 +3WB)KJ7 +PXM)HN2 +NBJ)FMB +BGN)BRP +BTH)C2B +9X5)MLT +XGJ)KGD +TDC)SBW +56Q)K7F +HF3)Z2X +RP9)952 +PKV)K4K +222)95K +LX9)4WG +RYF)HB2 +5CL)C4P +J2H)6PG +CXP)5GB +38R)L7N +NJ1)YDZ +LBC)42B +6WB)NCK +524)YOU +D8X)YNZ +KY2)BRH +W5X)DZX +SP9)G1J +JKT)LGJ +J2V)PJT +6SS)R9G +8MF)2L8 +X4J)8JJ +T1P)DLS +NWC)76R +YXW)RMQ +Y64)9NF +XB5)52M +JKP)YC1 +FZ2)ZCD +Q3S)CWT +YCS)QDR +S3M)792 +Q7K)N5M +952)MYL +GPR)F37 +Y7G)TFK +V7H)2G3 +CHW)BVC +FSM)TRY +RS7)BFX +KF6)3RW +TGV)6BJ +3TP)CXP +DXS)BW8 +8QM)NT3 +R4Z)X43 +7X3)7N7 +JJZ)3WB +GWZ)K7Z +XQF)R1M +2L8)4YX +891)F1D +S73)KS9 +289)3TB +XJF)PDZ +C29)K7N +YH5)8F3 +9NF)8LD +YX7)1NW +ZLJ)ZGS +DWS)CY2 +Z4P)XBM +HKY)K55 +P6W)BWQ +P1H)L64 +54T)25P +W38)6KP +CNV)9S2 +7FS)75T +9SV)PQQ +H46)VL3 +3FW)W91 +JBW)T99 +J89)MLR +CJC)4B6 +NYK)189 +R2K)3CT +S54)BHJ +98D)HRL +F1T)GRQ +T9M)NZJ +5B2)FNX +PQJ)D89 +WG3)2W2 +ZS9)WW8 +FSG)5SS +DW4)ZFG +78L)49Z +NGQ)2TJ +M6X)GDP +KXR)95L +1WQ)FNT +BRP)L4X +J3F)5C4 +2NB)JJD +SZL)5PT +FNB)DN9 +LNZ)ZBG +Z4J)NQV +D6J)H54 +1CF)SZF +QQF)1N2 +FFS)VF9 +NK7)KRM +6HY)TDQ +C2Q)16T +JTK)ZLR +1KD)N3R +2XH)JKP +BJ8)QHR +G9Y)5F2 +4R7)HGM +JGH)XS7 +72G)LLM +QLQ)Q1Y +TJL)8JW +N8F)8SX +JY8)HZD +3W9)JPV +WK4)HBD +8X9)6XH +YYG)WJQ +HZL)NQZ +BLY)JJG +6CH)CR4 +GQ6)248 +DWH)5LK +LQM)Z7Q +SN2)4DC +BF7)BTH +Z9S)NG8 +F5D)HK4 +2S6)5NW +LTM)757 +FC8)89N +SBJ)4T4 +XLM)XQR +S29)TDC +1YK)RL3 +6J2)7NB +SK1)7CS +GBD)H77 +9KL)HJF +LJ4)VST +S9W)4KN +99C)Z6N +L58)M2K +5JS)LR8 +WR5)9XR +V6W)WK4 +9S7)FRC +TM8)C39 +F4Q)Y86 +BN1)MTR +BGG)GP8 +GJN)MV8 +TLG)XYH +83S)CHW +Z1H)GX4 +3TB)HHX +J3Q)JQL +5Q1)75N +W91)57T +DVJ)HBR +B6F)M9M +WMP)5XN +WXQ)B17 +83M)XMH +8N9)SAN +LVG)8ZV +L2J)7SB +FNT)KM7 +BPC)B9T +1TQ)K27 +JZR)RJ4 +L9S)H93 +189)36D +TZG)2Z4 +5LZ)HXM +SJD)Q3S +WJQ)D81 +GP8)GZ2 +1TP)ZNV +X2J)837 +DJM)KDJ +7GP)NYK +TQ8)446 +HZL)4L8 +29G)3VP +4LZ)XTK +KFX)6N6 +HPM)WWQ +X1V)KVV +Y64)V4C +5GN)54T +SJ1)QS3 +DM4)83W +KDT)ZB8 +DL7)DKC +TML)SPL +LC2)K1W +MHW)5Z7 +MXT)RQN +9KL)K9L +M3T)YRM +KFR)Q49 +1DJ)SN2 +F82)2J1 +PWN)5PX +YT1)V7F +T6S)T1F +B8L)WB2 +Q79)LKF +853)RTD +KBQ)356 +HTL)54G +43T)53D +B5W)PH9 +7KQ)8TX +T2Z)1WQ +8HY)29M +552)M74 +STR)6HX +FRV)HMM +45F)J7C +4Y9)HFS +GNN)WJ6 +HXT)JQ8 +PNN)51L +PHR)RK5 +MM8)H1B +N66)G85 +C4P)W7Z +991)FSM +7QK)SLP +GDP)71Q +5MC)MRG +F2X)HY1 +B9B)CWM +SVZ)HN8 +XDB)4P8 +BS3)VFP +VXM)KCL +9G6)831 +9Z8)FNJ +GX4)C2Q +WFB)MZ9 +63V)MX3 +V8W)82Z +RTK)319 +427)WY1 +4T3)VVN +T2P)4LC +CR4)FQS +K4L)DTK +HLP)WCK +4YQ)H9N +RK5)QFW +GT9)SRN +YXF)FXY +V74)L3W +MY7)2RQ +JLR)JNS +9S5)LPH +H54)J37 +8XR)BLY +QMC)T48 +4TY)1QG +Z4J)H82 +BZC)LKD +4CP)86F +Z24)L58 +1FN)X15 +5FJ)QWJ +K27)2CD +3Z9)3W9 +L6V)J1J +51V)HJ2 +WD5)Q99 +49Z)G6N +Y4V)DDF +MFV)3GH +B1T)9CM +X9Z)BG5 +2M6)1XQ +2J8)3G5 +VMB)13Z +51S)BMW +1MH)LFK +VBK)3D4 +SDM)8XR +7NX)S2K +52L)4NL +LRS)664 +JDD)43S +JJV)H6X +62K)7L2 +WR1)L3D +LN4)WXQ +S52)C85 +F22)9SV +LH3)8B2 +YBD)8MY +TGM)N6H +ZVJ)MSN +S2S)5HV +2MF)GP1 +9ZP)3ZK +1LW)H44 +QTW)T9P +GHZ)YV7 +W7Z)M3Y +5FK)NWC +97X)36T +G7X)K5R +GLP)XQF +WQH)ZM7 +8YP)KF6 +WNB)WG1 +W21)1TQ +VBH)XM4 +CY5)3N6 +G1V)K1G +L2X)L9S +2CV)3LL +BKC)LC8 +R5P)JDL +JL3)T5B +HDY)FRM +XL2)F29 +8Y8)N86 +C8B)FDF +L3W)Z9L +WJ6)6FW +5HV)157 +DW9)1WX +C2B)JR2 +6HK)7GP +N86)971 +GZ6)KHJ +V4Z)376 +WT6)F4Q +H97)FP5 +M4L)MCT +D8G)BCQ +XPG)NP5 +8CG)GBD +6SD)6X3 +54L)1TP +N1W)MJD +ZXT)VXM +QH7)JN5 +S7H)4M5 +QSC)44B +19K)QLJ +951)25C +PJZ)W21 +X8F)X4F +CZW)SV8 +ZYJ)F5C +XNR)KPH +658)47Q +D66)3GD +ZGK)D65 +4ZT)YBT +3NR)K3P +WMD)HRP +VGN)554 +2GN)WH3 +8SX)DXJ +Z4M)MR9 +R1V)VDY +1D1)CRZ +CC5)MH1 +2NS)PXH +SLP)1FN +PTB)LYC +V4D)Z5M +Z2N)X77 +DR4)7KQ +646)98D +9PN)F21 +PB8)728 +WXT)4S9 +3YP)TGM +6PG)776 +9KY)T7C +5SS)LV1 +8HR)53Z +972)FZ2 +XJ8)9PN +6PB)Q35 +ZCR)42N +NNP)YPG +SL6)XL4 +1CG)YZJ +QKG)5GX +L94)HD8 +ZVH)GVJ +R93)3YL +4GC)2XH +FNJ)ZL5 +2LR)YBD +YDW)HMN +S8V)YRB +YV2)HS4 +6B6)6WZ +SVG)LB5 +DMQ)VWX +72Y)997 +MHY)3YY +JX9)XHT +MTV)DSB +413)6SD +DSB)25Q +9HF)BRG +B5W)P93 +9TB)XTP +JN3)6W2 +TFK)MKW +T49)4NY +742)MSJ +8F6)ZKW +TRQ)3JD +F2T)R8H +LQ4)GMJ +B9T)H46 +T2F)ZC2 +VC6)TJF +YDZ)R48 +RGG)974 +DTK)H4C +DTF)QCP +7KM)Z4C +GTS)MLJ +296)424 +664)H86 +2YP)ZYJ +V18)VC6 +7CS)SQH +DZS)3X8 +QYT)8HS +62Y)SQW +D8X)YXX +N2X)D3B +P84)6J2 +JPH)DZL +WM9)KWM +TM5)GM5 +W4X)YYR +TNG)LRP +1KP)ZQX +MZ9)72Y +WJZ)MPF +NP5)SQ3 +D66)5QS +H7H)ZCB +16T)V74 +X15)1WS +8NR)Y7N +237)DYP +N4Y)CGZ +Z8K)BYX +8KF)N6W +RF8)NMV +WFC)7XF +449)DDB +D49)X1H +TM8)78Q +G6N)73R +HGM)GD7 +F21)Y1R +TRC)5HH +N14)S73 +ZXT)BS5 +NG8)4L5 +8ZN)Q79 +4HJ)Q3T +837)NDT +1R7)R2K +77S)6YB +S7R)1XY +2VT)KNJ +WQ4)64D +M5Z)PVZ +RQN)8V9 +VVN)K2K +V2B)N3K +B17)7BX +1W5)LMT +1YW)X2J +XJC)XJF +P4W)4J1 +PRS)Q4P +BMM)QB5 +L7N)H29 +4W5)GKS +8WN)KH8 +N4R)39M +4NY)14W +19Q)ZG9 +W6W)J8C +PWZ)4RW +8F3)JBW +BC8)F4N +QG8)VDP +YG1)GBY +KRM)WJZ +4HL)2TH +W1V)FMT +1BL)NC2 +RTN)R6C +QLJ)PLT +SQH)93Y +KM7)9G2 +5Z3)JY8 +WB2)YSP +3S1)4W5 +5BH)SXV +28Q)5Q7 +PDZ)XD1 +D79)WHF +6BJ)DQT +5F8)C29 +46R)XNR +NC2)2Y8 +T5B)863 +TJF)PDM +L47)5QW +F59)JX9 +RK6)QG8 +GD7)RWP +863)7DK +97R)LJF +6N7)X32 +WLZ)XDM +RXH)79K +WG1)NQW +BNR)1P5 +ZXV)QQF +ZJX)GSZ +X2C)L5L +NVC)L2G +T1F)FK2 +GGZ)KH3 +TZC)R9K +157)FRV +3CX)Z1J +NS1)BGG +MFW)36X +DW3)C53 +88H)LP4 +FX4)F4M +676)7BB +9TR)Q3H +P5H)Z1H +LB1)XBR +SWS)FLP +4S4)QMC +KNW)5LZ +3PR)TVL +JYK)46F +ZM7)Z6T +Q99)427 +5R1)MYP +3TZ)YHB +QPD)L6V +HB8)K7P +2W2)ZFX +BS3)GWH +953)S2C +1BC)WKC +S7X)9PL +1RQ)KLD +1XY)JRV +D37)SF5 +PXD)P2C +4L4)CVV +MYP)2VZ +WPW)SFQ +N6H)8D7 +8B7)9RM +297)Q93 +LNG)R64 +BXB)NSR +DKC)MTV +6C1)81V +75N)21C +XY7)THS +BRG)YY2 +F37)RMV +831)LYP +M1P)GZ6 +ZXD)NR9 +6G1)35R +H2V)51V +Q9F)RRD +FXW)3XX +ZV3)CDP +JC5)JGH +Y73)KFX +V6G)1W5 +7BB)DR7 +RN7)56M +3GV)8X9 +HMM)41C +JK4)V1D +MFV)2J4 +QQW)H62 +N1R)CCC +B5T)3GV +G8D)8QM +JNB)Z75 +8D7)ST5 +JXX)C1B +G5Y)Y92 +G46)DW4 +3CQ)R9L +FR9)Q83 +N6Q)JR4 +ZG2)S4Z +JDC)NCF +ZLX)2XW +JJD)QLN +YY2)FJ5 +Z3P)W7C +LSB)N68 +64D)8BL +PR9)J67 +N6X)M2F +SQ3)XZ7 +MKW)KVM +L61)PL4 +R2Z)2BF +HGM)KQK +222)RJQ +4LC)PY4 +54C)N14 +MLR)Z7Z +BBD)W1V +JK1)32M +SY1)3S1 +65N)3TK +1X9)4HQ +6F3)H6H +489)GFB +Y86)52L +HN7)R1G +48K)5MC +4P3)Z6L +CHT)8R9 +3M8)HKP +RK6)PP4 +X77)V4D +YDR)LCG +DZP)3CY +75T)TKM +ZFK)5LQ +6R6)8NV +TVL)RHW +HMN)BNR +PG2)VN1 +FVQ)SQ5 +1HF)W5X +WVY)TGX +VYF)2N1 +BJS)LTJ +72V)GCC +8NV)BS3 +ZL5)P1H +3KR)69D +CZS)8WW +4N2)72G +KK2)JXX +5Q7)KPZ +4QP)HYV +1SY)V7H +CN4)JTP +9TC)SVG +K7P)T6S +QFQ)999 +NGN)QKG +BHR)DR4 +TGX)XPG +DY3)YG1 +M5Z)PHZ +KBQ)HVY +9D2)N5J +GMF)4LZ +1P8)BFN +GBY)KY4 +49M)LWB +FNZ)FFS +JL3)V2H +LB5)7FK +PM5)1BL +PHZ)LH8 +NCF)YNR +HSK)W6W +5RJ)C95 +RPK)ZRK +Y34)54N +5QW)TZ5 +KGJ)43X +P2V)Q9T +NQZ)L7W +WP4)S29 +J3S)C9G +5C2)TX5 +3PM)PK2 +3GD)393 +CCD)3Z9 +QKQ)PB8 +FCN)LRS +FQ4)M3T +45B)B1T +NPJ)MK3 +KGD)JJP +F5Y)JKZ +C6D)HSK +TR9)7SS +2TX)H73 +NFV)X5D +C2V)43T +M6T)KPS +PK2)1CG +TP1)N4Y +1D5)D9Z +MTR)97R +3TK)X3W +R7T)3VC +PHP)1LV +5GB)2H5 +YC1)24X +S5H)W79 +FQS)JVF +DML)6F3 +Z75)LXP +DMJ)29G +54N)GSS +RWP)D79 +VBV)XWX +VST)CMS +GZ2)676 +N72)FP3 +792)ZJX +H73)J17 +M8N)WQ4 +H6X)L5G +3VC)LBC +YBT)YR2 +LYC)4GX +3VP)17F +F5Y)9ZY +8LD)BCM +7JR)X45 +MV8)FY7 +JN6)31R +MZ5)CVK +239)S7Y +DJ3)S7H +RVK)6HK +G85)WR5 +LKF)TZG +SQ5)NP4 +HN8)H53 +CTW)MCJ +8ZV)6YF +2RQ)SR3 +MRR)Z4P +WQ3)TYW +6SW)L2J +HFC)CTH +N5M)1TK +757)RDF +R5Z)MHY +NW9)V3P +K3P)PWN +GD7)GDL +B2J)FN2 +BRJ)GK8 +S62)3NT +9BH)38R +KQK)WXW +2LS)T8V +4J1)5WT +7J5)H3D +W1B)F72 +F4N)NFK +QCP)4HJ +DWH)V5B +87N)XY7 +F13)LWC +7VH)67W +PMG)DY4 +JMC)WQ3 +6HY)PTT +YJ8)DML +9CM)DM1 +54J)DNJ +1Q6)8ST +CKW)XS3 +ZKW)JPL +111)YFN +H6W)R5Z +THS)X4J +DTM)PWZ +ZH5)8PG +JR4)Z24 +NCN)8HF +3BD)B8L +76R)LN4 +N3K)97M +JJG)N1H +5JW)P48 +YJS)XMP +4RW)T2Z +D65)DNY +KWM)ZGK +5FY)9BK +Y8J)7DR +5PJ)1YW +24L)PTB +XTR)PJZ +LLM)QSC +R6Z)V6W +H62)PQJ +HT7)V18 +6CP)S3M +WXW)N6J +GJX)F5Y +Q35)QY7 +3K8)F59 +8SX)SWS +B2R)6N7 +R8H)CRP +CGH)HFC +NWC)QKQ +P9D)BLW +NK3)YLD +CDP)2M4 +Q39)QB9 +F2J)X7D +J79)QHD +VXM)948 +X7D)GLP +NP4)Q37 +69H)K1C +FF1)65K +P7X)YDW +HTK)B6F +273)CTT +D25)164 +QGY)DXG +G46)BMM +QPQ)SZL +HM7)G7X +VMJ)J24 +5QS)RD6 +KVV)4CP +6W2)8KQ +1JP)PR9 +4B2)SF1 +FX4)NNP +2N7)ZRC +JQ8)N1W +LKD)83V +345)CJC +HVF)QYT +Y4H)7VH +5LR)4MJ +S2C)FSG +V5B)BBN +5X5)SJ1 +MKC)NPJ +BWL)F39 +VDZ)Z27 +7GP)YB3 +8R9)R3N +SQW)GNG +3X8)V2B +D89)SM1 +Z4P)RSN +YB3)5LR +V4C)1JP +FGH)FF1 +GKS)R69 +M5V)H4X +3CY)KXM +G4S)D5H +12P)1YK +3Y2)R1V +KTZ)DQW +KD3)L2L +KSL)F13 +R3Z)JKT +G9Q)1D1 +2J4)5DZ +X3V)MM8 +Z7Y)1BC +G1J)G4S +W4X)LFX +YJ6)JMV +FP5)KN7 +PCQ)8HR +FN2)W8G +31P)WFB +YXX)CYB +NXY)77B +NCK)Z8K +VPX)3TG +CN3)JY5 +HXS)WQF +FK3)DZS +WFT)9DP +XZ5)F1L +639)T81 +R26)PCQ +2VZ)YYD +4S9)1PZ +HVY)V4P +K55)K8N +2Y8)WMD +69T)24L +MHH)SRP +WPS)YWV +9PL)NHB +D3B)KDT +SHT)GJN +42N)6MG +K9F)YDT +N2R)FVQ +F3Q)296 +YML)8XQ +6YF)B9B +R13)Y64 +DNJ)DKW +H44)ZTP +1Q4)5JW +RLM)BRJ +LMJ)8HY +CL4)LF1 +6GW)TMM +VTP)JWQ +TQL)G52 +3QN)VWR +BFN)VPX +T39)TSK +Z1J)S3R +F7V)XBX +VNC)LW7 +WM8)788 +HBD)K9F +JQL)JGJ +3SV)WVN +DM1)297 +VHQ)467 +PVJ)12P +3GH)2M6 +6MG)KD3 +1NW)4GC +VTJ)FKC +Q8H)P86 +5QW)BXB +ML7)V61 +94V)NK3 +XM4)TML +V2P)5Y3 +CR6)JKG +7LG)S9W +8TX)V6G +2JY)ZG2 +DVR)57Z +VN1)Z2R +ZC3)N2C +SB6)RPW +58W)1ZX +VFP)X6C +JQN)ZC3 +53Z)LQM +KWL)TP1 +HKP)4BW +S9T)Q19 +K2K)WD5 +WLM)YV4 +SFQ)4R1 +6KP)CTQ +V3P)XDC +CXM)MKC +31Y)Z62 +XHT)L7R +FK2)S52 +LVY)HFP +RJQ)KV1 +9S2)2LR +NZ8)DVR +JKH)PG2 +ZQX)3TP +81V)9CP +42B)WDJ +7PB)S68 +39C)6C1 +RR8)KSZ +XL4)RTN +3XH)RYQ +78Q)TP3 +GCD)5YQ +R29)LVG +Q3H)646 +TMM)ZLX +4B2)WDB +6N5)449 +3XL)NFV +CDL)6JS +TMC)B7C +R1W)ZWC +LH3)XJC +CHH)DFJ +1FN)MLQ +LMT)658 +HK8)BN1 +73R)1GP +ZQ6)6B4 +Z5X)D37 +YPG)GTK +8SM)VL6 +W5C)C6D +4BW)YS6 +DYP)2TX +R9K)BRN +KS9)L9J +XTJ)B25 +Y23)CHB +NHB)LG4 +L5L)7Z4 +DRK)9SL +ST5)NVC +2WH)DTM +1LV)SDM +788)256 +TW7)6TN +6FW)3CX +BG9)4Y9 +67W)JJ7 +2D4)FR9 +Z8K)F1J +LTJ)31P +R94)YJ8 +5PT)MPX +9SL)LGR +FKZ)9G6 +DR7)SGZ +SM7)9KY +TKH)8MF +VXB)4N2 +XQR)W38 +21F)HK8 +Y3H)XLM +DBW)M8W +11H)853 +1WS)66W +DW4)KNK +NQV)SVB +6ZZ)8YP +ZWC)5PL +PP4)3CQ +T8V)THM +J1J)HMK +CPB)Y7G +GYH)9BH +WPK)FMS +95D)FJW +HM7)CJJ +ZGS)LBV +HMK)BZC +2BF)DWS +LWC)85N +L3B)M1P +7C2)WG3 +3ZK)7BM +GDK)8XJ +LGJ)4R6 +DL1)JSJ +44B)6T9 +KFT)CXM +Q4P)STR +LBC)6ZD +GDK)STH +6MX)F2P +Y92)21F +6ZD)YYQ +HYK)58W +3YF)KNM +X9G)8K2 +QWN)JQN +17F)KTZ +CJ4)62Y +KQW)GMF +15N)S9T +G1V)GMK +M62)X6J +8V9)SVZ +WW8)DJ9 +FP3)28Q +PMX)F3Q +N3G)56Q +46F)ZN3 +D3M)S3P +D64)LVY +72Y)ZHM +LPH)WLM +HY1)HZL +L3D)QPD +Q9T)X6Z +6HG)3DJ +KBP)9TR +25C)9Z8 +ZR9)RYK +TJR)5C2 +56M)X4Y +TL2)5CL +939)ZVH +595)DTF +Z27)D25 +54T)MWM +ZBL)W4F +6JS)H7H +YWV)QWN +5D9)S5H +P96)KZ1 +TDQ)8JZ +NQW)VHQ +K9L)DMJ +H6W)8F6 +2TJ)8NJ +MCJ)T1P +M94)JNB +5ZJ)9BG +KCL)RS7 +X6J)ZGQ +PQQ)JN6 +S2K)5FK +K7N)X2Q +HTQ)GW4 +LTJ)RPK +DD2)8J5 +7NX)Z2N +6LR)R3D +YR2)7Y7 +JBS)CZW +ZRK)XJ8 +4L5)3XF +GJ2)FNZ +XTP)YCS +HRP)P5H +BRJ)J89 +RD6)ZR3 +YNZ)N8F +2N1)XGH +JDL)DLD +YLD)94B +ZNV)1Q6 +6TG)CR6 +GMW)KWL +TZR)698 +RDG)VGN +F1D)5X5 +3CT)6CH diff --git a/2019/inputs/day_7.txt b/2019/inputs/day_7.txt new file mode 100644 index 0000000..b21d6af --- /dev/null +++ b/2019/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/2019/inputs/day_8.txt b/2019/inputs/day_8.txt new file mode 100644 index 0000000..21110e8 --- /dev/null +++ b/2019/inputs/day_8.txt @@ -0,0 +1 @@ +211202121222222222221222212222202022222222222122221220222222222222222222222202222222222222122121022222212222222222212212222222210222202212222222012222200222021222222222220222222222202222222222222022220221222222222222222222222222222222222222022022022222222222222222222212222222221222222202220222202222220202021222222222221222202222212222222222222122222220222222222222222222222222222222222222122220022222212222222222202222222222220222202212221222102222211202020222222222221222222222212222222222222022220221222222222222222222222212222222222222122022122222202222222222212202222222212222202212222222202222220222022222222222221222212222202022222222222222221220222222222222222222222212222222222222022122222222222222222222202202222222220222222202222222212222210002122222222222221222212222222022222222222122221221222222222222222212222202222222222222022220222222202222222222212222222222221222222222220222112222211012121222222222222222222222222221222222222122220222222222222222222212222212222222222222022120222222222222222222212202222222221222212202221222122222212122121222222222222222212222122022222222222222221220222222222222222212222212222220222222122021022222222222222222212202222222221222222202220222102222200212020222022222222222212222012221222222222122221221222222222222222212222202222222222222222121122222212222222222212212222222221222212222222222111222212022021222122222220222202222022022222222222122220221222222222222222202222222222222222222122120222222222222222222202212222222210222212212221222020222201222222222022222222222222222122222222222222022221220222222222222222202222212222222222222222222022222222222222222202222222222221222212202221222002222220202020222122222220222202222112221222222222022220222222222222222222222222212222220222222022120022222212222022222202202222222200222202202221222210222220022122222222222222222212222022021222222222222220221222222222222222202222202222221222222222020122222212220122222202212222222201222202212221222112222220002222222022222220222222222122121222222222022222221222222222222222212222202222201222222222120222222222221222222222202222222212222202222220222101222200212021222022222221222202222122222222222222222221220222222222222222222222212222210222222022022122222222220022222202202222222222222222222222222220222221022022222122222220222222222012020222220222122220221222222222222222212222212222212222222222220022222212222022222212222222222212222212212221222011222222012022222122222220222202222220122222222222122220221222222222222222222222212222221222222122020022222222222222222222222222202220222202212220222022222212102221222122222222222202222112021222222222022222220222222222222222222222222222202222222022120020222212221022222202202222212210222212202220222211222210102220222222222220222222222120122222222222022220220222222222222222222222222222202222222222222120222222220122222222202222202200222202222222222220222200012022222122222220222202222220122222222222122220222222222222222222202222212222220220222122122022222212222022222222222222202201222212212221222221222212122221222022222220222200222112022222222222222220020222222222222222202222202222220221222222020222222202221122222212212222212212222222212221222212222211012221222022222222222220222201121222220222022222021222222222222222212222222222200221222122220221222202220122222222202222222211222222202220222022222212002120222222222220222220222100222222221222022222122222222202222222212222212222221222222022121122222202222022222202202222212200222222202220222010222212102222222002222221222221222011022222222222022222120222222202222222222222212222210221222022221021222212220222222202212222212202222222202220222001222220012020222112222222222221222121122222220222122220020222222212222222212222212222220222222122022221222202220022222222202222222210222202202220222010222211022120222212222221222220222202120222221222122221122222222220222222202222202222210221222222221122222222220022222202212222202201222202212220222012222200212022222122222222222222222212222222222222122220121222222210222222202222212222201220222122121122222222222022222222222222212210222212212220222200222200012122222112222221222202222201220222222222222221221222222201222222212222222222210220222222122121222222221022222222222222212220222202212220222202222202012220222212222220222201222010121222220222222220020222222201222222212222212222220220222222122221222222221022222202202222202202222212222220222211222201112021222012222220222221222101121222220222222221121222222201222222212222202222022220222022221122222222222122222212222222222201222222222222222220222201202122222102222222222201222102220222222222122220222222222220222222222222202222211222222122120221222212221122222212202222202200222222222222222020222222222121222222222222222212222012021202222222022220021222222222222222202222222222200220222022221020222212220122222202222222222221222222212220212220222210122220222222222222222212222110222212220222222220021222222212222222222222212222001221222122020021222212222022222202202222212212222222202222212102222210022121222102222121222210222021121202221222122221022222222210222222222222202222001221222222121120212222220022222202212222202220222222212222212012222200022221222022222020222200222222122222221222022222122222222201222222202222202222110222222122221121222202221222222222202222222222222222202222212220222220202121222222222121222201222111221212221222022220120222222210222222202222212222202222222020021020202212222122222202212222202211222222202221212002222212122222222022222121222202222102121212221222022220022222202200222222212220222222211222222121221021222222221022222202222222222212222222202222212010222202102121222022222120222220222201021202222222022222222222222220222222212221212222200221222122221120222212221122222222222222202201222222212222212222222221222120222002222121222201222100021222221222222222120222212211222222222222202222001221222022020122210222221022222222212222222212222202222222212120222202022221222122202122222221222002221212222222022222222222202200222222212220222222111221222122221220210212221022222222202222212202222212212221222010222222102222222002220020222210222212120222222222022220022222202212222222222222212222002222222220121221210202221122222212212222222222222202202222202122222200222111222122220122222210222000020202221222022222221222222222222222202222212222211220222022220020212222220222222212212222222211222212212220202200222222102112222222222222222221222112021222221222222221222222222200222222202221222222212221022020220022220202222122222222202222210222222212202222202122222220112100222002200020222212222010120202220222022221020222212210222222202220202222011220220121121022022222221222222202212222222222222202222220222221222211012110222102221021222222222200220002222222022220121222212201222222202222212222212222221120220020121202222222222222202222222220222222212222202210222200022210222212220122222221222012220102220222222022221222212222222222202221212222021222022122222121012212222022222222222222200222222212212222212202222221102110222012212122222220222001222202221222222120021222212201222222212222222222011221120020221220111202220022222222202222201221222222222220202110222202012021222122220020222202222121220002222222122122122222222222222222212221212222220221122120020221110202222122222222212222212210222212112222222010222200112110222022222121222221222212020002220222222222121222202211222222212220202222222222220122120121011222221222222202202222222220222212102221222101222210222002222110221222202211222001021022222222022121220222212221222222222220222222012221121121021020121202220221222202212222001220222212112222202210222220212101222110211020222202222000220022222222122020222222222221222222222220222222022221122121121222002222221221222222202222210210222212212222202101222211102022222100220120212220222010020102220222222020222222222211222222202220222222221220121001022021110222221221222222222222011222222222022221202000222221022201222200221221010200222011220202220222022220220222212202222222222221222222212221220221220021210202221120222202012222112221222222022220202111222222102112222200220121110202222011020112221222222122101222212220222222202222202222101222222121122220001212221121222222202222220222222202112221222200212212112110222201201020101220222000220002221222022220011222212211222222202222202222012222122001122022210222220222222222022222222220222212102221222120202221202010222011201220010212222001221212220222122121100222222222222222212220212221001220221001120220221212221120222212002222010212222212222220202200212212112022222020220022001201222000020222222222122121002222202220222222212222202221200222220112120122211222222122222222212222012210222202212221212121212201202110222002200220211201222210022222220222122222010222222222222222222220212222122220222222122122200222221122222222012222221201222222112221212002212211022212222122211121222210222212222112222222022222211222220210222222222221222222102221221211022121110222222020222222012222201212222212202221212110222202102021222210211222210221222010020212021222022221021222200212222222222221202200111221121110122021020202221222222222202222022121222212012220212212212202212122222021220020120222222202122102220222122021211222201111222222222221212220101222022200022120002222222220222222002222022110222202202221222202222212202221222120220021210202222020122102020222022020102222220112022222202220202210100222122221122022202202222221222212012222110001222212202221212202212222212100222220211121101220222210021002122222022222222222212102222222202221222200002221020021022022002212222121222212112222100100212212112222202212222212002220220100211220102211222020021012120222022221222222211222022222202220212220102221021111020021201202220120222202222222012200212202102221212212202211022221222121212020221210222210100202222222122220212222201102022222222220212202000221222202222120212212221122222212102222111010222212122222202210212212002120221202221222002200222212020022221222022120000222210211122222202221212220012222022212020121120212222222222202112222111011202202022220202220212212002201220002212021002200222122222112221222122121222222210211222222222220222200111221020122122022121202220121222222022222220210212222022222222020222202022102221222202120112212222200112212020222122122111222212020222222202220212211101221222211221220120202220120222212102222120222222202102222222021202221122212222010210021122210222102120022220222122222210222202220122222202220222220001222020211220220020212220221022212222122010102212212222221202112222220002220221101212221021211222221200202021222222222012222221011222222222220222220222221120112221221012212220122222212022122122101222202022221212020212210022112221000220221102221222100120022221222022022001222210212022222222220222202220222222120121022002202221220222212012122200201202222202222222210212201012011221020221222212222222200220202122222022220102222222011222222212222222202012221221100221121212212222222122212112122222002202202112222222002212202212212221112220221111211222201000122121222122022020222201010222222202222212202221220122120120120120212221021222202012122021021212222112222212112210200122222220002212220112210222110021012022222222021021222212011122222222220202220110221020202121022212202221022022212212222101020222202202222222000222201202110221200222222010201212200221222022222222020000222201112222222220221212222012221120111220022102212221122122222112222012122222222122221202200222212122101221210210022001221222112122222122222122221111222212002222222210221212201120211021110120021201222222021022202022022101000222200022222212120220201212210221210222220222220212011221202220222222122000222210120022222220221202222021210020120120020221222221221122222122222202222222201022221210112212222122122220110202121112202222210022112022222122020122021210212222222011221222210010221222221022222121222221120122222122022012022202202012222222210200201002012221012221020200220202120211102222222222022110022202001122222112220212211120221222200221021020212220222122222112122201111202212102221220010200211002101221111211120121222212120102222022222222022000222212220022222021222212221012212122120021021100202222022222212012222002221222000002221212121201220222010222012210122002211202202201202020222222121101212202112122222212221102211011222120012221221210222221222122202122122212122202022102222202010221201002010221121210020102211222210220112021222122020221200210202222222200222122221200201222121122221112202222121022202022122001102222022112221220120222201212200221011200221212220202200211102020222022122212101221022022221122220112210220212220112222121012222222222222212012022201202212122212200200122210211122100222002210021201200222212202012021222222120112001220220122221102220012221201220221120002022011202221220022202212122210002202001202220212110222222002201221111222221220200212122022222220222222020120010211200022222212221212202110210222110000221120222220220222222102022122211222010222211221202202220112001222010211201201211222112002222220212222220112202221122222220101020022002211202221112210022212022220021120212202122122220222122001202222012201202102100221112210110120210212222111222222212022020111000222122022221202220002111220212121222222221020102222222222212222222222001222020022211221221200221012212220222202212101211222120010222121200022020200002210210222222102221022200220222020210212201101202221121021202122122220110212101100220220101202210202201220121200102211210212201122022020201022020000221202200122221011222012001022221022002211101122122221222120202202222222101212212201210220202211212102222222200200012220011212121100022222201122021212200201001122222022020012120011002222021201010021122221121022202122122110122222211021220200212202222222220221020200001011010202122210002020202022021012002202201222220011022110210112121221222112102000122221220220220012222102002202101112221211222210222222020022210210120112200222211111122021220122022002000211020022222010020022201021221121000100000202212221022021212112222202112212222222200221021200222102100121121221221010212202102200012220212120022212102222011022220220220211200121211220211001122222102221221020202202222010121212200100221202012222212112011222020210010010221212122200102022220221020002000212022122221202021122000112210021200010000210222220120121201122222021102212102111222201121202201202002020120200201212110202101010102022200121222211012221121122221000122021100210212222122211220212102221020122210202222110002212200011201200021201220022012110200222202010110002212220010120010022120110012200120022222122021212000212022122022010021101012221222020212102122120000212202002202202222222210012200102200200111220022112012202102021122021120011121200020122220001221102112201201020102122212202112220122122212222022110111222010201211210002212202112020020222212100211112122120200002020201020021202021200200022222010120111011000012120121101212002212222122121200022022212122202211001220201122201201012022011111200001112022002112002200220221121202120002212010122222010222121211010100220111112122101222222021021211212122121120212202000200210112220002211221002010102121110201000000011200112100002201220112102201101001200002222202202212002201221110202000102001202000200100102121000220100101111222110 diff --git a/2019/inputs/day_9.txt b/2019/inputs/day_9.txt new file mode 100644 index 0000000..6ec0b92 --- /dev/null +++ b/2019/inputs/day_9.txt @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,23,1,1004,1102,1,26,1000,1102,897,1,1028,1101,27,0,1012,1102,33,1,1001,1102,32,1,1007,1101,39,0,1005,1101,0,29,1018,1101,0,0,1020,1101,1,0,1021,1101,0,21,1002,1102,1,35,1014,1101,0,36,1009,1102,1,38,1006,1102,1,251,1024,1102,28,1,1017,1102,37,1,1008,1102,1,329,1026,1102,25,1,1011,1102,31,1,1013,1102,892,1,1029,1102,242,1,1025,1102,1,881,1022,1102,22,1,1003,1102,874,1,1023,1101,20,0,1016,1101,24,0,1019,1101,0,326,1027,1101,0,34,1015,1102,1,30,1010,109,-2,2102,1,7,63,1008,63,36,63,1005,63,205,1001,64,1,64,1105,1,207,4,187,1002,64,2,64,109,9,21101,40,0,6,1008,1013,43,63,1005,63,227,1105,1,233,4,213,1001,64,1,64,1002,64,2,64,109,26,2105,1,-9,4,239,1001,64,1,64,1106,0,251,1002,64,2,64,109,-15,1205,2,263,1105,1,269,4,257,1001,64,1,64,1002,64,2,64,109,-9,2102,1,0,63,1008,63,36,63,1005,63,295,4,275,1001,64,1,64,1106,0,295,1002,64,2,64,109,-14,1207,10,38,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,28,2106,0,4,1106,0,335,4,323,1001,64,1,64,1002,64,2,64,109,-8,1206,6,351,1001,64,1,64,1106,0,353,4,341,1002,64,2,64,109,-1,2107,33,-7,63,1005,63,369,1106,0,375,4,359,1001,64,1,64,1002,64,2,64,109,-9,2108,26,-1,63,1005,63,395,1001,64,1,64,1106,0,397,4,381,1002,64,2,64,109,3,1201,-2,0,63,1008,63,38,63,1005,63,419,4,403,1105,1,423,1001,64,1,64,1002,64,2,64,109,-13,2101,0,9,63,1008,63,23,63,1005,63,445,4,429,1105,1,449,1001,64,1,64,1002,64,2,64,109,11,1208,1,32,63,1005,63,471,4,455,1001,64,1,64,1106,0,471,1002,64,2,64,109,17,21108,41,38,-4,1005,1019,487,1105,1,493,4,477,1001,64,1,64,1002,64,2,64,109,6,1206,-9,511,4,499,1001,64,1,64,1106,0,511,1002,64,2,64,109,-23,21102,42,1,8,1008,1014,42,63,1005,63,533,4,517,1106,0,537,1001,64,1,64,1002,64,2,64,109,-3,2107,36,5,63,1005,63,555,4,543,1106,0,559,1001,64,1,64,1002,64,2,64,109,-6,1202,5,1,63,1008,63,21,63,1005,63,581,4,565,1106,0,585,1001,64,1,64,1002,64,2,64,109,1,1208,10,40,63,1005,63,605,1001,64,1,64,1106,0,607,4,591,1002,64,2,64,109,7,1201,0,0,63,1008,63,42,63,1005,63,631,1001,64,1,64,1106,0,633,4,613,1002,64,2,64,109,1,21107,43,42,7,1005,1013,649,1105,1,655,4,639,1001,64,1,64,1002,64,2,64,109,7,21108,44,44,3,1005,1016,677,4,661,1001,64,1,64,1106,0,677,1002,64,2,64,109,-7,21102,45,1,9,1008,1015,44,63,1005,63,701,1001,64,1,64,1106,0,703,4,683,1002,64,2,64,109,13,21101,46,0,-7,1008,1012,46,63,1005,63,729,4,709,1001,64,1,64,1105,1,729,1002,64,2,64,109,-13,2101,0,3,63,1008,63,33,63,1005,63,753,1001,64,1,64,1106,0,755,4,735,1002,64,2,64,109,14,1205,1,773,4,761,1001,64,1,64,1105,1,773,1002,64,2,64,109,-23,1202,10,1,63,1008,63,30,63,1005,63,797,1001,64,1,64,1105,1,799,4,779,1002,64,2,64,109,13,2108,22,-7,63,1005,63,817,4,805,1106,0,821,1001,64,1,64,1002,64,2,64,109,-11,1207,5,24,63,1005,63,843,4,827,1001,64,1,64,1105,1,843,1002,64,2,64,109,11,21107,47,48,7,1005,1017,861,4,849,1106,0,865,1001,64,1,64,1002,64,2,64,109,15,2105,1,-2,1001,64,1,64,1106,0,883,4,871,1002,64,2,64,109,10,2106,0,-7,4,889,1106,0,901,1001,64,1,64,4,64,99,21102,1,27,1,21102,1,915,0,1105,1,922,21201,1,28510,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,22102,1,1,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,21202,-2,1,-2,109,-3,2106,0,0 diff --git a/2019/readme.org b/2019/readme.org new file mode 100644 index 0000000..c674de4 --- /dev/null +++ b/2019/readme.org @@ -0,0 +1,26 @@ +* Advent of Code 2019 + +** Personal challenge + +Try to keep the solution pure. Only main can do IO things, like return +different results when it's called differently. The rest of the +program should only be pure expressions. + +** Optimizations + +- Limit the use of statements. Try to use expressions instead, or move + the statement out to a function. + +** Findings + +- Having iterators that you can't clone (like stdin) makes certain + things difficult. Eg, doing part 1 and 2 together. +- Using "new type" structs can be a pain. derive_more crate made most + of that pain go away. +- With immutable types, 'reset the machine to try again' type + constraints were handled for free. This made many later puzzles easier. +- The 'no statement' constraint meant that some functions ended up + nested in a way that makes it harder to name and read. +- The persistent data structures don't integrate with Rayon iterators. +- Easier to test subsets, but harder to inspect and audit runtime behaviour. +- Although it isn't frequently used, Rust supports functions inside functions. diff --git a/2019/src/bin/day_1.rs b/2019/src/bin/day_1.rs new file mode 100644 index 0000000..572d287 --- /dev/null +++ b/2019/src/bin/day_1.rs @@ -0,0 +1,93 @@ +use derive_more; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; + +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 1: The Tyranny of the Rocket Equation")] +/// Calculates the fuel needed for your rocket to save Santa. +/// +/// The weight of each module is read from stdin, one module weight +/// per line. See https://adventofcode.com/2019/day/1 for details. +struct Opt { + /// Includes the weight of fuel + #[structopt(short = "i", long = "include-fuel-weight")] + include_fuel_weight: bool, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let input = stdin.lock().lines().map(|l| match l { + Ok(s) => match s.parse::() { + Ok(module) => module, + Err(e) => { + eprintln!("Invalid input \"{}\": {}", s, e); + process::exit(1); + } + }, + Err(e) => { + eprintln!("Error reading input: {}", e); + process::exit(1); + } + }); + + println!("{}", fuel_required(input, opt.include_fuel_weight)) +} + +fn fuel_required(it: impl Iterator, include_fuel_weight: bool) -> Fuel { + it.map(if include_fuel_weight { + Module::fuel_including_fuel_weight + } else { + Module::fuel_excluding_fuel_weight + }) + .sum() +} + +#[derive(Debug, derive_more::FromStr, Clone, Copy)] +struct Module { + weight: Weight, +} + +impl Module { + fn fuel_excluding_fuel_weight(self) -> Fuel { + self.weight.required_fuel() + } + + fn fuel_including_fuel_weight(self) -> Fuel { + iter::successors(Some(self.weight.required_fuel()), |fuel| { + if fuel.is_zero() { + None + } else { + Some(fuel.weight().required_fuel()) + } + }) + .sum() + } +} + +#[derive(Debug, derive_more::FromStr, Clone, Copy)] +struct Weight(u32); + +impl Weight { + fn required_fuel(self) -> Fuel { + Fuel((self.0 / 3).saturating_sub(2)) + } +} + +#[derive(Debug, derive_more::Add, derive_more::Sum, Clone, Copy, derive_more::Display)] +struct Fuel(u32); + +impl Fuel { + fn weight(self) -> Weight { + Weight(self.0) + } + + fn is_zero(self) -> bool { + self.0 == 0 + } +} diff --git a/2019/src/bin/day_10.rs b/2019/src/bin/day_10.rs new file mode 100644 index 0000000..f25c3d2 --- /dev/null +++ b/2019/src/bin/day_10.rs @@ -0,0 +1,158 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 10: Monitoring Station")] +/// Finds the asteroid with the best view of the other asteroids. If +/// an n is provided, then it will print the nth asteroid destroyed by +/// a laser from the asteroid with the best view. Otherwise, it will +/// print the number of asteroids visible. +/// +/// Takes a map of asteroids in on stdin. +/// +/// See https://adventofcode.com/2019/day/10 for details. +struct Opt { + /// indexed from 0 + #[structopt(short = "n")] + n: Option, +} + +fn main() { + let opt = Opt::from_args(); + let stdin = io::stdin(); + let map: AsteroidMap = stdin + .lock() + .lines() + .map(|l| exit_on_failed_assertion(l, "Error reading input")) + .collect(); + + match opt.n { + Some(n) => println!("{:?}", map.nth_destroyed_asteroid(n)), + None => println!("{}", map.best_asteroid_line_of_sight_count()), + }; +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug)] +struct AsteroidMap { + asteroids: Vec, +} + +impl FromIterator for AsteroidMap { + fn from_iter>(iter: T) -> Self { + AsteroidMap { + asteroids: iter + .into_iter() + .enumerate() + .flat_map(move |(y, line)| { + line.chars() + .enumerate() + .map(move |(x, c)| (x, y, c)) + .collect::>() + }) + .filter(|(_x, _y, c)| *c == '#') + .map(|(x, y, _x)| Asteroid { + x: x as i32, + y: y as i32, + }) + .collect(), + } + } +} + +impl AsteroidMap { + fn best_asteroid_line_of_sight_count(&self) -> usize { + self.optimal_view_asteroid() + .map(|a| self.count_visible_from(&a)) + .unwrap_or(0) + } + + fn nth_destroyed_asteroid(&self, n: usize) -> Option { + self.optimal_view_asteroid() + .and_then(|source| self.nth_destroyed_asteroid_from(&source, n)) + } + + fn nth_destroyed_asteroid_from(&self, source: &Asteroid, n: usize) -> Option { + if self.asteroids.len() - 1 < n { + None + } else if self.count_visible_from(source) >= n { + sort_by_key( + self.asteroids + .iter() + .filter(|b| self.has_line_of_sight(source, b)), + |b| (source.angle_to(b) * 100000.) as i32, + ) + .nth(n) + .cloned() + } else { + self.remove_visible_to(source) + .nth_destroyed_asteroid_from(source, n - self.count_visible_from(source)) + } + } + + fn optimal_view_asteroid(&self) -> Option { + self.asteroids + .iter() + .max_by_key(|a| self.count_visible_from(a)) + .cloned() + } + + fn count_visible_from(&self, a: &Asteroid) -> usize { + self.asteroids + .iter() + .filter(|b| a != *b && self.has_line_of_sight(a, b)) + .count() + } + + fn remove_visible_to(&self, source: &Asteroid) -> AsteroidMap { + AsteroidMap { + asteroids: self + .asteroids + .iter() + .filter(|b| self.has_line_of_sight(source, b)) + .cloned() + .collect(), + } + } + + fn has_line_of_sight(&self, a: &Asteroid, b: &Asteroid) -> bool { + a != b + && !self.asteroids.iter().any(|c| { + a != c + && b != c + && a.angle_to(b) == a.angle_to(c) + && a.distance_squared(b) > a.distance_squared(c) + }) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct Asteroid { + x: i32, + y: i32, +} + +impl Asteroid { + fn angle_to(&self, other: &Asteroid) -> f32 { + ((self.x as f32 - other.x as f32).atan2(other.y as f32 - self.y as f32) + + std::f32::consts::PI) + % (2. * std::f32::consts::PI) + } + + fn distance_squared(&self, other: &Asteroid) -> i32 { + (self.x - other.x).pow(2) + (self.y - other.y).pow(2) + } +} diff --git a/2019/src/bin/day_11.rs b/2019/src/bin/day_11.rs new file mode 100644 index 0000000..da3e1fd --- /dev/null +++ b/2019/src/bin/day_11.rs @@ -0,0 +1,205 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::RedBlackTreeMap; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 11: Space Police")] +/// Calculates how many blocks a painting robot would paint. +/// +/// Takes the program to run on the robot in on stdin. +/// +/// See https://adventofcode.com/2019/day/11 for details. +struct Opt { + /// debug mode prints the size of the painted area on a black background + #[structopt(short = "d", long = "debug")] + debug: bool, +} + +fn main() { + let opt = Opt::from_args(); + let stdin = io::stdin(); + 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::(); + + let finished_robot = exit_on_failed_assertion( + Robot::new(program, !opt.debug).execute(), + "Robot encountered an error", + ); + if opt.debug { + println!("{}", finished_robot.canvas.size()); + } else { + println!("{}", finished_robot); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug, Clone)] +struct Robot { + program: IntcodeProgram, + position: (i32, i32), + facing: Direction, + canvas: RedBlackTreeMap<(i32, i32), bool>, + background: bool, +} + +impl fmt::Display for Robot { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.min_white_y()..=self.max_white_y()) + .map(move |y| { + (self.min_white_x()..=self.max_white_x()) + .map(move |x| (x, y)) + .map(|coord| self.canvas.get(&coord).cloned().unwrap_or(self.background)) + .map(|c| write!(f, "{}", if c { '#' } else { ' ' })) + .collect::() + .and_then(|_| writeln!(f, "")) + }) + .collect() + } +} + +#[derive(Debug, Clone)] +enum Direction { + Up, + Down, + Left, + Right, +} + +impl Robot { + fn new(program: IntcodeProgram, background: bool) -> Robot { + Robot { + program: program.run_to_termination_or_input(), + position: (0, 0), + facing: Direction::Up, + canvas: RedBlackTreeMap::new(), + background, + } + } + + fn execute(&self) -> Result { + iter::successors(Some(self.clone()), |robot| Some(robot.next())) + .find(|robot| { + robot.program.error.is_some() + || (robot.program.halted && robot.program.output.is_empty()) + }) + .unwrap() // infinite iterator won't terminate unless this is Some + .as_result() + } + + fn as_result(&self) -> Result { + match self.program.error { + Some(ref error) => Err(error.clone()), + None => Ok(self.clone()), + } + } + + fn next(&self) -> Robot { + match ( + self.program.output.get(0).map(intcode_to_bool), + self.program.output.get(1).map(intcode_to_bool), + ) { + (Some(paint), Some(rot)) => Robot { + program: self + .program + .with_cleared_output() + .with_input(list![bool_to_intcode( + self.canvas + .get(&self.facing.rotate(rot).move_position(self.position)) + .cloned() + .unwrap_or(self.background), + )]) + .run_to_termination_or_input(), + position: self.facing.rotate(rot).move_position(self.position), + facing: self.facing.rotate(rot), + canvas: self.canvas.insert(self.position, paint), + background: self.background, + }, + _ => Robot { + program: self + .program + .with_input(list![bool_to_intcode( + self.canvas + .get(&self.position) + .cloned() + .unwrap_or(self.background), + )]) + .run_to_termination_or_input(), + ..self.clone() + }, + } + } + + fn min_white_x(&self) -> i32 { + self.white_blocks().map(|(x, _y)| x).min().unwrap_or(0) + } + fn min_white_y(&self) -> i32 { + self.white_blocks().map(|(_x, y)| y).min().unwrap_or(0) + } + fn max_white_x(&self) -> i32 { + self.white_blocks().map(|(x, _y)| x).max().unwrap_or(0) + } + fn max_white_y(&self) -> i32 { + self.white_blocks().map(|(_x, y)| y).max().unwrap_or(0) + } + + fn white_blocks<'a>(&'a self) -> impl 'a + Iterator { + self.canvas + .iter() + .filter(|(_, val)| **val) + .map(|(coord, _)| coord) + .cloned() + } +} + +impl Direction { + fn rotate(&self, clockwise: bool) -> Direction { + use Direction::*; + + if clockwise { + match self { + Up => Right, + Right => Down, + Down => Left, + Left => Up, + } + } else { + match self { + Up => Left, + Left => Down, + Down => Right, + Right => Up, + } + } + } + + fn move_position(&self, position: (i32, i32)) -> (i32, i32) { + use Direction::*; + match self { + Up => (position.0, position.1 + 1), + Down => (position.0, position.1 - 1), + Left => (position.0 - 1, position.1), + Right => (position.0 + 1, position.1), + } + } +} diff --git a/2019/src/bin/day_12.rs b/2019/src/bin/day_12.rs new file mode 100644 index 0000000..7e42f4c --- /dev/null +++ b/2019/src/bin/day_12.rs @@ -0,0 +1,205 @@ +use std::io; +use std::io::prelude::*; +use std::iter; +use std::num::ParseIntError; +use std::ops; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 12: The N-Body Problem")] +/// Simulates N bodies, physically interacting +/// +/// See https://adventofcode.com/2019/day/12 for details. +struct Opt { + #[structopt(short = "n")] + n: Option, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let planets: Vec = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid planet")) + .collect(); + + match opt.n { + Some(n) => println!("{}", energy(simulate_planets_n_iterations(planets, n))), + None => println!("{}", simulate_planets_to_duplicate(planets)), + }; +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn energy(planets: Vec) -> i32 { + planets.into_iter().map(|p| p.energy()).sum() +} + +fn simulate_planets_n_iterations(planets: Vec, n: u64) -> Vec { + simulate_planets_iter(planets) + .find(|(i, _)| *i == n) + .unwrap() + .1 +} + +fn simulate_planets_to_duplicate(planets: Vec) -> u64 { + lowest_common_multiple( + simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_x(o)), + simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_y(o)), + simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_z(o)), + ) +} + +fn simulate_planets_to_duplicate_1d( + planets: Vec, + eq: impl FnMut((&Planet, &Planet)) -> bool + Copy, +) -> u64 { + simulate_planets_iter(planets.clone()) + .skip(1) + .find(|(_i, ps)| ps.iter().zip(planets.iter()).all(eq)) + .unwrap() + .0 +} + +fn lowest_common_multiple(x: u64, y: u64, z: u64) -> u64 { + (1..) + .map(|i| x * i) + .find(|mx| multiples(y, *mx) && multiples(z, *mx)) + .unwrap() +} + +fn multiples(x: u64, target: u64) -> bool { + target % x == 0 +} + +fn simulate_planets_iter(planets: Vec) -> impl Iterator)> { + iter::successors(Some((0, planets.clone())), |(i, planets)| { + Some((i + 1, simulate_planets(planets.clone()))) + }) +} + +fn simulate_planets(planets: Vec) -> Vec { + simulate_velocity(simulate_gravity(planets)) +} + +fn simulate_gravity(planets: Vec) -> Vec { + planets + .iter() + .map(|p| Planet { + pos: p.pos.clone(), + vel: planets + .iter() + .filter(|o| p != *o) + .map(|o| p.acc(o)) + .fold(p.vel, |acc, next| acc + next), + }) + .collect() +} + +fn simulate_velocity(planets: Vec) -> Vec { + planets + .into_iter() + .map(|p| Planet { + pos: p.pos + p.vel, + vel: p.vel, + }) + .collect() +} + +#[derive(Debug, Default, Clone, PartialEq)] +struct Planet { + pos: Vec3d, + vel: Vec3d, +} + +#[derive(Debug, Default, Clone, Copy, PartialEq)] +struct Vec3d { + x: i32, + y: i32, + z: i32, +} + +impl FromStr for Planet { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result { + s.replace(|c| "<>xyz= ".contains(c), "") + .split(',') + .map(|i| i.parse::()) + .collect::, _>>() + .and_then(|v| match &v[..] { + [x, y, z] => Ok(Planet { + pos: Vec3d { + x: *x, + y: *y, + z: *z, + }, + vel: Vec3d::default(), + }), + _ => "wrong number of fields" + .parse::() + .map(|_x| Planet::default()), + }) + } +} + +impl Planet { + fn acc(&self, other: &Planet) -> Vec3d { + Vec3d { + x: gravity(self.pos.x, other.pos.x), + y: gravity(self.pos.y, other.pos.y), + z: gravity(self.pos.z, other.pos.z), + } + } + + fn energy(&self) -> i32 { + (self.pos.x.abs() + self.pos.y.abs() + self.pos.z.abs()) + * (self.vel.x.abs() + self.vel.y.abs() + self.vel.z.abs()) + } + + fn equal_x(&self, other: &Planet) -> bool { + self.pos.x == other.pos.x && self.vel.x == other.vel.x + } + + fn equal_y(&self, other: &Planet) -> bool { + self.pos.y == other.pos.y && self.vel.y == other.vel.y + } + + fn equal_z(&self, other: &Planet) -> bool { + self.pos.z == other.pos.z && self.vel.z == other.vel.z + } +} + +fn gravity(this: i32, that: i32) -> i32 { + if that > this { + 1 + } else if this > that { + -1 + } else { + 0 + } +} + +impl ops::Add for Vec3d { + type Output = Vec3d; + fn add(self, rhs: Vec3d) -> Self::Output { + Vec3d { + x: self.x + rhs.x, + y: self.y + rhs.y, + z: self.z + rhs.z, + } + } +} diff --git a/2019/src/bin/day_13.rs b/2019/src/bin/day_13.rs new file mode 100644 index 0000000..ac1c478 --- /dev/null +++ b/2019/src/bin/day_13.rs @@ -0,0 +1,149 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::vector::Vector; +use rpds::RedBlackTreeMap; +use std::cmp::Ordering; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 13: Care Package")] +/// Executes an Intcode game +/// +/// The program is read from stdin as a series of comma-separated +/// values. Newlines are ignored. +/// +/// See https://adventofcode.com/2019/day/13 for details. +struct Opt { + #[structopt(short = "q", long = "quarters")] + quarters: 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.quarters { + Some(quarters) => { + let result = score_on_won_game(program.with_mem_0(quarters)); + println!("{}", result); + } + None => { + let result = exit_on_failed_assertion(program.execute(), "Program errored"); + println!("{}", count_blocks(&result)); + } + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Default, Clone)] +struct Screen { + screen: RedBlackTreeMap<(Intcode, Intcode), Intcode>, + previous_ball: (Intcode, Intcode), + ball: (Intcode, Intcode), + paddle: (Intcode, Intcode), + score: Intcode, +} + +impl Screen { + fn render(output: &Vector) -> Screen { + (0..output.len() / 3) + .map(|i| i * 3) + .map(|i| { + ( + output[i].clone(), + output[i + 1].clone(), + output[i + 2].clone(), + ) + }) + .fold(Screen::default(), |acc, (x, y, tile)| { + if x == Intcode::from(-1) && y == Intcode::from(0) { + Screen { score: tile, ..acc } + } else if tile == Intcode::from(4) { + Screen { + ball: (x, y), + previous_ball: acc.ball, + ..acc + } + } else if tile == Intcode::from(3) { + Screen { + paddle: (x.clone(), y.clone()), + screen: acc.screen.insert((x, y), tile), + ..acc + } + } else if tile == Intcode::from(0) { + Screen { + screen: acc.screen.remove(&(x, y)), + ..acc + } + } else { + Screen { + screen: acc.screen.insert((x, y), tile), + ..acc + } + } + }) + } + + fn paddle_required_direction(&self) -> Intcode { + match self.paddle.0.cmp(&self.ball.0) { + Ordering::Less => Intcode::from(1), + Ordering::Equal => Intcode::from(0), + Ordering::Greater => Intcode::from(-1), + } + } +} + +fn count_blocks(output: &Vector) -> usize { + Screen::render(output) + .screen + .values() + .filter(|val| **val == Intcode::from(2)) + .count() +} + +fn score_on_won_game(program: IntcodeProgram) -> Intcode { + Screen::render( + &iter::successors(Some(program.run_to_termination_or_input()), |program| { + Some(next_game_state(program.clone())) + }) + .take_while(|program| !program.halted) + .find(|program| count_blocks(&program.output) == 0) + .unwrap() + .output, + ) + .score +} + +fn next_game_state(program: IntcodeProgram) -> IntcodeProgram { + program_with_next_input(program.run_to_termination_or_input()) +} + +fn program_with_next_input(program: IntcodeProgram) -> IntcodeProgram { + program.with_input(list![next_input(&program.output)]) +} + +fn next_input(output: &Vector) -> Intcode { + Screen::render(output).paddle_required_direction() +} diff --git a/2019/src/bin/day_14.rs b/2019/src/bin/day_14.rs new file mode 100644 index 0000000..0532f5f --- /dev/null +++ b/2019/src/bin/day_14.rs @@ -0,0 +1,221 @@ +use rpds::map::red_black_tree_map::RedBlackTreeMap; +use rpds::rbt_map; +use rpds::vector::Vector; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 14: Space Stoichiometry")] +/// Finds how much ore you need to produce one fuel. +/// +/// Recipes are passed in on stdin, one per line. +/// +/// See https://adventofcode.com/2019/day/14 for details. +struct Opt { + #[structopt(long = "available-ore")] + available_ore: Option, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let recipes = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid recipe")) + .collect::>(); + + match opt.available_ore { + Some(ore) => println!("{}", max_fuel_production(ore, &recipes)), + None => println!("{}", Desires::new(1).min_ore_required(&recipes)), + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn max_fuel_production(ore_max: i64, recipes: &[Recipe]) -> i64 { + binary_search_max_fuel_production( + ore_max / Desires::new(1).min_ore_required(&recipes), + 2 * ore_max / Desires::new(1).min_ore_required(&recipes), + ore_max, + recipes, + ) +} + +fn binary_search_max_fuel_production( + fuel_min: i64, + fuel_max: i64, + ore_max: i64, + recipes: &[Recipe], +) -> i64 { + if fuel_max - fuel_min <= 1 { + fuel_min + } else if Desires::new((fuel_min + fuel_max) / 2).min_ore_required(recipes) <= ore_max { + binary_search_max_fuel_production((fuel_min + fuel_max) / 2, fuel_max, ore_max, recipes) + } else { + binary_search_max_fuel_production(fuel_min, (fuel_min + fuel_max) / 2, ore_max, recipes) + } +} + +#[derive(Debug, Clone)] +struct Recipe { + ingredients: Vector, + output: Chemical, +} + +#[derive(Default, Debug, Clone)] +struct Chemical { + name: String, + quantity: i64, +} + +impl FromStr for Recipe { + type Err = ParseErr; + fn from_str(s: &str) -> Result { + // 2 XSNKB, 15 ZVMCB, 3 KDFNZ => 2 RFLX + s.replace(" => ", "=") + .replace(", ", ",") + .split(|c| c == ',' || c == '=') + .map(|chem| chem.parse::()) + .collect::, ParseErr>>() + .map(|chemicals| Recipe { + ingredients: chemicals + .drop_last() + .expect("Assertion failed: line did not have any chemicals"), + output: chemicals + .last() + .cloned() + .expect("Assertion failed: line did not have any chemicals"), + }) + } +} + +impl Recipe { + fn required_scale(&self, desired_quantity: i64) -> i64 { + (desired_quantity + self.output.quantity - 1) / self.output.quantity + } +} + +impl FromStr for Chemical { + type Err = ParseErr; + fn from_str(s: &str) -> Result { + // 1 FUEL + match s.split(' ').collect::>()[..] { + [quantity, name] => quantity + .parse::() + .map_err(|_| ParseErr) + .map(|q| Chemical { + name: name.to_string(), + quantity: q, + }), + _ => Err(ParseErr), + } + } +} + +impl Chemical { + fn scale(&self, scale: i64) -> Chemical { + Chemical { + name: self.name.clone(), + quantity: self.quantity * scale, + } + } +} + +#[derive(Debug, Clone, Copy)] +struct ParseErr; + +impl fmt::Display for ParseErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Error parsing input") + } +} + +impl std::error::Error for ParseErr {} + +#[derive(Debug, Clone)] +struct Desires { + chemicals: RedBlackTreeMap, +} + +impl Desires { + fn new(fuel: i64) -> Desires { + Desires { + chemicals: rbt_map!["FUEL".to_string() => fuel, "ORE".to_string() => 0], + } + } + + fn min_ore_required(&self, recipes: &[Recipe]) -> i64 { + iter::successors(Some(self.clone()), |prev| Some(prev.next(recipes))) + .find(|desires| desires.is_only_ore()) + .unwrap() + .chemicals + .get("ORE") + .cloned() + .unwrap() + } + + fn is_only_ore(&self) -> bool { + !self + .chemicals + .iter() + .any(|(name, quantity)| *quantity > 0 && name != "ORE") + } + + fn next(&self, recipes: &[Recipe]) -> Desires { + self.chemicals + .iter() + .find(|(name, quantity)| **quantity > 0 && *name != "ORE") + .map(|(mixing, quantity)| { + self.with_mixed_recipe( + recipes + .iter() + .find(|recipe| recipe.output.name == *mixing) + .expect("Required chemical without a recipe"), + *quantity, + ) + }) + .unwrap_or(self.clone()) + } + + fn with_mixed_recipe(&self, recipe: &Recipe, desired_quantity: i64) -> Desires { + recipe.ingredients.iter().fold( + self.with_chemical( + recipe + .output + .scale(-1 * recipe.required_scale(desired_quantity)), + ), + |acc, next_ingredient| { + acc.with_chemical(next_ingredient.scale(recipe.required_scale(desired_quantity))) + }, + ) + } + + fn with_chemical(&self, chemical: Chemical) -> Desires { + Desires { + chemicals: match self.chemicals.get(&chemical.name) { + Some(existing_quantity) => self + .chemicals + .insert(chemical.name.clone(), existing_quantity + chemical.quantity), + None => self + .chemicals + .insert(chemical.name.clone(), chemical.quantity), + }, + } + } +} diff --git a/2019/src/bin/day_15.rs b/2019/src/bin/day_15.rs new file mode 100644 index 0000000..b2205bb --- /dev/null +++ b/2019/src/bin/day_15.rs @@ -0,0 +1,183 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::rbt_set; +use rpds::set::red_black_tree_set::RedBlackTreeSet; +use rpds::vector; +use rpds::vector::Vector; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 15: Oxygen System")] +/// Executes an Intcode robot that's searching a map. Prints the +/// time taken for oxygen to propagate to the whole area. +/// +/// See https://adventofcode.com/2019/day/15 for details. +struct Opt { + /// Run in 'find' mode, find the oxygen tank but don't see how long it takes the oxygen to propagate + #[structopt(short = "f")] + find: 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::(), "Invalid number")) + .collect::(); + + if opt.find { + println!("{}", shortest_distance(program)); + } else { + println!("{}", max_depth_from_oxygen(program)); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn shortest_distance(program: IntcodeProgram) -> usize { + iter::successors( + Some(( + rbt_set![(0, 0)], + vector![((0, 0), program.run_to_termination_or_input())], + )), + |(visited, programs)| { + Some(next_depth_states( + visited.clone(), + next_program_states(programs, visited), + )) + }, + ) + .enumerate() + .find(|(_i, (_visited, programs))| { + programs + .iter() + .any(|(_location, program)| program.output == vector![2.into()]) + }) + .unwrap() + .0 +} + +fn max_depth_from_oxygen(program: IntcodeProgram) -> usize { + max_depth( + iter::successors( + Some(( + rbt_set![(0, 0)], + vector![((0, 0), program.run_to_termination_or_input())], + )), + |(visited, programs)| { + Some(next_depth_states( + visited.clone(), + next_program_states(programs, visited), + )) + }, + ) + .find(|(_visited, programs)| { + programs + .iter() + .any(|(_location, program)| program.output == vector![2.into()]) + }) + .unwrap() + .1 + .iter() + .find(|(_location, program)| program.output == vector![2.into()]) + .cloned() + .unwrap() + .1, + ) +} + +fn max_depth(program: IntcodeProgram) -> usize { + iter::successors( + Some(( + rbt_set![(0, 0)], + vector![((0, 0), program.run_to_termination_or_input())], + )), + |(visited, programs)| { + Some(next_depth_states( + visited.clone(), + next_program_states(programs, visited), + )) + }, + ) + .take_while(|(_visited, programs)| programs.len() > 0) + .count() + - 1 +} + +fn inputs() -> [((i32, i32), Intcode); 4] { + [ + ((0, 1), Intcode::from(1)), + ((0, -1), Intcode::from(2)), + ((1, 0), Intcode::from(3)), + ((-1, 0), Intcode::from(4)), + ] +} + +fn next_program_states( + programs: &Vector<((i32, i32), IntcodeProgram)>, + visited: &RedBlackTreeSet<(i32, i32)>, +) -> Vector<((i32, i32), IntcodeProgram)> { + let inputs = inputs(); + programs + .iter() + .flat_map(|(location, program)| { + inputs.iter().map(move |(vec, input)| { + ( + (location.0 + vec.0, location.1 + vec.1), + program + .with_cleared_output() + .with_input(list![input.clone()]) + .run_to_termination_or_input(), + ) + }) + }) + .filter(|(location, program)| { + !visited.contains(location) && program.output != vector![0.into()] + }) + .collect() +} + +fn next_depth_states( + previous_visited: RedBlackTreeSet<(i32, i32)>, + programs: Vector<((i32, i32), IntcodeProgram)>, +) -> ( + RedBlackTreeSet<(i32, i32)>, + Vector<((i32, i32), IntcodeProgram)>, +) { + ( + programs + .iter() + .fold(previous_visited, |acc, (next, _)| acc.insert(*next)), + dedup_locations(programs), + ) +} + +fn dedup_locations( + programs: Vector<((i32, i32), IntcodeProgram)>, +) -> Vector<((i32, i32), IntcodeProgram)> { + programs.iter().fold(Vector::new(), |acc, next| { + if acc.iter().any(|(loc, _)| *loc == next.0) { + acc + } else { + acc.push_back(next.clone()) + } + }) +} diff --git a/2019/src/bin/day_16.rs b/2019/src/bin/day_16.rs new file mode 100644 index 0000000..aa53127 --- /dev/null +++ b/2019/src/bin/day_16.rs @@ -0,0 +1,112 @@ +use rayon::prelude::*; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::num::ParseIntError; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 16: Flawed Frequency Transmission")] +/// Performs the flawed frequency transform of a number. +/// +/// See https://adventofcode.com/2019/day/16 for details. +struct Opt { + /// the offset after which you start reading output + #[structopt(short = "o", long = "offset", default_value = "0")] + offset: usize, + input_repeats: usize, + fft_repeats: usize, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(parse(&x), "Input was not a valid recipe")) + .for_each(|input| { + println!( + "{}", + transform(input, opt.input_repeats, opt.fft_repeats, opt.offset) + .into_iter() + .map(|c| c.to_string()) + .collect::() + ); + }); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn parse(s: &str) -> Result, ParseIntError> { + s.chars().map(|c| c.to_string().parse::()).collect() +} + +fn transform(input: Vec, input_repeats: usize, fft_repeats: usize, offset: usize) -> Vec { + iter::successors( + Some( + input + .iter() + .cycle() + .take(input.len() * input_repeats) + .cloned() + .collect::>(), + ), + |input| Some(next_phase(input, offset)), + ) + .nth(fft_repeats) + .unwrap() + .into_iter() + .skip(offset) + .take(8) + .collect() +} + +fn next_phase(input: &Vec, offset: usize) -> Vec { + if offset > input.len() / 2 { + (0..input.len()) + .into_par_iter() + .map(|digit| { + if digit < offset { + 0 + } else { + input.iter().skip(digit).sum::().abs() % 10 + } + }) + .collect() + } else { + (0..input.len()) + .into_par_iter() + .map(|digit| { + input + .iter() + .zip(pattern(digit)) + .map(|(x, y)| x * y) + .sum::() + .abs() + % 10 + }) + .collect() + } +} + +fn pattern(digit: usize) -> impl Iterator { + iter::repeat(0) + .take(digit + 1) + .chain(iter::repeat(1).take(digit + 1)) + .chain(iter::repeat(0).take(digit + 1)) + .chain(iter::repeat(-1).take(digit + 1)) + .cycle() + .skip(1) +} diff --git a/2019/src/bin/day_17.rs b/2019/src/bin/day_17.rs new file mode 100644 index 0000000..e85373c --- /dev/null +++ b/2019/src/bin/day_17.rs @@ -0,0 +1,78 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 17: Set and Forget")] +/// Pilots a vacuum robot around on a scaffold. What could go wrong? +/// +/// See https://adventofcode.com/2019/day/17 for details. +struct Opt { + /// Draw the map and exit + #[structopt(short = "d")] + draw_map: 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::(), "Invalid number")) + .collect::(); + + let result = exit_on_failed_assertion( + if opt.draw_map { + program.execute() + } else { + // L,12,L,8,R,10,R,10,L,6,L,4,L,12,L,12,L,8,R,10,R,10,L,6,L,4,L,12,R,10,L,8,L,4,R,10,L,6,L,4,L,12,L,12,L,8,R,10,R,10,R,10,L,8,L,4,R,10,L,6,L,4,L,12,R,10,L,8,L,4,R,10 + // | | || + + let input = vec![ + "A,B,A,B,C,B,A,C,B,C\n", + "L,12,L,8,R,10,R,10\n", + "L,6,L,4,L,12\n", + "R,10,L,8,L,4,R,10\n", + "y\n", + ]; + program + .with_mem_0(Intcode::from(2)) + .with_input( + input + .iter() + .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) + .collect(), + ) + .execute() + }, + "Program failed", + ); + + println!( + "{}", + result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", result.last().unwrap()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} diff --git a/2019/src/bin/day_18.rs b/2019/src/bin/day_18.rs new file mode 100644 index 0000000..255baa0 --- /dev/null +++ b/2019/src/bin/day_18.rs @@ -0,0 +1,365 @@ +use rpds::rbt_set; +use rpds::vector::Vector; +use rpds::RedBlackTreeMap; +use rpds::RedBlackTreeSet; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 18: Many-Worlds Interpretation")] +/// Finds the shortest path through a maze with keys +/// +/// See https://adventofcode.com/2019/day/18 for details. +struct Opt {} + +fn main() { + let stdin = io::stdin(); + let _opt = Opt::from_args(); + + let maze: Maze = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .collect(); + + println!("{}", maze.shortest_route()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +struct Maze { + blocks: Vec>, + start: BoardState, + keys: KeySet, +} + +impl FromIterator for Maze { + fn from_iter>(iter: T) -> Self { + Maze::from_blocks( + iter.into_iter() + .map(|line| line.chars().collect()) + .collect(), + ) + } +} + +impl Maze { + fn from_blocks(blocks: Vec>) -> Maze { + Maze { + start: BoardState { + robots: blocks + .iter() + .enumerate() + .flat_map(|(y, line)| { + line.iter() + .enumerate() + .filter(|(_x, ch)| **ch == '@') + .map(move |(x, _ch)| Location { x, y }) + }) + .collect(), + keys: KeySet::default(), + }, + keys: blocks + .iter() + .flat_map(|line| line.iter()) + .fold(KeySet::default(), |acc, next| acc.add_key(*next)), + blocks, + } + } + + fn block_at(&self, location: &Location) -> Option { + self.blocks + .get(location.y) + .and_then(|line| line.get(location.x)) + .cloned() + } + + fn shortest_route(&self) -> usize { + iter::successors( + Some(( + ExploredStates::default().insert(&self.start), + rbt_set![self.start.clone()], + )), + |(explored, locations)| { + Some(Maze::next_depth_states( + explored.clone(), + self.next_locations(locations, explored), + )) + }, + ) + // .inspect(|(explored, states)| eprintln!("{:?}", states)) + .take_while(|(_explored, states)| states.size() > 0) + .enumerate() + .find(|(_i, (_explored, states))| states.iter().any(|state| state.keys == self.keys)) + .unwrap() + .0 + } + + fn next_depth_states( + explored: ExploredStates, + locations: RedBlackTreeSet, + ) -> (ExploredStates, RedBlackTreeSet) { + ( + locations + .iter() + .fold(explored, |acc, next| acc.insert(next)), + locations, + ) + } + + fn next_locations( + &self, + locations: &RedBlackTreeSet, + explored: &ExploredStates, + ) -> RedBlackTreeSet { + locations + .iter() + .flat_map(|current| { + (0..current.robots.len()).flat_map(move |i_robot| { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .iter() + .map(move |(dx, dy)| current.next(i_robot, *dx, *dy)) + .map(move |(state, new_location)| { + self.block_at(&new_location) + .map(|c| state.with_key(c)) + .unwrap_or(state) + }) + }) + }) + .filter(|state| self.is_open(state)) + .filter(|state| !explored.contains(state)) + .collect() + } + + fn is_open(&self, state: &BoardState) -> bool { + state.robots.iter().all(|location| { + self.block_at(location) + .map(|c| Maze::char_is_open(c, state.keys)) + .unwrap_or(false) + }) + } + + fn char_is_open(c: char, keys: KeySet) -> bool { + c != '#' && !keys.door_is_locked(c) + } +} + +#[derive(Default, Debug, Clone)] +struct ExploredStates { + for_key: RedBlackTreeMap, +} + +#[derive(Default, Debug, Clone)] +struct ExploredStatesForKey { + robots: Vector>, +} + +impl ExploredStates { + fn insert(&self, new: &BoardState) -> ExploredStates { + ExploredStates { + for_key: self.for_key.insert( + new.keys.clone(), + self.for_key + .get(&new.keys) + .map(|current| ExploredStatesForKey { + robots: current + .robots + .iter() + .zip(new.robots.iter()) + .map(|(current_explored, robot)| current_explored.insert(robot.clone())) + .collect(), + }) + .unwrap_or_else(|| ExploredStatesForKey { + robots: new + .robots + .iter() + .map(|robot| RedBlackTreeSet::new().insert(robot.clone())) + .collect(), + }), + ), + } + } + + fn contains(&self, state: &BoardState) -> bool { + self.for_key + .get(&state.keys) + .filter(|for_key| { + state + .robots + .iter() + .zip(for_key.robots.iter()) + .all(|(r_state, r_explored)| r_explored.contains(r_state)) + }) + .is_some() + } +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct BoardState { + robots: Vector, + keys: KeySet, +} + +impl BoardState { + fn next(&self, i_robot: usize, dx: isize, dy: isize) -> (BoardState, Location) { + ( + BoardState { + robots: self + .robots + .set(i_robot, self.robots[i_robot].next(dx, dy)) + .unwrap(), + ..self.clone() + }, + self.robots[i_robot].next(dx, dy), + ) + } + + fn with_key(&self, c: char) -> BoardState { + BoardState { + keys: self.keys.add_key(c), + ..self.clone() + } + } +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct Location { + x: usize, + y: usize, +} + +impl Location { + fn next(&self, dx: isize, dy: isize) -> Location { + Location { + x: (self.x as isize + dx) as usize, + y: (self.y as isize + dy) as usize, + } + } +} + +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct KeySet { + bitset: u32, +} + +impl KeySet { + fn add_key(self, key: char) -> KeySet { + KeySet { + bitset: self.bitset | KeySet::key_to_bitset(key), + } + } + + fn door_is_locked(self, door: char) -> bool { + KeySet::door_to_bitset(door) & (!self.bitset) > 0 + } + + fn key_to_bitset(key: char) -> u32 { + if key.is_ascii_alphabetic() && key.is_ascii_lowercase() { + 1 << (key as u8 - b'a') + } else { + 0 + } + } + + fn door_to_bitset(door: char) -> u32 { + if door.is_ascii_alphabetic() && door.is_ascii_uppercase() { + 1 << (door as u8 - b'A') + } else { + 0 + } + } +} + +#[test] +fn doors_are_locked_without_key() { + assert_eq!(true, KeySet::default().door_is_locked('A')) +} + +#[test] +fn doors_are_unlocked_with_key() { + assert_eq!(false, KeySet::default().add_key('a').door_is_locked('A')) +} + +#[test] +fn example_1() { + let maze: Maze = r" +######### +#b.A.@.a# +######### +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 8); +} + +#[test] +fn example_2() { + let maze: Maze = r" +################# +#i.G..c...e..H.p# +########.######## +#j.A..b...f..D.o# +########@######## +#k.E..a...g..B.n# +########.######## +#l.F..d...h..C.m# +################# +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 136); +} + +#[test] +fn example_3() { + let maze: Maze = r" +############# +#DcBa.#.GhKl# +#.###@#@#I### +#e#d#####j#k# +###C#@#@###J# +#fEbA.#.FgHi# +############# +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 32); +} + +#[test] +fn example_4() { + let maze: Maze = r" +############# +#g#f.D#..h#l# +#F###e#E###.# +#dCba@#@BcIJ# +############# +#nK.L@#@G...# +#M###N#H###.# +#o#m..#i#jk.# +############# +" + .split('\n') + .map(|s| s.to_string()) + .collect(); + + assert_eq!(maze.shortest_route(), 74); +} diff --git a/2019/src/bin/day_19.rs b/2019/src/bin/day_19.rs new file mode 100644 index 0000000..73c8374 --- /dev/null +++ b/2019/src/bin/day_19.rs @@ -0,0 +1,102 @@ +use aoc2019::*; +use cached::cached_key; +use cached::UnboundCache; +use rpds::list; +use rpds::list::List; +use rpds::vector; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 19: Tractor Beam")] +/// Finds the effective area of a tractor beam in an n x n square, and +/// how far away you need to be to capture Santa's ship. +/// +/// See https://adventofcode.com/2019/day/19 for details. +struct Opt { + /// The size for a diagnostics scan. + #[structopt(long = "diagnostics-size")] + diagnostics_size: Option, + /// The size of Santa's ship + #[structopt(long = "ship-size")] + ship_size: 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::(); + + if let Some(size) = opt.diagnostics_size { + println!("{}", count_active_in_area(program.clone(), 0, 0, size)); + } + if let Some(size) = opt.ship_size { + println!("{:?}", find_closest_ship_space(program, size)) + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn count_active_in_area(program: IntcodeProgram, left: usize, top: usize, size: usize) -> usize { + (left..left + size) + .flat_map(|x| (top..top + size).map(move |y| (x, y))) + .filter(|(x, y)| tractor_beam_is_active(program.clone(), *x, *y)) + .count() +} + +fn area_is_all_full(program: IntcodeProgram, left: usize, top: usize, size: usize) -> bool { + // This check with a grid that's aligned to 10 gives an early exit + // for most, that will have the program executions shared. This + // makes the memoized tractor function more effective at cutting + // down on execution, even though you need to do the whole lot + // again to verify if this passes. + (left..left + size) + .flat_map(|x| (top..top + size).map(move |y| (x, y))) + .filter(|(x, y)| x % 10 == 0 && y % 10 == 0) + .all(|(x, y)| tractor_beam_is_active(program.clone(), x, y)) + && (left..left + size) + .flat_map(|x| (top..top + size).map(move |y| (x, y))) + .all(|(x, y)| tractor_beam_is_active(program.clone(), x, y)) +} + +fn find_closest_ship_space(program: IntcodeProgram, size: usize) -> (usize, usize) { + (0..) + .flat_map(|radius| { + (0..radius) + .flat_map(move |x| (0..radius).map(move |y| (x, y))) + .filter(move |(x, y)| { + (radius - 1) * (radius - 1) < x * x + y * y && x * x + y * y <= radius * radius + }) + }) + .find(|(x, y)| area_is_all_full(program.clone(), *x, *y, size)) + .unwrap() +} + +cached_key! { + TRACTOR_BEAM_IS_ACTIVE: UnboundCache<(usize, usize), bool> = UnboundCache::new(); + Key = { (x, y) }; + fn tractor_beam_is_active(program: IntcodeProgram, x: usize, y: usize) -> bool = { + program + .with_input(list![Intcode::from(x), Intcode::from(y)]) + .execute() + == Ok(vector![Intcode::from(1)]) + + } +} 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)) +} diff --git a/2019/src/bin/day_20.rs b/2019/src/bin/day_20.rs new file mode 100644 index 0000000..953df75 --- /dev/null +++ b/2019/src/bin/day_20.rs @@ -0,0 +1,310 @@ +use rpds::rbt_set; +use rpds::vector::Vector; +use rpds::RedBlackTreeMap; +use rpds::RedBlackTreeSet; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 20: Donut Maze")] +/// Finds the shortest path through a maze with portals. +/// +/// See https://adventofcode.com/2019/day/20 for details. +struct Opt { + /// include the rule that going through portals changes your depth + #[structopt(short = "d")] + include_depth: bool, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let maze = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .collect::() + .build(); + + println!("{}", maze.shortest_route(opt.include_depth)); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +struct MazeBuilder { + map: Vector>, +} + +impl FromIterator for MazeBuilder { + fn from_iter>(iter: T) -> Self { + MazeBuilder { + map: iter + .into_iter() + .map(|line| line.chars().collect()) + .collect(), + } + } +} + +impl MazeBuilder { + fn build(self) -> Maze { + Maze { + walls: self + .map + .iter() + .map(|line| line.iter().map(|ch| *ch != '.').collect()) + .collect(), + portals: self.grouped_portals(), + entrance: self + .all_portals() + .find(|(id, _)| *id == ['A', 'A']) + .unwrap() + .1, + exit: self + .all_portals() + .find(|(id, _)| *id == ['Z', 'Z']) + .unwrap() + .1, + } + } + + fn grouped_portals(&self) -> Vector<(Point, Point)> { + self.all_portals() + .fold( + (Vector::new(), RedBlackTreeMap::new()), + |(matched, unmatched): ( + Vector<(Point, Point)>, + RedBlackTreeMap<[char; 2], Point>, + ), + (next_id, next_p)| match unmatched.get(&next_id) { + Some(pair) => ( + matched.push_back(pair.clone().inside_out( + next_p, + self.map[0].len(), + self.map.len(), + )), + unmatched.remove(&next_id), + ), + None => (matched, unmatched.insert(next_id, next_p)), + }, + ) + .0 + } + + fn all_portals(&self) -> impl Iterator + '_ { + self.horizontal_trailing_portals() + .chain(self.horizontal_leading_portals()) + .chain(self.vertical_trailing_portals()) + .chain(self.vertical_leading_portals()) + } + + fn horizontal_trailing_portals(&self) -> impl Iterator + '_ { + // .XX + (0..self.map.len()) + .flat_map(move |y| (0..self.map[y].len() - 2).map(move |x| Point { x, y })) + .filter(move |p| { + self.map[p.y][p.x] == '.' + && self.map[p.y][p.x + 1].is_alphabetic() + && self.map[p.y][p.x + 2].is_alphabetic() + }) + .map(move |p| ([self.map[p.y][p.x + 1], self.map[p.y][p.x + 2]], p)) + } + + fn horizontal_leading_portals(&self) -> impl Iterator + '_ { + // XX. + (0..self.map.len()) + .flat_map(move |y| (0..self.map[y].len() - 2).map(move |x| Point { x, y })) + .filter(move |p| { + self.map[p.y][p.x + 2] == '.' + && self.map[p.y][p.x + 1].is_alphabetic() + && self.map[p.y][p.x].is_alphabetic() + }) + .map(move |p| { + ( + [self.map[p.y][p.x], self.map[p.y][p.x + 1]], + Point { x: p.x + 2, y: p.y }, + ) + }) + } + + fn vertical_trailing_portals(&self) -> impl Iterator + '_ { + // .XX + (0..self.map[0].len()) + .flat_map(move |x| (0..self.map.len() - 2).map(move |y| Point { x, y })) + .filter(move |p| { + self.map[p.y][p.x] == '.' + && self.map[p.y + 1][p.x].is_alphabetic() + && self.map[p.y + 2][p.x].is_alphabetic() + }) + .map(move |p| ([self.map[p.y + 1][p.x], self.map[p.y + 2][p.x]], p)) + } + + fn vertical_leading_portals(&self) -> impl Iterator + '_ { + // XX. + (0..self.map[0].len()) + .flat_map(move |x| (0..self.map.len() - 2).map(move |y| Point { x, y })) + .filter(move |p| { + self.map[p.y + 2][p.x] == '.' + && self.map[p.y + 1][p.x].is_alphabetic() + && self.map[p.y][p.x].is_alphabetic() + }) + .map(move |p| { + ( + [self.map[p.y][p.x], self.map[p.y + 1][p.x]], + Point { x: p.x, y: p.y + 2 }, + ) + }) + } +} + +#[derive(Debug)] +struct Maze { + walls: Vector>, + portals: Vector<(Point, Point)>, + entrance: Point, // AA + exit: Point, // ZZ +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct Point { + x: usize, + y: usize, +} + +impl Point { + fn add(&self, x: isize, y: isize) -> Point { + Point { + x: (self.x as isize + x) as usize, + y: (self.y as isize + y) as usize, + } + } + + fn inside_out(self, other: Point, width: usize, height: usize) -> (Point, Point) { + if self.closest_side(width, height) > other.closest_side(width, height) { + (self, other) + } else { + (other, self) + } + } + + fn closest_side(&self, width: usize, height: usize) -> usize { + self.x.min(width - self.x).min(self.y).min(height - self.y) + } +} + +impl Maze { + fn shortest_route(&self, include_depth: bool) -> usize { + iter::successors( + Some(( + rbt_set![(self.entrance.clone(), 0)], + rbt_set![(self.entrance.clone(), 0)], + )), + |(explored, locations)| { + Some(Maze::next_depth_states( + explored.clone(), + self.next_locations(locations, explored, include_depth), + )) + }, + ) + // .inspect(|(explored, states)| eprintln!("{:?}", states)) + .take_while(|(_explored, states)| states.size() > 0) + .enumerate() + .find(|(_i, (_explored, states))| { + states + .iter() + .any(|(p_state, depth)| *p_state == self.exit && (!include_depth || *depth == 0)) + }) + .unwrap() + .0 + } + + fn next_depth_states( + explored: RedBlackTreeSet<(Point, isize)>, + locations: RedBlackTreeSet<(Point, isize)>, + ) -> ( + RedBlackTreeSet<(Point, isize)>, + RedBlackTreeSet<(Point, isize)>, + ) { + ( + locations + .iter() + .fold(explored, |acc, next| acc.insert(next.clone())), + locations, + ) + } + + fn next_locations( + &self, + locations: &RedBlackTreeSet<(Point, isize)>, + explored: &RedBlackTreeSet<(Point, isize)>, + include_depth: bool, + ) -> RedBlackTreeSet<(Point, isize)> { + locations + .iter() + .flat_map(|(p, depth)| { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .iter() + .map(move |(dx, dy)| (p.add(*dx, *dy), *depth)) + .chain( + self.portals + .iter() + .filter(move |(from, _to)| p == from) + .map(move |(_from, to)| (to.clone(), depth + 1)), + ) + .chain( + self.portals + .iter() + .filter(move |(_to, from)| p == from) + .map(move |(to, _from)| (to.clone(), depth - 1)), + ) + }) + .filter(|(p_next, depth)| { + !self.walls[p_next.y][p_next.x] && (!include_depth || *depth >= 0) + }) + .filter(|state| !explored.contains(state)) + .collect() + } +} + +#[test] +fn portal_maze_example_1() { + let maze: Maze = r" A + A + #######.######### + #######.........# + #######.#######.# + #######.#######.# + #######.#######.# + ##### B ###.# +BC...## C ###.# + ##.## ###.# + ##...DE F ###.# + ##### G ###.# + #########.#####.# +DE..#######...###.# + #.#########.###.# +FG..#########.....# + ###########.##### + Z + Z " + .split('\n') + .map(|s| s.to_string()) + .collect::() + .build(); + + assert_eq!(maze.shortest_route(false), 23); + assert_eq!(maze.shortest_route(true), 26); +} diff --git a/2019/src/bin/day_21.rs b/2019/src/bin/day_21.rs new file mode 100644 index 0000000..7fa781c --- /dev/null +++ b/2019/src/bin/day_21.rs @@ -0,0 +1,109 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 21: Springdroid Adventure")] +/// Pilots a springdroid around! +/// +/// See https://adventofcode.com/2019/day/21 for details. +struct Opt {} + +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::(); + + let walk_result = exit_on_failed_assertion( + { + let input = vec![ + "NOT T T\n", + "AND A T\n", + "AND B T\n", + "AND C T\n", + "NOT T J\n", + "AND D J\n", + "WALK\n", + ]; + program + .with_input( + input + .iter() + .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) + .collect(), + ) + .execute() + }, + "Program failed", + ); + + println!( + "{}", + walk_result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", walk_result.last().unwrap()); + + let run_result = exit_on_failed_assertion( + { + // (!A || !B || !C) && D && (E || H) + let input = vec![ + "OR E J\n", + "OR H J\n", + "AND D J\n", + "NOT T T\n", + "AND A T\n", + "AND B T\n", + "AND C T\n", + "NOT T T\n", + "AND T J\n", + "RUN\n", + ]; + program + .with_input( + input + .iter() + .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) + .collect(), + ) + .execute() + }, + "Program failed", + ); + + println!( + "{}", + run_result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", run_result.last().unwrap()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} diff --git a/2019/src/bin/day_22.rs b/2019/src/bin/day_22.rs new file mode 100644 index 0000000..5b999a6 --- /dev/null +++ b/2019/src/bin/day_22.rs @@ -0,0 +1,325 @@ +use derive_more::Display; +use num::bigint::BigInt; +use num::traits::identities::Zero; +use num::traits::sign::abs; +use num::traits::Signed; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 22: Slam Shuffle")] +/// Shuffles some cards. +/// +/// See https://adventofcode.com/2019/day/22 for details. +struct Opt { + /// The size of the deck + deck_size: BigInt, + /// At the end, query the position of card + card: BigInt, + /// Number of repetitions + repetitions: BigInt, + + /// Prints the card in position n, rather than the position of card n + #[structopt(short = "p")] + position_mode: bool, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let instructions = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Parse error")) + .collect::>(); + + //eprintln!("{:?}", instructions); + + if opt.position_mode { + println!( + "{}", + instructions + .iter() + .rev() + .fold( + StandardisedInstruction::identity(opt.deck_size.clone()), + |acc, next| acc.then(&(next.clone(), opt.deck_size.clone(), false).into()) + ) + .repeat(opt.repetitions) + .apply(opt.card.clone()) + ); + } else { + println!( + "{}", + instructions + .iter() + .fold( + StandardisedInstruction::identity(opt.deck_size.clone()), + |acc, next| { + eprintln!("{}", acc); + acc.then(&(next.clone(), opt.deck_size.clone(), true).into()) + } + ) + .repeat(opt.repetitions) + .apply(opt.card.clone()) + ); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +fn mod_plus(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + mod_normalize(a + b, modulus) +} + +fn mod_sub(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + mod_normalize(a - b, modulus) +} + +fn mod_times(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + mod_normalize(a * b, modulus) +} + +fn mod_divide(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + mod_times(a, mod_inverse(b, modulus.clone()), modulus) +} + +fn mod_pow(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { + a.modpow(&b, &modulus) +} + +fn mod_normalize(a: BigInt, modulus: BigInt) -> BigInt { + if a.is_negative() { + a.clone() + modulus.clone() * (1 + abs(a) / modulus) + } else { + a % modulus + } +} + +// NB: This may give nonsense if modulus isn't coprime with a +fn mod_inverse(a: BigInt, modulus: BigInt) -> BigInt { + mod_normalize(euclid_gcd_coefficients(a, modulus.clone()).0, modulus) +} + +fn euclid_gcd_coefficients(a: BigInt, b: BigInt) -> (BigInt, BigInt) { + fn euclid_gcd_coefficients_inner( + r: BigInt, + old_r: BigInt, + s: BigInt, + old_s: BigInt, + t: BigInt, + old_t: BigInt, + ) -> (BigInt, BigInt) { + if r.is_zero() { + (old_s, old_t) + } else { + euclid_gcd_coefficients_inner( + old_r.clone() - (old_r.clone() / r.clone()) * r.clone(), + r.clone(), + old_s - (old_r.clone() / r.clone()) * s.clone(), + s, + old_t - (old_r.clone() / r) * t.clone(), + t, + ) + } + } + + assert!(a < b); + + euclid_gcd_coefficients_inner(b, a, 0.into(), 1.into(), 1.into(), 0.into()) +} + +#[derive(Debug, Clone)] +enum Instruction { + DealIntoNewStack, + Cut(BigInt), + ReverseCut(BigInt), + DealWithIncrement(BigInt), +} + +impl FromStr for Instruction { + type Err = ParseErr; + fn from_str(s: &str) -> Result { + if s.starts_with("deal into new stack") { + Ok(Instruction::DealIntoNewStack) + } else if s.starts_with("cut -") { + s.split(' ') + .nth(1) + .map(|val| { + val.parse::() + .map_err(|_| ParseErr) + .map(|parsed| Instruction::ReverseCut(abs(parsed))) + }) + .unwrap_or(Err(ParseErr)) + } else if s.starts_with("cut") { + s.split(' ') + .nth(1) + .map(|val| { + val.parse::() + .map_err(|_| ParseErr) + .map(|parsed| Instruction::Cut(parsed)) + }) + .unwrap_or(Err(ParseErr)) + } else if s.starts_with("deal with increment") { + s.split(' ') + .nth(3) + .map(|val| { + val.parse::() + .map_err(|_| ParseErr) + .map(|parsed| Instruction::DealWithIncrement(parsed)) + }) + .unwrap_or(Err(ParseErr)) + } else { + Err(ParseErr) + } + } +} + +// f(x) = ax + b mod c +#[derive(Display, Clone)] +#[display(fmt = "f(x) = {} x + {} % {}", a, b, modulus)] +struct StandardisedInstruction { + a: BigInt, + b: BigInt, + modulus: BigInt, +} + +impl From<(Instruction, BigInt, bool)> for StandardisedInstruction { + fn from((instruction, modulus, forward): (Instruction, BigInt, bool)) -> Self { + match (instruction, forward) { + (Instruction::DealIntoNewStack, _) => StandardisedInstruction { + a: BigInt::from(-1), + b: BigInt::from(-1), + modulus: modulus, + }, + (Instruction::Cut(n), true) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(-n), + modulus: modulus, + }, + (Instruction::Cut(n), false) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(n), + modulus: modulus, + }, + (Instruction::ReverseCut(n), true) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(n), + modulus: modulus, + }, + (Instruction::ReverseCut(n), false) => StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(-n), + modulus: modulus, + }, + (Instruction::DealWithIncrement(n), true) => StandardisedInstruction { + a: BigInt::from(n), + b: BigInt::from(0), + modulus: modulus, + }, + (Instruction::DealWithIncrement(n), false) => StandardisedInstruction { + a: BigInt::from(mod_inverse(n, modulus.clone())), + b: BigInt::from(0), + modulus: modulus, + }, + } + .normalise() + } +} + +impl StandardisedInstruction { + fn identity(modulus: BigInt) -> StandardisedInstruction { + StandardisedInstruction { + a: BigInt::from(1), + b: BigInt::from(0), + modulus, + } + } + fn normalise(&self) -> StandardisedInstruction { + StandardisedInstruction { + a: mod_normalize(self.a.clone(), self.modulus.clone()), + b: mod_normalize(self.b.clone(), self.modulus.clone()), + modulus: self.modulus.clone(), + } + } + fn then(&self, other: &StandardisedInstruction) -> StandardisedInstruction { + // g(f(x)) = ga (fa x + fb) + gb = + StandardisedInstruction { + a: mod_times(self.a.clone(), other.a.clone(), self.modulus.clone()), + b: mod_plus( + mod_times(self.b.clone(), other.a.clone(), self.modulus.clone()), + other.b.clone(), + self.modulus.clone(), + ), + modulus: self.modulus.clone(), + } + } + fn repeat(&self, repetitions: BigInt) -> StandardisedInstruction { + StandardisedInstruction { + a: mod_pow(self.a.clone(), repetitions.clone(), self.modulus.clone()), + b: mod_divide( + mod_times( + self.b.clone(), + mod_sub( + BigInt::from(1), + mod_pow(self.a.clone(), repetitions.clone(), self.modulus.clone()), + self.modulus.clone(), + ), + self.modulus.clone(), + ), + mod_sub(BigInt::from(1), self.a.clone(), self.modulus.clone()), + self.modulus.clone(), + ), + modulus: self.modulus.clone(), + } + } + + fn apply(&self, x: BigInt) -> BigInt { + mod_plus( + mod_times(self.a.clone(), x, self.modulus.clone()), + self.b.clone(), + self.modulus.clone(), + ) + } +} + +#[derive(Debug, Clone, Copy)] +struct ParseErr; + +impl fmt::Display for ParseErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Error parsing input") + } +} + +impl std::error::Error for ParseErr {} + +#[test] +fn mod_inverse_of_13() { + assert_eq!(mod_inverse(1.into(), 13.into()), 1.into()); + assert_eq!(mod_inverse(2.into(), 13.into()), 7.into()); + assert_eq!(mod_inverse(3.into(), 13.into()), 9.into()); + assert_eq!(mod_inverse(4.into(), 13.into()), 10.into()); + assert_eq!(mod_inverse(5.into(), 13.into()), 8.into()); + assert_eq!(mod_inverse(6.into(), 13.into()), 11.into()); + assert_eq!(mod_inverse(7.into(), 13.into()), 2.into()); + assert_eq!(mod_inverse(8.into(), 13.into()), 5.into()); + assert_eq!(mod_inverse(9.into(), 13.into()), 3.into()); + assert_eq!(mod_inverse(10.into(), 13.into()), 4.into()); + assert_eq!(mod_inverse(11.into(), 13.into()), 6.into()); + assert_eq!(mod_inverse(12.into(), 13.into()), 12.into()); +} diff --git a/2019/src/bin/day_23.rs b/2019/src/bin/day_23.rs new file mode 100644 index 0000000..e074cf4 --- /dev/null +++ b/2019/src/bin/day_23.rs @@ -0,0 +1,211 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::vector::Vector; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 23: Category Six")] +/// Executes an Intcode program on a network of computers +/// +/// See https://adventofcode.com/2019/day/23 for details. +struct Opt { + #[structopt(short = "n", long = "network-size")] + network_size: usize, + #[structopt(long = "nat")] + send_nat: 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::(), "Invalid number")) + .collect::(); + + let network = Network::new(program, opt.network_size); + + if opt.send_nat { + println!("{}", network.first_repeated_nat_packet().y); + } else { + println!("{}", network.first_nat_packet().y); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug, Clone)] +struct Network { + computers: Vector, + nat: Option, + is_potentially_idle: bool, + is_idle: bool, +} + +impl Network { + fn new(program: IntcodeProgram, network_size: usize) -> Network { + Network { + computers: (0..network_size) + .map(|ip| program.with_input(list![ip.into(), Intcode::from(-1)])) + .collect(), + nat: None, + is_potentially_idle: false, + is_idle: false, + } + } + + fn first_nat_packet(&self) -> Packet { + iter::successors(Some(self.clone()), |network| Some(network.next())) + .filter_map(|network| network.nat) + .next() + .unwrap() + } + + fn first_repeated_nat_packet(&self) -> Packet { + self.sent_nat_packets() + .zip(self.sent_nat_packets().skip(1)) + // .inspect(|(nat, _p2)| eprintln!("{}", nat.y)) + .find(|(p1, p2)| p1.y == p2.y) + .unwrap() + .0 + } + + fn sent_nat_packets<'a>(&'a self) -> impl Iterator + 'a { + iter::successors(Some(self.clone()), |network| { + Some(network.with_nat_packet_sent().run_to_network_idle()) + }) + .filter_map(|network| network.nat) + } + + fn run_to_network_idle(&self) -> Network { + iter::successors(Some(self.clone()), |network| Some(network.next())) + .find(|network| network.is_idle) + .unwrap() + } + + fn with_nat_packet_sent(&self) -> Network { + if self.nat.is_some() { + Network { + computers: self + .computers + .iter() + .enumerate() + .map(|(ip, computer)| { + computer + .with_additional_input( + self.nat + .iter() + .filter(|packet| packet.dest == Intcode::from(ip)) + .flat_map(|packet| vec![packet.x.clone(), packet.y.clone()]) + .collect(), + ) + .run_to_termination_or_input() + }) + .collect(), + nat: self.nat.clone(), + is_potentially_idle: false, + is_idle: false, + } + } else { + self.clone() + } + } + + fn next(&self) -> Network { + Network { + computers: self + .computers + .iter() + .enumerate() + .map(|(ip, computer)| { + computer + .with_cleared_output() + .with_additional_input(if self.empty_queues() { + list![Intcode::from(-1)] + } else { + list![] + }) + .with_additional_input( + self.pending_packets() + .filter(|packet| packet.dest == Intcode::from(ip)) + .flat_map(|packet| vec![packet.x, packet.y]) + .collect(), + ) + .run_to_termination_or_input() + }) + .collect(), + nat: self + .pending_packets() + .filter(|packet| packet.is_nat()) + .map(|packet| packet.with_dest(0.into())) + .last() + .or_else(|| self.nat.clone()), + is_potentially_idle: self.empty_queues(), + is_idle: self.is_potentially_idle && self.empty_queues(), + } + } + + fn pending_packets<'a>(&'a self) -> impl Iterator + 'a { + self.computers.iter().flat_map(|computer| { + computer + .output + .iter() + .cloned() + .collect::>() + .chunks_exact(3) + .map(|packet| Packet { + dest: packet[0].clone(), + x: packet[1].clone(), + y: packet[2].clone(), + }) + .collect::>() + }) + } + + fn pending_input<'a>(&'a self) -> impl Iterator + 'a { + self.computers + .iter() + .flat_map(|computer| computer.input.iter().cloned().collect::>()) + } + + fn empty_queues(&self) -> bool { + self.pending_packets().count() == 0 && self.pending_input().count() == 0 + } +} + +#[derive(Debug, Clone)] +struct Packet { + dest: Intcode, + x: Intcode, + y: Intcode, +} + +impl Packet { + fn is_nat(&self) -> bool { + self.dest == 255.into() + } + + fn with_dest(&self, dest: Intcode) -> Packet { + Packet { + dest, + ..self.clone() + } + } +} diff --git a/2019/src/bin/day_24.rs b/2019/src/bin/day_24.rs new file mode 100644 index 0000000..ebc6a1b --- /dev/null +++ b/2019/src/bin/day_24.rs @@ -0,0 +1,239 @@ +use rpds::RedBlackTreeSet; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::iter::FromIterator; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 24: Planet of Discord")] +/// Simulates the life and death of Eris bugs +/// +/// See https://adventofcode.com/2019/day/24 for details. +struct Opt { + /// How many iterations of the game of life should be run + /// If not provided, runs until a state appears twice. + #[structopt(short = "n")] + depth: Option, + /// Interprets the map as being one part of an infinite fractal map + #[structopt(short = "f")] + fractal: bool, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let initial_state: State = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .collect::() + .with_fractal_mode(opt.fractal); + + let final_state = match opt.depth { + Some(depth) => initial_state.n_steps_forward(depth), + None => initial_state.first_repeated_state(), + }; + + println!("Bugs: {}", final_state.alive.size()); + println!("Biodiversity: {}", final_state.biodiversity_rating()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct State { + alive: RedBlackTreeSet, + fractal_mode: bool, +} + +impl FromIterator for State { + fn from_iter>(iter: T) -> Self { + State { + alive: iter + .into_iter() + .enumerate() + .flat_map(move |(y, line)| { + line.chars() + .enumerate() + .filter(move |(_x, c)| *c == '#') + .map(move |(x, _c)| Coordinate { + x: x as isize, + y: y as isize, + depth: 0, + }) + .collect::>() + }) + .collect(), + fractal_mode: false, + } + } +} + +impl State { + fn with_fractal_mode(&self, fractal_mode: bool) -> State { + State { + fractal_mode, + ..self.clone() + } + } + + fn n_steps_forward(&self, n: usize) -> Self { + iter::successors(Some(self.clone()), |state| Some(state.next())) + .nth(n) + .unwrap() + } + + fn first_repeated_state(&self) -> State { + iter::successors( + Some((RedBlackTreeSet::new(), self.clone())), + |(seen, state)| Some((seen.insert(state.clone()), state.next())), + ) + .find(|(seen, state)| seen.contains(state)) + .unwrap() + .1 + } + + fn next(&self) -> State { + State { + alive: self + .still_alive_next_round() + .chain(self.comes_alive_next_round()) + .collect(), + ..self.clone() + } + } + + fn biodiversity_rating(&self) -> usize { + self.alive + .iter() + .map(|coord| 2_usize.pow((coord.y * 5 + coord.x) as u32)) + .sum() + } + + fn still_alive_next_round<'a>(&'a self) -> impl Iterator + 'a { + self.alive + .iter() + .filter(move |coord| self.count_alive_neighbours(**coord) == 1) + .cloned() + } + + fn comes_alive_next_round<'a>(&'a self) -> impl Iterator + 'a { + self.alive + .iter() + .flat_map(move |coord| self.neighbours(*coord)) + .filter(move |coord| !self.alive.contains(coord)) + .filter(move |coord| { + self.count_alive_neighbours(*coord) == 1 || self.count_alive_neighbours(*coord) == 2 + }) + } + + fn count_alive_neighbours(&self, coordinate: Coordinate) -> usize { + self.neighbours(coordinate) + .into_iter() + .filter(|coord| self.alive.contains(coord)) + .count() + } + + fn neighbours(&self, coordinate: Coordinate) -> Vec { + if self.fractal_mode { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .into_iter() + .map(|(dx, dy)| Coordinate { + x: coordinate.x + dx, + y: coordinate.y + dy, + depth: coordinate.depth, + }) + .flat_map(move |coord| match (coord.x, coord.y) { + (x, _y) if x < 0 => vec![Coordinate { + x: 1, + y: 2, + depth: coord.depth - 1, + }] + .into_iter(), + (_x, y) if y < 0 => vec![Coordinate { + x: 2, + y: 1, + depth: coord.depth - 1, + }] + .into_iter(), + (x, _y) if x >= 5 => vec![Coordinate { + x: 3, + y: 2, + depth: coord.depth - 1, + }] + .into_iter(), + (_x, y) if y >= 5 => vec![Coordinate { + x: 2, + y: 3, + depth: coord.depth - 1, + }] + .into_iter(), + (2, 2) => match (coordinate.x, coordinate.y) { + (1, 2) => (0..5) + .map(|y| Coordinate { + x: 0, + y, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (2, 1) => (0..5) + .map(|x| Coordinate { + x, + y: 0, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (3, 2) => (0..5) + .map(|y| Coordinate { + x: 4, + y, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (2, 3) => (0..5) + .map(|x| Coordinate { + x, + y: 4, + depth: coord.depth + 1, + }) + .collect::>() + .into_iter(), + (_, _) => vec![].into_iter(), + }, + _ => vec![coord.clone()].into_iter(), + }) + .collect() + } else { + [(-1, 0), (1, 0), (0, -1), (0, 1)] + .into_iter() + .map(|(dx, dy)| Coordinate { + x: coordinate.x + dx, + y: coordinate.y + dy, + depth: coordinate.depth, + }) + .filter(|coord| coord.x >= 0 && coord.x < 5 && coord.y >= 0 && coord.y < 5) + .collect() + } + } +} + +#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] +struct Coordinate { + x: isize, + y: isize, + depth: isize, +} diff --git a/2019/src/bin/day_25.dot b/2019/src/bin/day_25.dot new file mode 100644 index 0000000..58dc131 --- /dev/null +++ b/2019/src/bin/day_25.dot @@ -0,0 +1,43 @@ +digraph { + Breach [label="Hull Breach"] + Crew [label="Crew Quarters (antenna)"] + Hallway [label="Hallway (weather machine)"] + Storage [label="Storage (klein bottle)"] + Stables [label="Stables (spool of cat6)"] + Warp [label="Warp Drive Maintenance"] + Security [label="Security Checkpoint"] + Pressure [label="Pressure-Sensitive Floor"] + Gift [label="Gift Wrapping Center"] + Sick [label="Sick Bay (infinite loop X)"] + Chocolate [label="Hot Chocolate Fountain (giant electromagnet X)"] + Observatory [label="Observatory (cake)"] + Navigation [label="Navigation (escape pod XX)"] + Corridor [label="Corridor"] + Holodeck [label="Holodeck (molten lava X)"] + Science [label="Science Lab (tambourine)"] + Passages [label="Passages (shell)"] + Engineering [label="Engineering"] + Arcade [label="Arcade (photons X)"] + Kitchen [label="Kitchen (mug)"] + + + Breach -> Crew [label=East] + Breach -> Hallway [label=North] + Hallway -> Storage [label=North] + Storage -> Stables [label=East] + Stables -> Warp [label=South] + Warp -> Security [label=South] + Security -> Pressure [label=East] + Stables -> Gift [label=East] + Gift -> Sick [label=North] + Sick -> Chocolate [label=West] + Chocolate -> Observatory [label=North] + Chocolate -> Navigation [label=West] + Corridor -> Holodeck [label=North] + Holodeck -> Science [label=North] + Sick -> Corridor [label=East] + Corridor -> Passages [label=South] + Passages -> Engineering [label=East] + Engineering -> Arcade [label=South] + Gift -> Kitchen [label=South] +} diff --git a/2019/src/bin/day_25.rs b/2019/src/bin/day_25.rs new file mode 100644 index 0000000..522789e --- /dev/null +++ b/2019/src/bin/day_25.rs @@ -0,0 +1,110 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 25: Cryostasis")] +/// Pilots a robot to save Santa! +/// +/// See https://adventofcode.com/2019/day/25 for details. +struct Opt {} + +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::(); + + let input = vec![ + "east", + "take antenna", + "west", + "north", + "take weather machine", + "north", + "take klein bottle", + "east", + "take spool of cat6", + "east", + "south", + "take mug", + "north", + "north", + "west", + "north", + "take cake", + "south", + "east", + "east", + "north", + "north", + "take tambourine", + "south", + "south", + "south", + "take shell", + "north", + "west", + "south", + "west", + "south", + "south", + "inv", + //"drop mug", + //"drop weather machine", + "drop cake", + "drop shell", + "drop klein bottle", + "drop tambourine", + //"drop antenna", + //"drop spool of cat6", + "east", + ]; + + let result = exit_on_failed_assertion( + program + .with_input( + input + .iter() + .flat_map(|line| { + line.chars() + .map(|c| Intcode::from(c as u8)) + .chain(vec![Intcode::from(10)].into_iter()) + }) + .collect(), + ) + .run_to_termination_or_input() + .output_into_result(), + "Program failed", + ); + + println!( + "{}", + result + .drop_last() + .unwrap() + .iter() + .flat_map(|c| c.to_signed_bytes_be()) + .map(|c| c as char) + .collect::() + ); + println!("{}", result.last().unwrap()); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} diff --git a/2019/src/bin/day_3.rs b/2019/src/bin/day_3.rs new file mode 100644 index 0000000..f4163bd --- /dev/null +++ b/2019/src/bin/day_3.rs @@ -0,0 +1,333 @@ +use rpds::vector::Vector; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 3: Crossed Wires")] +/// Finds the closest intersection between two wires. By default, +/// 'closest' is defined as closest in terms of Manhattan distance. If +/// --signal-distance is set, distance is defined in terms of the +/// total distance along the wire. +/// +/// See https://adventofcode.com/2019/day/3 for details. +struct Opt { + #[structopt(short = "s", long = "signal-distance")] + /// returns the closest intersection by signal distance. + signal_distance: bool, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let mut input = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid wire")); + + let (wire1, wire2) = match (input.next(), input.next()) { + (Some(w1), Some(w2)) => (w1, w2), + _ => { + eprintln!("Input must have two wires"); + process::exit(1); + } + }; + + match wire1.closest_collision(&wire2, opt.signal_distance) { + Some(c) => println!( + "{}", + if opt.signal_distance { + c.signal_distance + } else { + c.manhattan_distance() + } + ), + None => { + eprintln!("No collisions"); + 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); + } + } +} + +#[derive(Debug, Clone)] +struct Wire { + segments: Vector, +} + +impl FromStr for Wire { + type Err = UnknownError; + + fn from_str(s: &str) -> Result { + s.split(',') + .fold( + Ok(Vector::new()), + |acc: Result, UnknownError>, next_str| { + acc.and_then(|previous_segments| { + WireSegment::from_str( + previous_segments.last().map(|l| l.end()).unwrap_or((0, 0)), + previous_segments + .last() + .map(|l| l.end_signal_distance()) + .unwrap_or(0), + next_str, + ) + .map(|seg| previous_segments.push_back(seg)) + }) + }, + ) + .map(|segments| Wire { segments }) + } +} + +impl Wire { + fn closest_collision(&self, other: &Wire, use_signal_distance: bool) -> Option { + self.collisions(other).min_by_key(|c| { + if use_signal_distance { + c.signal_distance + } else { + c.manhattan_distance() + } + }) + } + + fn collisions<'a>(&'a self, other: &'a Wire) -> impl Iterator + 'a { + self.segments + .iter() + .flat_map(move |seg1| other.segments.iter().map(move |seg2| (seg1, seg2))) + .flat_map(|(seg1, seg2)| seg1.collisions(seg2)) + .filter(|c| !(c.x == 0 && c.y == 0)) + } +} + +#[derive(Debug, Clone)] +struct WireSegment { + start: (i32, i32), + start_signal_distance: i32, + direction: Direction, + length: i32, +} + +impl WireSegment { + fn from_str( + start: (i32, i32), + start_signal_distance: i32, + s: &str, + ) -> Result { + s.parse::().and_then(|direction| { + WireSegment::length_from_str(s).map(|length| WireSegment { + start, + start_signal_distance, + direction, + length, + }) + }) + } + + fn length_from_str(s: &str) -> Result { + s.chars() + .skip(1) + .collect::() + .parse() + .map_err(|_| UnknownError) + } + + fn end(&self) -> (i32, i32) { + ( + self.start.0 + self.direction.as_vec().0 * self.length, + self.start.1 + self.direction.as_vec().1 * self.length, + ) + } + + fn end_signal_distance(&self) -> i32 { + self.start_signal_distance + self.length + } + + fn collisions(&self, other: &WireSegment) -> Option { + use Direction::*; + + match (self.direction, other.direction) { + (Left, Left) | (Right, Right) | (Up, Up) | (Down, Down) => None, + (Left, Right) | (Right, Left) | (Up, Down) | (Down, Up) => None, + (Left, Up) => collisions( + self.end(), + self.end_signal_distance(), + self.length, + -1, + other.start, + other.start_signal_distance, + other.length, + 1, + ), + (Left, Down) => collisions( + self.end(), + self.end_signal_distance(), + self.length, + -1, + other.end(), + other.end_signal_distance(), + other.length, + -1, + ), + (Right, Up) => collisions( + self.start, + self.start_signal_distance, + self.length, + 1, + other.start, + other.start_signal_distance, + other.length, + 1, + ), + (Right, Down) => collisions( + self.start, + self.start_signal_distance, + self.length, + 1, + other.end(), + other.end_signal_distance(), + other.length, + -1, + ), + (Down, Right) => collisions( + other.start, + other.start_signal_distance, + other.length, + 1, + self.end(), + self.end_signal_distance(), + self.length, + -1, + ), + (Down, Left) => collisions( + other.end(), + other.end_signal_distance(), + other.length, + -1, + self.end(), + self.end_signal_distance(), + self.length, + -1, + ), + (Up, Right) => collisions( + other.start, + other.start_signal_distance, + other.length, + 1, + self.start, + self.start_signal_distance, + self.length, + 1, + ), + (Up, Left) => collisions( + other.end(), + other.end_signal_distance(), + other.length, + -1, + self.start, + self.start_signal_distance, + self.length, + 1, + ), + } + } +} + +fn collisions( + horizontal_start: (i32, i32), + horizontal_start_signal_distance: i32, + horizontal_length: i32, + horizontal_signal_distance_multiplier: i32, + vertical_start: (i32, i32), + vertical_start_signal_distance: i32, + vertical_length: i32, + vertical_signal_distance_multiplier: i32, +) -> Option { + if horizontal_start.1 >= vertical_start.1 + && horizontal_start.1 <= vertical_start.1 + vertical_length + && vertical_start.0 >= horizontal_start.0 + && vertical_start.0 <= horizontal_start.0 + horizontal_length + { + Some(Collision { + x: vertical_start.0, + y: horizontal_start.1, + signal_distance: horizontal_start_signal_distance + + (vertical_start.0 - horizontal_start.0) * horizontal_signal_distance_multiplier + + vertical_start_signal_distance + + (horizontal_start.1 - vertical_start.1) * vertical_signal_distance_multiplier, + }) + } else { + None + } +} + +#[derive(Debug, Clone, Copy)] +enum Direction { + Up, + Down, + Left, + Right, +} + +impl FromStr for Direction { + type Err = UnknownError; + + fn from_str(s: &str) -> Result { + use Direction::*; + match s.chars().next() { + Some('L') => Ok(Left), + Some('R') => Ok(Right), + Some('U') => Ok(Up), + Some('D') => Ok(Down), + Some(_) => Err(UnknownError), + None => Err(UnknownError), + } + } +} +impl Direction { + fn as_vec(&self) -> (i32, i32) { + use Direction::*; + match self { + Up => (0, 1), + Down => (0, -1), + Left => (-1, 0), + Right => (1, 0), + } + } +} + +struct Collision { + x: i32, + y: i32, + signal_distance: i32, +} + +impl Collision { + fn manhattan_distance(&self) -> i32 { + self.x.abs() + self.y.abs() + } +} + +#[derive(Debug, PartialEq)] +struct UnknownError; + +impl fmt::Display for UnknownError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Unknown error") + } +} +impl std::error::Error for UnknownError {} diff --git a/2019/src/bin/day_4.rs b/2019/src/bin/day_4.rs new file mode 100644 index 0000000..d7d6b69 --- /dev/null +++ b/2019/src/bin/day_4.rs @@ -0,0 +1,55 @@ +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 4: Secure Container")] +/// Calculates how many possible lock values there are +/// +/// See https://adventofcode.com/2019/day/4 for details. +struct Opt { + /// Repeated digits must be exactly 2 long + #[structopt(long = "larger-range-rule")] + larger_range_rule: bool, + min: u32, + max: u32, +} + +fn main() { + let opt = Opt::from_args(); + + println!( + "{}", + valid_combinations(opt.min, opt.max, opt.larger_range_rule) + ) +} + +fn valid_combinations(min: u32, max: u32, larger_range_rule: bool) -> u32 { + (min..max) + .filter(|x| { + two_adjacent_identical_digits(*x, larger_range_rule) && digits_never_decrease(*x) + }) + .count() as u32 +} + +fn two_adjacent_identical_digits(x: u32, larger_range_rule: bool) -> bool { + if larger_range_rule { + (0..5).any(|d| { + digit(x, d) == digit(x, d + 1) + && digit(x, d) != digit(x, d + 2) + && digit(x, d) != digit(x, d - 1) + }) + } else { + (0..5).any(|d| digit(x, d) == digit(x, d + 1)) + } +} + +fn digits_never_decrease(x: u32) -> bool { + (0..5).all(|d| digit(x, d) >= digit(x, d + 1)) +} + +fn digit(x: u32, digit: i32) -> u32 { + if digit < 0 { + 0 + } else { + (x / 10u32.pow(digit as u32)) % 10 + } +} diff --git a/2019/src/bin/day_5.rs b/2019/src/bin/day_5.rs new file mode 100644 index 0000000..07f7af8 --- /dev/null +++ b/2019/src/bin/day_5.rs @@ -0,0 +1,45 @@ +use aoc2019::*; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 5: Sunny with a Chance of Asteroids")] +/// Executes an Intcode program +/// +/// The program is read from stdin as a series of comma-separated +/// values. Newlines are ignored. +/// +/// See https://adventofcode.com/2019/day/5 for details. +struct Opt { + #[structopt(short = "i", long = "input")] + input: Vec, +} + +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::() + .with_input(opt.input.into_iter().collect()); + + let result = exit_on_failed_assertion(program.execute(), "Program errored"); + println!("{}", result); +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} diff --git a/2019/src/bin/day_6.rs b/2019/src/bin/day_6.rs new file mode 100644 index 0000000..2af272c --- /dev/null +++ b/2019/src/bin/day_6.rs @@ -0,0 +1,251 @@ +use rpds::vector::Vector; +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::iter::FromIterator; +use std::process; +use std::str::FromStr; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 6: Universal Orbit Map")] +/// Finds the minumum number of orbital transfers between two points. +/// +/// Input is read from stdin, one direct orbit per line, in the format +/// `A)B` (B is orbiting A). +/// +/// See https://adventofcode.com/2019/day/6 for details. +struct Opt { + /// Debug checksum: Counts the total orbits + #[structopt(short = "d", long = "debug")] + debug: bool, +} + +fn main() { + let stdin = io::stdin(); + let opt = Opt::from_args(); + + let orbits: OrbitalMap = stdin + .lock() + .lines() + .map(|x| exit_on_failed_assertion(x, "Error reading input")) + .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid orbit")) + .collect(); + + // eprintln!("{:#?}", orbits); + + if opt.debug { + println!("{}", orbits.total_orbits()); + } else { + println!("{}", orbits.orbital_transfers("YOU", "SAN")); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug)] +struct StrError { + str: String, +} + +impl fmt::Display for StrError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.str) + } +} +impl std::error::Error for StrError {} + +#[derive(Debug, Clone)] +struct Orbit { + a: String, + b: String, +} + +impl FromStr for Orbit { + type Err = StrError; + + fn from_str(s: &str) -> Result { + match s.split(')').collect::>()[..] { + [a, b] => Ok(Orbit { + a: a.to_string(), + b: b.to_string(), + }), + _ => Err(StrError { + str: format!("{} is not a valid orbit description", s), + }), + } + } +} + +#[derive(Clone, Debug)] +struct OrbitalMap { + id: String, + depth: usize, + orbiters: Vector, +} + +struct OrbitalMapBuilder { + orbiters: Vector, + inserted_orbits: Vector, + pending_orbits: Vector, +} + +impl FromIterator for OrbitalMap { + fn from_iter>(iter: T) -> Self { + iter.into_iter().collect::().build() + } +} + +impl FromIterator for OrbitalMapBuilder { + fn from_iter>(iter: T) -> Self { + OrbitalMapBuilder { + orbiters: Vector::new(), + inserted_orbits: Vector::new(), + pending_orbits: iter.into_iter().collect(), + } + } +} + +impl OrbitalMapBuilder { + fn build(self) -> OrbitalMap { + if self.pending_orbits.is_empty() { + OrbitalMap { + id: ROOT.into(), + depth: 0, + orbiters: self.orbiters, + } + } else { + self.pending_orbits + .into_iter() + .fold( + OrbitalMapBuilder { + pending_orbits: Vector::new(), + ..self + }, + |acc, next| acc.insert(&next), + ) + .build() + } + } + + fn insert(self, orbit: &Orbit) -> OrbitalMapBuilder { + if orbit.a == ROOT { + OrbitalMapBuilder { + orbiters: self.orbiters.push_back(OrbitalMap::new(orbit.b.clone(), 1)), + inserted_orbits: self.inserted_orbits.push_back(orbit.b.clone()), + ..self + } + } else if self.inserted_orbits.iter().any(|o| *o == orbit.a) { + OrbitalMapBuilder { + orbiters: self + .orbiters + .into_iter() + .map(|map| OrbitalMap::insert(map.clone(), orbit)) + .collect(), + inserted_orbits: self.inserted_orbits.push_back(orbit.b.clone()), + ..self + } + } else { + OrbitalMapBuilder { + pending_orbits: self.pending_orbits.push_back(orbit.clone()), + ..self + } + } + } +} + +const ROOT: &str = "COM"; + +impl OrbitalMap { + fn new(id: String, depth: usize) -> OrbitalMap { + OrbitalMap { + id, + depth, + orbiters: Vector::new(), + } + } + + fn insert(self, orbit: &Orbit) -> OrbitalMap { + if orbit.a == self.id { + if self.orbiters.iter().any(|o| o.id == orbit.b) { + self + } else { + OrbitalMap { + orbiters: self + .orbiters + .push_back(OrbitalMap::new(orbit.b.clone(), self.depth + 1)), + ..self + } + } + } else { + OrbitalMap { + orbiters: self + .orbiters + .into_iter() + .map(|map| OrbitalMap::insert(map.clone(), orbit)) + .collect(), + ..self + } + } + } + + fn count_orbits(&self) -> usize { + self.orbiters.len() + + self + .orbiters + .iter() + .map(|o| o.count_orbits()) + .sum::() + } + + fn total_orbits(&self) -> usize { + self.count_orbits() + + self + .orbiters + .iter() + .map(|o| o.total_orbits()) + .sum::() + } + + fn find_depth(&self, id: &str) -> usize { + if self.id == id { + self.depth + } else { + // only the actual one will return non-zero from this + self.orbiters.iter().map(|o| o.find_depth(id)).sum() + } + } + + fn contains(&self, id: &str) -> bool { + self.id == id || self.orbiters.iter().any(|o| o.contains(id)) + } + + fn find_common_ancestor(&self, a: &str, b: &str) -> Option { + if !self.contains(a) || !self.contains(b) { + None + } else { + self.orbiters + .iter() + .flat_map(|o| o.find_common_ancestor(a, b)) + .next() + .or(Some(self.clone())) + } + } + + fn orbital_transfers(&self, from: &str, to: &str) -> usize { + self.find_depth(from) + self.find_depth(to) + - 2 * self + .find_common_ancestor(from, to) + .map(|o| o.depth) + .unwrap_or(0) + - 2 + } +} diff --git a/2019/src/bin/day_7.rs b/2019/src/bin/day_7.rs new file mode 100644 index 0000000..9b9177a --- /dev/null +++ b/2019/src/bin/day_7.rs @@ -0,0 +1,175 @@ +use aoc2019::*; +use rpds::list; +use rpds::list::List; +use rpds::vector::Vector; +use std::io; +use std::io::prelude::*; +use std::iter; +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::(), "Invalid number")) + .collect::(); + + let result = exit_on_failed_assertion( + find_max_power(&program, opt.feedback_loop_mode), + "Program errored", + ); + println!("{}", result); +} + +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_max_power( + program: &IntcodeProgram, + feedback_loop_mode: bool, +) -> Result { + PhaseSetting::all(feedback_loop_mode) + .map(|phase| AmplifierArray::new(program, &phase).execute()) + .collect::, _>>() + .map(|powers| powers.into_iter().max().unwrap_or(Intcode::from(0))) +} + +#[derive(Debug, Clone)] +struct PhaseSetting([Intcode; 5]); + +impl PhaseSetting { + fn all(feedback_loop_mode: bool) -> impl Iterator { + if feedback_loop_mode { + PhaseSetting::permute(5, 10) + } else { + PhaseSetting::permute(0, 5) + } + } + + fn permute(min: i32, max: i32) -> impl Iterator { + // This is an absolutely atrocious way to do the permutation, + // but luckily it's only 5 elements long. + (min..max) + .flat_map(move |a| { + (min..max).flat_map(move |b| { + (min..max).flat_map(move |c| { + (min..max).flat_map(move |d| { + (min..max).map(move |e| { + PhaseSetting([a.into(), b.into(), c.into(), d.into(), e.into()]) + }) + }) + }) + }) + }) + .filter(move |phase| (min..max).all(|x| phase.0.contains(&x.into()))) + } +} + +#[derive(Debug, Clone)] +struct AmplifierArray { + amplifiers: Vector, +} + +impl AmplifierArray { + fn new(program: &IntcodeProgram, phase: &PhaseSetting) -> AmplifierArray { + AmplifierArray { + amplifiers: (0..5) + .map(|n| AmplifierArray::new_amp(program, phase, n)) + .collect(), + } + } + + fn new_amp(program: &IntcodeProgram, phase: &PhaseSetting, n: usize) -> IntcodeProgram { + if n == 0 { + program.with_input(list![phase.0[n].clone(), Intcode::from(0)]) + } else { + program.with_input(list![phase.0[n].clone()]) + } + } + + fn execute(&self) -> Result { + self.run_to_termination().output_into_result() + } + + fn run_to_termination(&self) -> AmplifierArray { + iter::successors(Some(self.clone()), |p| Some(p.next())) + .find(|p| p.is_terminated()) + .unwrap() // successors doesn't terminate, so this will never be none. + } + + fn output_into_result(&self) -> Result { + self.amplifiers + .first() + .and_then(|amp| amp.input.first().cloned()) + .ok_or(IntcodeProgramError::Unknown) + } + + fn is_terminated(&self) -> bool { + self.amplifiers.last().map(|amp| amp.halted).unwrap_or(true) + } + + fn next(&self) -> AmplifierArray { + self.run_amplifiers().update_inputs() + } + + fn run_amplifiers(&self) -> AmplifierArray { + AmplifierArray { + amplifiers: self + .amplifiers + .iter() + .map(|amp| amp.run_to_termination_or_input()) + .collect(), + } + } + + fn update_inputs(&self) -> AmplifierArray { + AmplifierArray { + amplifiers: self + .amplifiers + .iter() + .fold( + ( + Vector::new(), + self.amplifiers + .last() + .map(|a| a.output.iter().cloned().collect::>()) + .unwrap_or(List::new()), + ), + |(amps, piped_input), next_amp| { + ( + amps.push_back( + next_amp + .with_additional_input(piped_input) + .with_cleared_output(), + ), + next_amp.output.iter().cloned().collect::>(), + ) + }, + ) + .0, + } + } +} diff --git a/2019/src/bin/day_8.rs b/2019/src/bin/day_8.rs new file mode 100644 index 0000000..0508e7c --- /dev/null +++ b/2019/src/bin/day_8.rs @@ -0,0 +1,135 @@ +use std::fmt; +use std::io; +use std::io::prelude::*; +use std::process; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 8: Space Image Format")] +/// Executes an Intcode program on 5 amplifiers, and finds the input that gives the max output +/// +/// See https://adventofcode.com/2019/day/8 for details. +struct Opt { + /// Rather than rendering the image, calculate and print its checksum + #[structopt(short = "c", long = "checksum")] + checksum_mode: bool, + #[structopt(short = "w", long = "width")] + width: u32, + #[structopt(short = "h", long = "height")] + height: u32, +} + +fn main() { + let opt = Opt::from_args(); + + let image: Image = { + let mut buffer = String::new(); + exit_on_failed_assertion( + io::stdin().read_to_string(&mut buffer), + "Error reading input", + ); + + Image::from_str(&buffer.trim(), opt.width, opt.height) + }; + + if opt.checksum_mode { + println!("{}", image.checksum()); + } else { + println!("{}", image); + } +} + +fn exit_on_failed_assertion(data: Result, message: &str) -> A { + match data { + Ok(data) => data, + Err(e) => { + eprintln!("{}: {}", message, e); + process::exit(1); + } + } +} + +#[derive(Debug)] +struct Image { + width: u32, + height: u32, + layers: Vec, +} + +impl fmt::Display for Image { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.flatten() + .pixels + .chunks(self.width as usize) + .map(|line| { + line.iter() + .map(|c| write!(f, "{}", if *c == 0 { ' ' } else { '1' })) + .collect::() + .and_then(|_| writeln!(f)) + }) + .collect() + } +} + +impl Image { + fn from_str(s: &str, width: u32, height: u32) -> Image { + Image { + width, + height, + layers: s + .as_bytes() + .chunks((width * height) as usize) + .map(|chunk| ImageLayer::new(chunk)) + .collect(), + } + } + + fn checksum(&self) -> usize { + self.layers + .iter() + .min_by_key(|layer| layer.pixel_count(0)) + .map(|layer| layer.pixel_count(1) * layer.pixel_count(2)) + .unwrap_or(0) + } + + fn flatten(&self) -> ImageLayer { + self.layers + .iter() + .fold(ImageLayer::empty(self.width, self.height), |acc, next| { + ImageLayer { + pixels: acc + .pixels + .iter() + .zip(next.pixels.iter()) + .map(|(a, b)| if *a == 2 { *b } else { *a }) + .collect(), + } + }) + } +} + +#[derive(Debug)] +struct ImageLayer { + pixels: Vec, +} + +impl ImageLayer { + fn new(char_pixels: &[u8]) -> ImageLayer { + ImageLayer { + pixels: char_pixels + .iter() + .map(|c| c.overflowing_sub(b'0').0) + .collect(), + } + } + + fn empty(width: u32, height: u32) -> ImageLayer { + ImageLayer { + pixels: vec![2; (width * height) as usize], + } + } + + fn pixel_count(&self, value: u8) -> usize { + self.pixels.iter().filter(|p| **p == value).count() + } +} diff --git a/2019/src/bin/day_9.rs b/2019/src/bin/day_9.rs new file mode 100644 index 0000000..7f9b4aa --- /dev/null +++ b/2019/src/bin/day_9.rs @@ -0,0 +1 @@ +// Run the day 5 binary for this diff --git a/2019/src/lib.rs b/2019/src/lib.rs new file mode 100644 index 0000000..a7dfc02 --- /dev/null +++ b/2019/src/lib.rs @@ -0,0 +1,438 @@ +use derivative::Derivative; +use num::bigint::BigInt; +use num::traits::identities::Zero; +use rpds::RedBlackTreeMap; +use rpds::{list::List, vector::Vector}; +use std::fmt; +use std::iter; +use std::iter::FromIterator; +use std::iter::IntoIterator; +use std::iter::Iterator; + +pub type Intcode = BigInt; + +#[derive(Clone, Derivative)] +#[derivative(Debug)] +pub struct IntcodeProgram { + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + instruction_pointer: Intcode, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + relative_base: Intcode, + pub error: Option, + pub halted: bool, + pub awaiting_input: bool, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + memory: RedBlackTreeMap, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + pub input: List, + #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] + pub output: Vector, +} + +impl FromIterator for IntcodeProgram { + fn from_iter>(iter: I) -> Self { + IntcodeProgram { + instruction_pointer: Intcode::from(0), + relative_base: Intcode::from(0), + error: None, + halted: false, + awaiting_input: false, + memory: iter + .into_iter() + .enumerate() + .map(|(addr, val)| (Intcode::from(addr), val)) + .collect(), + input: List::new(), + output: Vector::new(), + } + } +} + +pub fn intcode_to_bool(i: &Intcode) -> bool { + *i != Intcode::from(0) +} + +pub fn bool_to_intcode(i: bool) -> Intcode { + if i { + Intcode::from(1) + } else { + Intcode::from(0) + } +} + +impl IntcodeProgram { + pub fn with_mem_0(&self, val: Intcode) -> IntcodeProgram { + self.with_memory_set(0.into(), val) + } + + pub fn with_noun_verb_input(&self, noun: Intcode, verb: Intcode) -> IntcodeProgram { + self.with_memory_set(1.into(), noun) + .with_memory_set(2.into(), verb) + } + + pub fn with_input(&self, input: List) -> IntcodeProgram { + IntcodeProgram { + input, + ..self.clone() + } + } + + pub fn with_additional_input(&self, input: List) -> IntcodeProgram { + IntcodeProgram { + input: self.input.iter().chain(input.iter()).cloned().collect(), + ..self.clone() + } + } + + pub fn with_cleared_output(&self) -> IntcodeProgram { + IntcodeProgram { + output: Vector::new(), + ..self.clone() + } + } + + pub fn execute(&self) -> Result, IntcodeProgramError> { + self.run_to_termination().output_into_result() + } + + pub fn execute_returning_memory_0(&self) -> Result { + self.run_to_termination().memory_0_into_result() + } + + pub fn run_to_termination(&self) -> IntcodeProgram { + iter::successors(Some(self.clear_await_input()), |p| { + Some(IntcodeProgram::next(&p)) + }) + .find(|p| p.halted) + .unwrap() // successors doesn't terminate, so this will never be none. + } + + pub fn run_to_termination_or_input(&self) -> IntcodeProgram { + iter::successors(Some(self.clear_await_input()), |p| { + Some(IntcodeProgram::next(&p)) + }) + .find(|p| p.halted || p.awaiting_input) + .unwrap() + } + + pub fn output_into_result(&self) -> Result, IntcodeProgramError> { + match self.error { + Some(ref error) => Err(error.clone()), + None => Ok(self.output.clone()), + } + } + + fn with_instruction_pointer(&self, instruction_pointer: Intcode) -> IntcodeProgram { + IntcodeProgram { + instruction_pointer, + ..self.clone() + } + } + + fn with_instruction_pointer_offset(&self, offset: usize) -> IntcodeProgram { + IntcodeProgram { + instruction_pointer: self.instruction_pointer.clone() + offset, + ..self.clone() + } + } + + fn with_relative_base(&self, relative_base: Intcode) -> IntcodeProgram { + IntcodeProgram { + relative_base, + ..self.clone() + } + } + + fn with_memory_set(&self, address: Intcode, value: Intcode) -> IntcodeProgram { + IntcodeProgram { + memory: self.memory.insert(address, value), + ..self.clone() + } + } + + fn with_input_consumed(&self) -> IntcodeProgram { + self.input + .drop_first() + .map(|input| IntcodeProgram { + input, + ..self.clone() + }) + .unwrap_or(self.error(IntcodeProgramError::Unknown)) + } + + fn with_output(&self, print: Intcode) -> IntcodeProgram { + IntcodeProgram { + output: self.output.push_back(print), + ..self.clone() + } + } + + fn memory_0_into_result(&self) -> Result { + match self.error { + Some(ref error) => Err(error.clone()), + None => Ok(self + .memory + .get(&Intcode::from(0)) + .cloned() + .unwrap_or(Intcode::from(0))), + } + } + fn next(&self) -> IntcodeProgram { + //dbg!(self); + self.memory + .get(&self.instruction_pointer) + .map(|opcode| match opcode.to_radix_le(100).1[0] { + 1 => self.add(opcode), + 2 => self.multiply(opcode), + 3 => self.input(opcode), + 4 => self.output(opcode), + 5 => self.jump_if_true(opcode), + 6 => self.jump_if_false(opcode), + 7 => self.less_than(opcode), + 8 => self.equals(opcode), + 9 => self.set_relative_base(opcode), + 99 => self.halt(), + unknown => self.error(IntcodeProgramError::InvalidOpcode(unknown.clone())), + }) + .unwrap_or(self.error(IntcodeProgramError::Unknown)) + } + + fn add(&self, mode: &Intcode) -> IntcodeProgram { + self.with_instruction_pointer_offset(4).with_memory_set( + self.get_literal(3, mode), + self.get(1, mode) + self.get(2, mode), + ) + } + + fn multiply(&self, mode: &Intcode) -> IntcodeProgram { + self.with_instruction_pointer_offset(4).with_memory_set( + self.get_literal(3, mode), + self.get(1, mode) * self.get(2, mode), + ) + } + + fn input(&self, mode: &Intcode) -> IntcodeProgram { + match self.input.first().cloned() { + Some(input) => self + .with_instruction_pointer_offset(2) + .with_memory_set(self.get_literal(1, mode), input) + .with_input_consumed(), + None => self.await_input(), + } + } + + fn output(&self, mode: &Intcode) -> IntcodeProgram { + self.with_instruction_pointer_offset(2) + .with_output(self.get(1, mode)) + } + + fn jump_if_true(&self, mode: &Intcode) -> IntcodeProgram { + if !self.get(1, mode).is_zero() { + self.with_instruction_pointer(self.get(2, mode)) + } else { + self.with_instruction_pointer_offset(3) + } + } + fn jump_if_false(&self, mode: &Intcode) -> IntcodeProgram { + if self.get(1, mode).is_zero() { + self.with_instruction_pointer(self.get(2, mode)) + } else { + self.with_instruction_pointer_offset(3) + } + } + + fn less_than(&self, mode: &Intcode) -> IntcodeProgram { + self.with_instruction_pointer_offset(4).with_memory_set( + self.get_literal(3, mode), + if self.get(1, mode) < self.get(2, mode) { + Intcode::from(1) + } else { + Intcode::from(0) + }, + ) + } + + fn equals(&self, mode: &Intcode) -> IntcodeProgram { + self.with_instruction_pointer_offset(4).with_memory_set( + self.get_literal(3, mode), + if self.get(1, mode) == self.get(2, mode) { + Intcode::from(1) + } else { + Intcode::from(0) + }, + ) + } + + fn set_relative_base(&self, mode: &Intcode) -> IntcodeProgram { + self.with_instruction_pointer_offset(2) + .with_relative_base(self.relative_base.clone() + self.get(1, mode)) + } + + fn halt(&self) -> IntcodeProgram { + IntcodeProgram { + halted: true, + ..self.clone() + } + } + + fn await_input(&self) -> IntcodeProgram { + IntcodeProgram { + awaiting_input: true, + ..self.clone() + } + } + + fn clear_await_input(&self) -> IntcodeProgram { + IntcodeProgram { + awaiting_input: false, + ..self.clone() + } + } + + fn error(&self, error: IntcodeProgramError) -> IntcodeProgram { + IntcodeProgram { + halted: true, + error: Some(error), + ..self.clone() + } + } + + fn get(&self, pointer_offset: usize, mode: &Intcode) -> Intcode { + match mode + .to_radix_le(10) + .1 + .get(pointer_offset + 1) + .cloned() + .unwrap_or(0) + { + 0 => self.get_position(pointer_offset), + 1 => self.get_immediate(pointer_offset), + 2 => self.get_relative(pointer_offset), + _ => Intcode::from(0), + } + } + + fn get_literal(&self, pointer_offset: usize, mode: &Intcode) -> Intcode { + match mode + .to_radix_le(10) + .1 + .get(pointer_offset + 1) + .cloned() + .unwrap_or(0) + { + 0 => self.get_immediate(pointer_offset), + 1 => self.get_immediate(pointer_offset), + 2 => self.get_immediate_relative(pointer_offset), + _ => Intcode::from(0), + } + } + + fn get_immediate(&self, pointer_offset: usize) -> Intcode { + self.memory + .get(&(self.instruction_pointer.clone() + pointer_offset)) + .cloned() + .unwrap_or(Intcode::from(0)) + } + + fn get_position(&self, pointer_offset: usize) -> Intcode { + self.memory + .get(&self.get_immediate(pointer_offset)) + .cloned() + .unwrap_or(Intcode::from(0)) + } + + fn get_relative(&self, pointer_offset: usize) -> Intcode { + self.memory + .get(&(self.get_immediate(pointer_offset) + self.relative_base.clone())) + .cloned() + .unwrap_or(Intcode::from(0)) + } + + fn get_immediate_relative(&self, pointer_offset: usize) -> Intcode { + self.get_immediate(pointer_offset) + self.relative_base.clone() + } +} + +#[derive(Debug, PartialEq, Clone)] +pub enum IntcodeProgramError { + InvalidOpcode(u8), + Unknown, +} + +impl fmt::Display for IntcodeProgramError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use IntcodeProgramError::*; + + match self { + InvalidOpcode(i) => write!(f, "{} is not a valid opcode", i), + Unknown => write!(f, "Unknown error"), + } + } +} +impl std::error::Error for IntcodeProgramError {} + +#[cfg(test)] +mod tests { + use super::*; + + fn i32_vec_to_intcode_program(input: Vec) -> IntcodeProgram { + input.into_iter().map(Intcode::from).collect() + } + + fn i32_vec_to_intcode_memory(input: Vec) -> RedBlackTreeMap { + input + .into_iter() + .enumerate() + .map(|(i, val)| (Intcode::from(i), Intcode::from(val))) + .collect() + } + + fn i32_vec_to_intcode_vec(input: Vec) -> Vector { + input.into_iter().map(Intcode::from).collect() + } + + fn test_example_program( + before_execution: Vec, + after_execution: Vec, + ) -> IntcodeProgram { + let program = i32_vec_to_intcode_program(before_execution).run_to_termination(); + + assert_eq!(program.error, None); + assert_eq!(program.memory, i32_vec_to_intcode_memory(after_execution)); + program + } + + #[test] + fn day_2_example_1() { + test_example_program(vec![1, 0, 0, 0, 99], vec![2, 0, 0, 0, 99]); + } + + #[test] + fn day_2_example_2() { + test_example_program(vec![2, 3, 0, 3, 99], vec![2, 3, 0, 6, 99]); + } + + #[test] + fn day_5_example_1() { + test_example_program(vec![1002, 4, 3, 4, 33], vec![1002, 4, 3, 4, 99]); + } + + #[test] + fn day_9_example_1() { + let quine = vec![ + 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, + ]; + let program = i32_vec_to_intcode_program(quine.clone()).run_to_termination(); + assert_eq!(program.error, None); + assert_eq!(program.output, i32_vec_to_intcode_vec(quine)); + } +} + +pub fn sort_by_key( + iter: impl IntoIterator, + f: impl FnMut(&T) -> K, +) -> impl Iterator { + let mut tmp: Vec = iter.into_iter().collect(); + tmp.sort_by_key(f); + tmp.into_iter() +} diff --git a/2019/src/main.rs b/2019/src/main.rs new file mode 100644 index 0000000..0c24a73 --- /dev/null +++ b/2019/src/main.rs @@ -0,0 +1,12 @@ +use std::io; +use std::io::prelude::*; + +fn main() { + let stdin = io::stdin(); + let answer = string_length_sum(stdin.lock().lines().map(|l| l.unwrap())); + dbg!(answer); +} + +fn string_length_sum(it: impl Iterator) -> usize { + it.map(|l| l.len()).sum() +} diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 52c69da..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,580 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aoc2019" -version = "0.1.0" -dependencies = [ - "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cached 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derivative 1.0.3 (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)", - "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "archery" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitmaps" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cached" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "clap" -version = "2.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "derivative" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "derive_more" -version = "0.99.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "heck" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hermit-abi" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "im" -version = "14.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.66" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-bigint" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-complex" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-iter" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num_cpus" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "once_cell" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro-error" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro2" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand_xoshiro" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rpds" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scopeguard" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sized-chunks" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "static_assertions" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "structopt" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "structopt-derive" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-segmentation" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "version_check" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum archery 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d308d8fa3f687f7a7588fccc4812ed6914be09518232f00454693a7417273ad2" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum bitmaps 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81e039a80914325b37fde728ef7693c212f0ac913d5599607d7b95a9484aae0b" -"checksum cached 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b052fd10f32987c3bd028d91ef86190b36fba5c8fccb5515d42083f061e6104" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" -"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" -"checksum derivative 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "942ca430eef7a3806595a6737bc388bf51adb888d3fc0dd1b50f1c170167ee3a" -"checksum derive_more 0.99.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" -"checksum im 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1f9b6540e530defef7f2df4ed330d45b739b10450548c74a9913f63ea1acc6b" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" -"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" -"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -"checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" -"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_xoshiro 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004" -"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" -"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" -"checksum rpds 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1196a0a2f52d343bd32179834273eaac7d8739f7e3f8b700227d2fa06b9a423b" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum sized-chunks 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62db64dd92b3b54314b1e216c274634ca2b3fe8da8b3873be670cb1ac4dad30f" -"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" -"checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index c5937b0..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "aoc2019" -version = "0.1.0" -authors = ["Justin Wernick "] -edition = "2018" - -[dependencies] -structopt = "0.3.5" -derive_more = "0.99.2" -derivative = "1.0.3" -im = "14.0.0" -rpds = "0.7.0" -archery = "0.3.0" -num = "0.2" -rayon = "1.3.0" -cached = "0.11.0" - -[profile.release] -debug = true diff --git a/inputs/day_1.txt b/inputs/day_1.txt deleted file mode 100644 index 5c720ed..0000000 --- a/inputs/day_1.txt +++ /dev/null @@ -1,100 +0,0 @@ -66690 -86239 -75191 -140364 -95979 -106923 -95229 -123571 -84764 -89444 -98107 -89062 -109369 -146067 -124760 -76900 -139198 -111441 -74046 -84920 -54397 -143807 -121654 -93863 -73909 -104121 -58485 -119084 -126227 -142078 -79820 -132617 -108430 -98032 -107434 -127307 -105619 -57741 -53468 -63301 -137970 -136780 -80897 -133205 -79159 -89124 -94477 -56714 -143704 -122097 -117335 -108246 -75507 -101459 -101162 -146197 -121884 -66217 -57074 -142903 -140951 -64883 -124556 -67382 -142407 -121778 -57933 -94599 -87426 -143758 -64043 -65678 -90137 -61090 -77315 -102383 -146607 -139290 -85394 -149787 -125611 -106405 -91561 -135739 -54845 -68782 -111175 -61011 -125658 -70751 -85607 -75458 -75419 -124311 -66022 -122784 -129018 -54901 -73788 -108240 diff --git a/inputs/day_10.txt b/inputs/day_10.txt deleted file mode 100644 index 51520ab..0000000 --- a/inputs/day_10.txt +++ /dev/null @@ -1,24 +0,0 @@ -.###.#...#.#.##.#.####.. -.#....#####...#.######.. -#.#.###.###.#.....#.#### -##.###..##..####.#.####. -###########.#######.##.# -##########.#########.##. -.#.##.########.##...###. -###.#.##.#####.#.###.### -##.#####.##..###.#.##.#. -.#.#.#####.####.#..##### -.###.#####.#..#..##.#.## -########.##.#...######## -.####..##..#.###.###.#.# -....######.##.#.######.# -###.####.######.#....### -############.#.#.##.#### -##...##..####.####.#..## -.###.#########.###..#.## -#.##.#.#...##...#####..# -##.#..###############.## -##.###.#####.##.######.. -##.#####.#.#.##..####### -...#######.######...#### -#....#.#.#.####.#.#.#.## diff --git a/inputs/day_11.txt b/inputs/day_11.txt deleted file mode 100644 index d6581e1..0000000 --- a/inputs/day_11.txt +++ /dev/null @@ -1 +0,0 @@ -3,8,1005,8,320,1106,0,11,0,0,0,104,1,104,0,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,102,1,8,29,2,1005,1,10,1006,0,11,3,8,1002,8,-1,10,101,1,10,10,4,10,108,0,8,10,4,10,102,1,8,57,1,8,15,10,1006,0,79,1,6,3,10,3,8,102,-1,8,10,101,1,10,10,4,10,108,0,8,10,4,10,101,0,8,90,2,103,18,10,1006,0,3,2,105,14,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,123,2,9,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,1001,8,0,150,1,2,2,10,2,1009,6,10,1,1006,12,10,1006,0,81,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,187,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,209,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,231,1,1008,11,10,1,1001,4,10,2,1104,18,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,264,1,8,14,10,1006,0,36,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,101,0,8,293,1006,0,80,1006,0,68,101,1,9,9,1007,9,960,10,1005,10,15,99,109,642,104,0,104,1,21102,1,846914232732,1,21102,1,337,0,1105,1,441,21102,1,387512115980,1,21101,348,0,0,1106,0,441,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21102,209533824219,1,1,21102,1,395,0,1106,0,441,21101,0,21477985303,1,21102,406,1,0,1106,0,441,3,10,104,0,104,0,3,10,104,0,104,0,21101,868494234468,0,1,21101,429,0,0,1106,0,441,21102,838429471080,1,1,21102,1,440,0,1106,0,441,99,109,2,21201,-1,0,1,21101,0,40,2,21102,472,1,3,21101,0,462,0,1106,0,505,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,467,468,483,4,0,1001,467,1,467,108,4,467,10,1006,10,499,1102,1,0,467,109,-2,2106,0,0,0,109,4,2101,0,-1,504,1207,-3,0,10,1006,10,522,21101,0,0,-3,21202,-3,1,1,22101,0,-2,2,21102,1,1,3,21102,541,1,0,1106,0,546,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,569,2207,-4,-2,10,1006,10,569,22102,1,-4,-4,1105,1,637,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21102,588,1,0,1105,1,546,22101,0,1,-4,21102,1,1,-1,2207,-4,-2,10,1006,10,607,21101,0,0,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,629,21201,-1,0,1,21102,629,1,0,105,1,504,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0 diff --git a/inputs/day_12.txt b/inputs/day_12.txt deleted file mode 100644 index 7e72a58..0000000 --- a/inputs/day_12.txt +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/inputs/day_13.txt b/inputs/day_13.txt deleted file mode 100644 index c600ec1..0000000 --- a/inputs/day_13.txt +++ /dev/null @@ -1 +0,0 @@ -1,380,379,385,1008,2689,888873,381,1005,381,12,99,109,2690,1102,0,1,383,1101,0,0,382,21001,382,0,1,20102,1,383,2,21101,0,37,0,1105,1,578,4,382,4,383,204,1,1001,382,1,382,1007,382,41,381,1005,381,22,1001,383,1,383,1007,383,25,381,1005,381,18,1006,385,69,99,104,-1,104,0,4,386,3,384,1007,384,0,381,1005,381,94,107,0,384,381,1005,381,108,1105,1,161,107,1,392,381,1006,381,161,1101,-1,0,384,1106,0,119,1007,392,39,381,1006,381,161,1102,1,1,384,20101,0,392,1,21101,23,0,2,21102,0,1,3,21102,138,1,0,1105,1,549,1,392,384,392,21001,392,0,1,21101,23,0,2,21101,3,0,3,21102,1,161,0,1105,1,549,1101,0,0,384,20001,388,390,1,20101,0,389,2,21101,0,180,0,1106,0,578,1206,1,213,1208,1,2,381,1006,381,205,20001,388,390,1,20101,0,389,2,21101,205,0,0,1105,1,393,1002,390,-1,390,1102,1,1,384,21001,388,0,1,20001,389,391,2,21101,228,0,0,1105,1,578,1206,1,261,1208,1,2,381,1006,381,253,20101,0,388,1,20001,389,391,2,21101,253,0,0,1106,0,393,1002,391,-1,391,1101,0,1,384,1005,384,161,20001,388,390,1,20001,389,391,2,21101,279,0,0,1106,0,578,1206,1,316,1208,1,2,381,1006,381,304,20001,388,390,1,20001,389,391,2,21101,0,304,0,1106,0,393,1002,390,-1,390,1002,391,-1,391,1101,0,1,384,1005,384,161,20102,1,388,1,20101,0,389,2,21101,0,0,3,21101,0,338,0,1106,0,549,1,388,390,388,1,389,391,389,21001,388,0,1,21002,389,1,2,21102,4,1,3,21101,0,365,0,1105,1,549,1007,389,24,381,1005,381,75,104,-1,104,0,104,0,99,0,1,0,0,0,0,0,0,230,18,20,1,1,20,109,3,21201,-2,0,1,22101,0,-1,2,21101,0,0,3,21102,1,414,0,1106,0,549,22102,1,-2,1,22102,1,-1,2,21101,0,429,0,1105,1,601,2102,1,1,435,1,386,0,386,104,-1,104,0,4,386,1001,387,-1,387,1005,387,451,99,109,-3,2106,0,0,109,8,22202,-7,-6,-3,22201,-3,-5,-3,21202,-4,64,-2,2207,-3,-2,381,1005,381,492,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,481,21202,-4,8,-2,2207,-3,-2,381,1005,381,518,21202,-2,-1,-1,22201,-3,-1,-3,2207,-3,-2,381,1006,381,507,2207,-3,-4,381,1005,381,540,21202,-4,-1,-1,22201,-3,-1,-3,2207,-3,-4,381,1006,381,529,22102,1,-3,-7,109,-8,2106,0,0,109,4,1202,-2,41,566,201,-3,566,566,101,639,566,566,2101,0,-1,0,204,-3,204,-2,204,-1,109,-4,2105,1,0,109,3,1202,-1,41,594,201,-2,594,594,101,639,594,594,20102,1,0,-2,109,-3,2106,0,0,109,3,22102,25,-2,1,22201,1,-1,1,21101,0,521,2,21102,1,1011,3,21102,1,1025,4,21102,630,1,0,1106,0,456,21201,1,1664,-2,109,-3,2105,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,2,2,0,2,0,2,0,2,0,0,2,2,0,2,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,0,0,2,0,1,1,0,0,0,0,2,0,0,2,0,2,2,2,2,0,2,0,0,0,2,2,0,0,2,2,2,2,0,0,0,0,0,2,0,0,0,0,2,2,0,1,1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,2,2,0,2,0,0,0,0,2,0,0,0,0,2,0,0,0,0,2,2,2,0,0,1,1,0,0,2,2,2,0,0,0,2,0,0,0,0,0,2,2,0,0,2,0,2,0,0,0,2,2,0,0,0,2,0,0,0,2,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,2,0,0,2,0,0,0,0,2,0,0,2,0,2,0,2,0,2,0,0,1,1,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0,0,2,2,0,0,0,2,2,0,0,2,0,0,0,2,2,2,2,2,0,2,0,1,1,0,0,0,0,2,0,2,0,0,2,0,0,0,0,0,0,2,0,0,2,0,2,2,2,0,2,2,2,0,0,0,0,0,2,0,0,2,0,0,1,1,0,2,0,0,2,0,0,0,0,2,0,0,0,0,2,2,0,2,0,0,0,0,2,0,0,0,0,0,2,0,2,0,0,2,0,0,2,0,0,1,1,0,2,2,2,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,0,0,2,0,0,2,0,2,0,2,2,0,2,2,0,2,0,2,0,0,1,1,0,0,2,0,0,2,0,2,0,0,2,0,0,2,0,0,0,2,0,0,0,0,2,0,0,2,0,0,2,2,0,2,0,0,0,0,2,2,0,1,1,0,0,2,2,0,0,2,2,0,2,2,0,0,0,0,0,2,0,0,0,0,2,2,2,0,0,2,0,2,0,2,2,0,0,2,0,2,0,0,1,1,0,0,2,2,2,0,0,2,2,0,2,2,2,0,0,0,2,2,2,0,2,0,0,0,0,0,2,0,0,2,0,2,0,0,0,0,0,0,0,1,1,0,2,0,0,0,2,2,0,2,0,0,2,0,2,2,2,0,0,2,2,0,2,0,0,0,0,0,0,2,2,0,2,2,0,2,0,0,2,0,1,1,0,0,2,0,0,2,2,0,0,0,0,0,2,2,0,2,2,2,0,2,0,2,2,2,0,0,2,0,2,2,2,0,0,0,0,0,0,2,0,1,1,0,2,0,2,0,2,2,2,2,0,0,0,2,0,0,0,2,2,0,0,0,0,2,0,2,2,0,0,0,0,2,0,2,0,0,2,0,0,0,1,1,0,0,0,0,2,0,0,2,0,0,2,2,0,2,0,0,0,2,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0,0,0,0,0,2,0,1,1,0,2,0,0,0,2,0,0,0,2,2,0,2,0,0,2,0,0,2,2,0,2,0,0,2,0,0,0,0,0,0,0,0,2,0,0,2,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,34,58,37,19,14,62,51,10,28,52,86,20,39,30,61,36,77,73,19,11,17,74,7,54,40,59,20,92,18,13,85,72,83,58,18,68,10,22,94,22,25,40,67,96,55,96,42,16,80,80,96,35,19,79,81,63,91,5,72,68,80,93,79,36,91,47,71,82,45,29,51,36,10,62,57,29,17,16,4,88,75,81,70,77,32,2,38,37,35,86,41,35,61,71,72,22,14,33,12,10,10,56,30,3,90,71,24,62,69,31,47,2,18,77,43,20,64,85,50,43,43,73,16,23,98,4,23,53,82,15,88,1,39,78,43,57,65,8,45,79,17,44,32,76,31,3,25,71,45,16,42,61,89,21,93,4,98,66,68,5,13,19,48,65,29,5,24,59,29,49,57,39,21,96,10,8,25,82,17,42,46,49,83,4,81,32,14,7,76,62,31,74,55,19,39,63,89,41,38,28,34,34,88,7,77,43,87,10,47,85,39,31,88,69,40,72,51,49,64,46,64,14,66,95,95,58,38,88,82,35,6,58,3,21,33,58,9,95,43,52,13,22,22,10,11,47,35,33,31,58,93,83,13,14,55,71,88,42,73,83,91,84,62,78,80,15,26,50,8,15,6,91,89,3,12,53,47,47,82,67,12,77,6,63,88,94,53,19,97,36,34,59,91,27,37,45,44,31,8,58,16,7,74,76,83,17,28,42,85,19,1,61,73,84,37,15,43,52,80,48,51,98,70,77,28,55,78,85,64,32,22,82,69,7,82,55,78,24,5,89,55,4,34,28,71,76,81,90,96,2,2,77,41,32,24,60,10,11,26,64,66,19,11,77,11,82,81,1,52,2,79,43,47,87,63,73,3,81,69,66,53,4,83,88,13,5,62,94,55,58,4,93,96,58,40,69,64,56,80,71,85,44,45,24,80,59,53,15,85,92,89,95,69,77,53,27,72,3,54,49,9,35,10,85,43,86,9,42,69,29,64,96,17,72,47,24,2,13,40,45,62,19,41,85,28,68,73,20,52,56,19,57,1,36,64,18,26,41,94,81,45,35,29,32,28,87,86,53,71,54,67,68,47,53,17,40,61,58,74,2,51,43,23,62,54,13,80,67,88,94,1,62,85,7,12,87,51,4,69,25,57,6,79,94,15,75,93,46,19,28,84,72,84,59,60,59,59,14,11,30,57,53,75,83,72,61,65,50,26,49,23,40,82,11,67,8,55,13,22,41,32,33,89,37,69,11,24,24,8,21,89,11,46,89,88,59,3,7,43,85,74,92,72,60,85,82,33,82,71,14,21,41,4,78,88,4,22,81,30,92,17,9,62,69,84,47,6,86,49,94,11,96,21,1,5,1,45,19,60,59,17,85,67,42,21,11,79,39,27,72,54,19,69,50,52,78,78,6,16,96,86,37,58,79,9,45,10,73,29,53,75,63,50,66,6,69,8,74,68,88,9,88,87,50,34,45,12,43,43,58,14,29,32,77,77,97,45,29,41,94,21,91,52,22,74,44,48,11,20,68,9,51,7,85,93,74,59,16,34,60,12,3,18,17,4,71,44,49,79,68,54,96,74,21,74,60,59,16,77,65,97,84,54,52,37,95,9,3,41,9,72,82,82,95,31,71,56,50,59,93,57,79,16,9,74,72,47,1,9,5,55,63,64,80,40,93,54,11,57,26,76,19,85,41,80,90,92,27,61,24,83,93,96,95,28,68,80,11,60,65,36,2,46,75,59,52,11,36,74,62,52,6,23,85,93,61,36,26,70,2,13,97,52,92,96,87,63,63,31,2,50,25,34,79,46,4,48,51,74,96,74,7,43,82,84,50,59,53,13,51,8,81,36,93,10,31,10,50,76,69,33,3,71,1,1,65,68,57,69,15,64,81,59,38,38,89,79,80,52,44,59,26,96,21,38,38,79,2,96,2,92,73,49,14,71,74,66,94,98,63,28,59,26,30,67,1,61,84,92,47,24,27,41,57,95,89,6,96,48,43,7,82,42,5,27,15,32,89,53,3,35,63,84,97,92,77,50,38,73,10,50,89,95,96,77,61,51,90,22,75,41,77,1,14,72,68,91,10,80,28,25,10,86,54,10,87,55,40,79,16,35,8,82,51,70,84,12,72,74,4,88,71,69,83,9,55,10,57,9,3,40,74,72,61,75,64,54,32,61,26,53,48,45,22,6,83,21,21,9,4,7,65,98,78,17,54,35,95,79,36,53,59,84,53,14,20,94,12,31,54,86,39,95,82,38,8,22,58,50,27,32,53,79,49,71,76,18,64,75,64,88,58,88,27,62,31,54,11,59,11,3,42,66,85,41,888873 diff --git a/inputs/day_14.txt b/inputs/day_14.txt deleted file mode 100644 index dac9757..0000000 --- a/inputs/day_14.txt +++ /dev/null @@ -1,59 +0,0 @@ -2 RWPCH => 9 PVTL -1 FHFH => 4 BLPJK -146 ORE => 5 VJNBT -8 KDFNZ, 1 ZJGH, 1 GSCG => 5 LKPQG -11 NWDZ, 2 WBQR, 1 VRQR => 2 BMJR -3 GSCG => 4 KQDVM -5 QVNKN, 6 RPWKC => 3 BCNV -10 QMBM, 4 RBXB, 2 VRQR => 1 JHXBM -15 RPWKC => 6 MGCQ -1 QWKRZ => 4 FHFH -10 RWPCH => 6 MZKG -11 JFKGV, 5 QVNKN, 1 CTVK => 4 VQDT -1 SXKT => 5 RPWKC -1 VQDT, 25 ZVMCB => 2 RBXB -6 LGLNV, 4 XSNKB => 3 WBQR -199 ORE => 2 SXKT -1 XSNKB, 6 CWBNX, 1 HPKB, 5 PVTL, 1 JNKH, 9 SXKT, 3 KQDVM => 3 ZKTX -7 FDSX => 6 WJDF -7 JLRM => 4 CWBNX -167 ORE => 5 PQZXH -13 JHXBM, 2 NWDZ, 4 RFLX, 12 VRQR, 10 FJRFG, 14 PVTL, 2 JLRM => 6 DGFG -12 HPKB, 3 WHVXC => 9 ZJGH -1 JLRM, 2 ZJGH, 2 QVNKN => 9 FJRFG -129 ORE => 7 KZFPJ -2 QMBM => 1 RWPCH -7 VJMWM => 4 JHDW -7 PQZXH, 7 SXKT => 9 BJVQM -1 VJMWM, 4 JHDW, 1 MQXF => 7 FDSX -1 RPWKC => 7 WHVXC -1 ZJGH => 1 ZVMCB -1 RWPCH => 3 MPKR -187 ORE => 8 VJMWM -15 CTVK => 5 GSCG -2 XSNKB, 15 ZVMCB, 3 KDFNZ => 2 RFLX -18 QVNKN => 8 XLFZJ -4 CWBNX => 8 ZSCX -2 ZJGH, 1 JLRM, 1 MGCQ => 9 NPRST -13 BJVQM, 2 BCNV => 2 QWKRZ -2 QWKRZ, 2 BLPJK, 5 XSNKB => 2 VRQR -13 HPKB, 3 VQDT => 9 JLRM -2 SXKT, 1 VJNBT, 5 VLWQB => 6 CTVK -2 MPKR, 2 LMNCH, 24 VRQR => 8 DZFNW -2 VQDT => 1 KDFNZ -1 CTVK, 6 FDSX => 6 QVNKN -3 CTVK, 1 QVNKN => 4 HPKB -3 NPRST, 1 KGSDJ, 1 CTVK => 2 QMBM -4 KZFPJ, 1 PQZXH => 5 VLWQB -2 VQDT => 7 KGSDJ -3 MPKR => 2 JNKH -1 KQDVM => 5 XQBS -3 ZKGMX, 1 XQBS, 11 MZKG, 11 NPRST, 1 DZFNW, 5 VQDT, 2 FHFH => 6 JQNF -2 FJRFG, 17 BMJR, 3 BJVQM, 55 JQNF, 8 DGFG, 13 ZJGH, 29 ZKTX => 1 FUEL -27 KZFPJ, 5 VJNBT => 5 MQXF -11 FDSX, 1 WHVXC, 1 WJDF => 4 ZKGMX -1 ZVMCB => 4 NWDZ -1 XLFZJ => 6 LGLNV -13 ZSCX, 4 XLFZJ => 8 LMNCH -1 RPWKC, 1 FDSX, 2 BJVQM => 8 JFKGV -1 WJDF, 1 LKPQG => 4 XSNKB diff --git a/inputs/day_15.txt b/inputs/day_15.txt deleted file mode 100644 index ca5836c..0000000 --- a/inputs/day_15.txt +++ /dev/null @@ -1 +0,0 @@ -3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1002,1034,1,1039,102,1,1036,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,1001,1035,0,1040,1002,1038,1,1043,101,0,1037,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,102,1,1035,1040,1001,1038,0,1043,101,0,1037,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,1,1032,1006,1032,165,1008,1040,9,1032,1006,1032,165,1102,1,2,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1102,1,1,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,35,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,102,1,1039,1034,1002,1040,1,1035,1002,1041,1,1036,102,1,1043,1038,101,0,1042,1037,4,1044,1105,1,0,1,5,41,19,22,1,39,81,29,20,15,82,33,18,45,30,32,55,28,26,70,13,56,32,28,18,3,59,90,11,95,15,85,8,61,25,59,24,34,1,85,5,25,54,57,18,20,54,80,91,28,65,36,12,44,36,13,92,24,56,13,39,69,29,79,10,41,27,23,25,72,20,3,61,15,51,11,12,12,48,10,45,13,29,49,90,30,17,9,41,21,18,7,30,48,17,83,71,4,10,31,10,96,81,77,9,50,39,21,36,33,72,12,3,23,79,18,4,75,17,58,64,8,7,97,60,72,72,1,94,55,42,2,94,2,21,88,19,82,57,96,19,25,27,41,62,15,40,23,61,86,27,73,61,13,46,52,81,12,34,23,73,23,59,1,30,47,9,99,10,37,17,28,98,5,92,73,8,63,4,86,76,79,7,30,68,28,91,12,12,98,74,4,22,44,10,23,45,37,16,90,76,23,74,75,12,21,38,14,15,76,28,49,71,7,6,6,71,53,33,12,87,15,92,66,21,38,13,53,92,34,49,25,6,67,21,27,89,24,61,25,30,41,30,99,28,19,41,90,51,74,14,33,54,48,10,14,42,2,67,76,10,21,2,67,43,27,69,11,16,78,7,36,9,24,48,63,81,53,29,94,34,25,99,66,47,17,97,33,52,11,62,22,52,30,23,89,95,15,13,50,48,26,10,6,69,78,13,6,94,1,28,67,10,70,16,50,19,24,15,79,50,27,3,19,62,4,31,83,20,17,83,67,5,80,26,36,62,87,3,10,80,22,65,60,10,78,4,20,60,30,11,7,83,10,13,72,81,37,22,14,55,63,51,27,32,77,52,20,50,16,48,2,55,10,53,26,84,6,87,43,37,26,3,85,62,25,78,50,16,10,37,22,54,5,80,24,7,32,49,18,27,12,41,70,82,20,34,91,15,98,77,22,6,79,3,8,54,17,32,4,44,2,97,14,15,65,30,97,14,79,75,11,77,5,61,37,20,91,20,45,74,19,40,2,41,89,12,34,44,18,62,57,17,68,22,96,7,59,63,2,60,70,2,26,75,26,3,53,19,80,16,97,7,34,58,52,66,24,75,25,30,75,42,13,12,89,13,3,84,92,1,75,30,54,43,2,56,15,1,15,84,99,6,98,42,17,29,1,18,26,70,71,29,91,23,21,87,66,18,38,32,18,81,65,2,58,99,12,4,84,24,32,88,30,67,49,29,59,64,18,70,10,24,56,5,27,97,50,4,28,85,65,16,67,83,15,16,61,18,86,8,36,25,36,29,97,45,19,81,41,29,45,30,69,26,57,93,27,72,34,30,99,61,2,48,16,12,76,98,28,14,32,32,90,48,10,30,57,23,39,2,8,39,33,13,88,34,31,74,15,60,8,47,60,31,5,79,1,98,86,33,3,99,33,62,11,96,25,22,38,98,84,3,56,70,49,3,8,56,87,4,29,59,65,26,34,77,7,14,78,26,25,70,49,3,31,45,92,24,95,17,4,9,4,96,64,92,27,67,4,99,6,44,7,16,86,2,75,1,6,68,81,4,1,44,49,7,92,8,40,36,25,81,13,56,99,10,2,30,72,6,43,30,12,43,93,19,20,23,95,10,19,66,63,28,96,40,50,8,15,56,38,13,93,42,71,12,18,87,8,4,21,85,9,2,66,77,10,80,26,61,9,43,20,88,10,39,67,55,31,49,17,58,26,80,20,84,54,49,5,73,11,52,15,63,7,62,24,57,92,61,25,87,56,37,31,38,14,99,0,0,21,21,1,10,1,0,0,0,0,0,0 diff --git a/inputs/day_16.txt b/inputs/day_16.txt deleted file mode 100644 index 357965c..0000000 --- a/inputs/day_16.txt +++ /dev/null @@ -1 +0,0 @@ -59723517898690342336085619027921111260000667417052529433894092649779685557557996383085708903241535436786723718804155370155263736632861535632645335233170435646844328735934063129720822438983948765830873108060969395372667944081201020154126736565212455403582565814037568332106043336657972906297306993727714730061029321153984390658949013821918352341503629705587666779681013358053312990709423156110291835794179056432958537796855287734217125615700199928915524410743382078079059706420865085147514027374485354815106354367548002650415494525590292210440827027951624280115914909910917047084328588833201558964370296841789611989343040407348115608623432403085634084 diff --git a/inputs/day_17.txt b/inputs/day_17.txt deleted file mode 100644 index 49131d4..0000000 --- a/inputs/day_17.txt +++ /dev/null @@ -1 +0,0 @@ -1,330,331,332,109,3974,1102,1182,1,15,1101,1475,0,24,1001,0,0,570,1006,570,36,101,0,571,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,15,1,15,1008,15,1475,570,1006,570,14,21102,1,58,0,1105,1,786,1006,332,62,99,21101,333,0,1,21102,73,1,0,1105,1,579,1102,0,1,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,1002,574,1,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21102,340,1,1,1105,1,177,21101,0,477,1,1106,0,177,21102,1,514,1,21101,0,176,0,1106,0,579,99,21102,184,1,0,1105,1,579,4,574,104,10,99,1007,573,22,570,1006,570,165,1002,572,1,1182,21101,0,375,1,21101,0,211,0,1105,1,579,21101,1182,11,1,21102,1,222,0,1106,0,979,21102,1,388,1,21102,1,233,0,1106,0,579,21101,1182,22,1,21101,0,244,0,1105,1,979,21101,0,401,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21102,1,266,0,1106,0,979,21102,414,1,1,21102,277,1,0,1105,1,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21102,1182,1,1,21102,1,313,0,1106,0,622,1005,575,327,1101,1,0,575,21101,327,0,0,1105,1,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,50,26,0,109,4,1201,-3,0,587,20102,1,0,-1,22101,1,-3,-3,21102,0,1,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1106,0,597,109,-4,2106,0,0,109,5,2101,0,-4,630,20101,0,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,653,20101,0,0,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21102,702,1,0,1106,0,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21102,731,1,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21101,756,0,0,1105,1,786,1106,0,774,21202,-1,-11,1,22101,1182,1,1,21102,774,1,0,1105,1,622,21201,-3,1,-3,1106,0,640,109,-5,2105,1,0,109,7,1005,575,802,20102,1,576,-6,20101,0,577,-5,1105,1,814,21101,0,0,-1,21101,0,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,51,-3,22201,-6,-3,-3,22101,1475,-3,-3,2102,1,-3,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1105,1,924,1205,-2,873,21102,1,35,-4,1106,0,924,1202,-3,1,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1101,0,2,0,2101,0,-3,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21002,0,1,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,51,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,49,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1102,1,1,575,21101,973,0,0,1105,1,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,0,1,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1105,1,1041,21102,1,-4,-2,1106,0,1041,21101,0,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,2102,1,-2,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,2102,1,-2,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1106,0,989,21101,0,439,1,1105,1,1150,21101,477,0,1,1106,0,1150,21102,1,514,1,21102,1,1149,0,1105,1,579,99,21101,1157,0,0,1106,0,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,2101,0,-5,1176,2102,1,-4,0,109,-6,2106,0,0,32,5,46,1,3,1,46,1,3,1,46,1,3,1,46,1,3,1,46,1,3,1,40,11,40,1,5,1,44,1,5,1,44,1,5,1,44,1,5,1,44,1,5,1,40,11,40,1,3,1,46,1,3,1,46,1,3,1,46,1,3,9,38,1,11,1,26,1,11,1,11,1,26,1,11,1,11,1,26,1,11,5,7,1,26,1,15,1,7,1,26,1,15,1,7,1,26,1,15,1,7,1,26,1,11,7,5,1,26,1,11,1,3,1,1,1,5,1,26,1,9,13,1,1,3,13,10,1,9,1,1,1,3,1,1,1,3,1,1,1,3,1,22,5,5,1,1,13,3,1,26,1,5,1,5,1,1,1,3,1,5,1,26,1,5,1,5,7,5,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,11,26,1,5,1,34,11,5,1,34,1,15,1,34,1,5,9,1,9,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,26,1,5,1,7,1,9,1,22,11,7,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,1,3,1,13,1,9,1,22,5,13,11,22 diff --git a/inputs/day_18.txt b/inputs/day_18.txt deleted file mode 100644 index 3cb4307..0000000 --- a/inputs/day_18.txt +++ /dev/null @@ -1,81 +0,0 @@ -################################################################################# -#.............#.....#.................#.#.....#...#.......#...................#a# -#.#####.#######.#.###.#########.#####.#.#.###Y###.#.#####.#.#####.###########.#.# -#.#...#.#.....#.#..c#.........#...#.#...#...#.#...#.#.#...#.#.#...#...#...#.....# -#.#.###.#.###.#.###.#.###########.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.####### -#.#...#...#.#...#.#...#...........#.#...#.#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.....# -#.#.#.#####.#####.#####.###.#######.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.###.# -#.#.#.............#.#...#.#.#..e..#.....#.#...........#...#.#...#...#...#.....#.# -#.#########.#####.#.#.###.#.#.###.#####.#.###############.#T#.#.###############.# -#...#..k....#.....#.#.Z.#...#...#.....#.#.........#.#.....#.#.#.....#.L.....#...# -###.#.#.#######.###.###.#######.#####.#.#########.#.#.###.#.#.###.#.###.###.#.### -#...#.#.#.....#.#...#...#.....#.....#.#.#...#...#.#.#.#...#.#.#...#...#.#...#...# -#.###.#.#.###.#.#.###.###.###.#####.#.#.#.#.#.#.#.#.#.###.#.###.#####.#.#.#####.# -#.#...#.#.#...#.#...#.....#.#.....#.#.#.#.#...#...#.#...#.#.#...#.#...#.#.#.....# -#.###.#.#.#.###.###.#######.#.#####.#.#.#.#########.###.###.#.###.#.###.#.#.###.# -#...#.#.#.#...#...#.........#.#.....#.#.#.............#.......#...#.#...#.#...#.# -###.#.###.###.###.###.#.#####.#.#####.###############.#########.#.#.###.#.###.#.# -#.....#...#...#.J...#.#.#.....#.....#...#...........#.#...#...#.#.......#...#.#.# -#######.###.#######.#.###.#####.#######.#########.#.#.###.#.#.#########.#####.#.# -#.......#.#...#...#...#...#...#.#.......#.....O.#.#.#.#...#.#.......#...#.....#s# -#.#######.###.#.#.#####.###.#.#.#.#######.#####.#.#.#.#.###.#####.#.#.###.#####.# -#...#...#...#...#...#.#.#...#...#.......#.....#.#.#.#.#...#.#...#.#.#...#...#...# -###.#.#.#.#########.#.#.#.#######.#####.#.#####.#.###.###.#.###.###.#.#####.#.### -#.#...#.#.........#...#...#....d#.....#.#.#.....#.#...#...#.#.#...#.#.#.....#.#.# -#.#####.#######.#######.###.###.#####.#.#.#.#####.#.###.#.#.#.###.#.#.#.#####.#.# -#...#.#.......#.......#...#.#...#.....#.#.#.....#.......#.#.....#.#.#.#.#.......# -#.#.#.#######.#.#.#####.###.#.#####.###.#.#####.#############.###.#.#.#.#######.# -#.#...#.....#.#.#...#...#...#.....#...#.#.#...#.#...........#.#...#.#.#.#...#.#.# -#.###.###.#.#.#.###.#.###.#######.#####.#.###.#.#.#########.#.#.###.#.#.#.#.#.#.# -#...#.....#.#.#...#...#...#.......#.....#...#.#.#.....#...#...#...#.#.#...#.#...# -#.#.#######.#.###.#####.###.#######.#######.#.#.#####.###.#######.#.#####.#.#.### -#.#.#.....#.#.#.#.#.#...#.#.#...#...#...#...#.#.....#...#.....#...#.....#.#.#w#.# -#.#.#.###.#.#.#.#.#.#.###.#.#.#.###.#.#.#.###.#.###.###.#.###.#.###.###.###.#.#.# -#.#.#.#.#.#.#.#.#.#.#.#m..#...#...#...#.#.#...#...#...#.#...#.#.#.....#.#...#.#.# -###.#.#.#.###W#.#.#.#.#.#########.#####.#.#.#.###.#####.###.#.#.#######.#.###.#.# -#...#...#.#...#.....#.#.......#...#...#.#.#.#.#.#.....#.....#.#.........#.#.#...# -#.###.###.#.###.#####.#.###.###.###.#.#.#.#.#.#.#####.#######.###########.#.###.# -#.#...#...#.#...#.S...#...#.....#...#.#.#...#.....#.#.........#...#...#...#.....# -#.#.###.###.#####.#######.#######.###.#.#########.#.###########.#.#.#.#.###.##### -#.....#...........#.......F.......#..................f..........#...#...#.......# -#######################################.@.####################################### -#.....#.#...........#.....#.........................#...#.....#.M.......#.....#.# -###P#.#.#.#######.###.###.#.#######.###.#.#########.#.#.#.###.###.#####.###.#.#.# -#...#...#...#.#...#.....#.#.#.......#...#...#.........#...#.......#...#.....#.#.# -#.#.#######.#.#.###.#####.#.#.#######.#####.###############.#########.#######.#.# -#.#.#.....#.#.#.#...#...#.#.#.#.........#...#.......#...#.....#.....#.#.......#.# -#.###.###.#.#.#.#.###.#.#.#.#.###########.###.#####.#.#.#######.###.#.#.#######.# -#...#.#.#.#...#.#.#...#...#.#...........#...#...#.#...#.......#.#.#.#.#.........# -#.#.#.#.#.#.###.#.#.#####.#######.#####.###.###.#.###########.#.#.#.#.#.#######.# -#.#.#...#...#...#.#r#.....#.....#.....#.#...#.#.#.......#...#.....#.#...#.....#.# -#.#.###.#####.###.#.#######.###.#####.#.#.#.#.#.###.#####.#.#######.#.###.###.#.# -#.#...#.#...#...#.#.........#...#...#.#.#.#...#...#.#.....#.#......p#...#.#.#.#.# -###.#.#.#.#.###.#.###########.###.#.#.#.#.###.###.#.#.#####.#.###.#######.#.#.### -#...#.#.#.#...#.......#.....#.#...#...#.#...#.#...#.....#...#.#...#.K...#.#.#...# -#.#####.#.###.#######.#.###Q#.#.#######.###.#.#.#####.###.###.#.###.###.#.#.###.# -#.....#...#...#.#...#.#.#.#...#...#.....#...#.#.....#.#...#...#.#...#.#..j#.#...# -#.###.#####.###.#.#.###.#.#########.###.#.#########.###.#.#.###.#.###.#####.#.### -#...#.#.....#...#.#.B...#...#...#...#...#.#.......#.....#.#...#.#...........#.R.# -#.###.#.#######.#.#######.#.#.#.#.###.###.#.#.###.#######.###.###.#############.# -#.#...#.......#.#n....#...#.#.#...#...#.#...#...#.....#...#.#.....#..u..#.....#.# -###.#.#######.#.#####.#.###.#.#####.###.#.#####.###.###.###.###.###.###.#.###.#.# -#...#.#...#...#.....#.#.#...#...#.#...#.#...#...#...#...#...#.#.#...#...#.#...#.# -#.#####.#.#.###.#.#####.#.###.#.#.###.#.#####.#######.#####.#.###.###.###.###.#.# -#...#...#.#.#...#.......#.#...#.#...#...#.....#.......#.....#.U...#.#...#...#...# -#.#.#.###.#.#.#########.#.#####.###.###.#.#.###.#######.###########.###X#.#.###.# -#.#..l#...#.#...#.......#.....#...#...#.#.#o#...#.#.....#...#......x....#.#.#...# -#.#####C###.#.###.###########.###.#.###.#.###.###.#.###.#.#.#I#############.#.### -#.....#...#.#.#...#...#.....#.#...#.#...#.#...#.....#...#.#...#v......G.#...#..q# -###.#####.#.###.###.#.#.###.#.#.###.#.###.#.###.#####.#.#.#####.#######.#.#####.# -#.#y#...#.#...#.#...#.#...#.#...#...#...#.#.#...#.....#.#..i..#...#.....#...#...# -#.#.#.#.#.###.#.#.###.#.#.#.#####.#.###.#.#.###.#.###########H#.#.#.#####.#.#.### -#...#.#.#...#.#.....#.#.#.#.#...#.#.....#.#...#.#...........#.#.#.#g..#...#.#...# -#.###.#.###A#.#######.#.#.#.#.###.#######.###.#.#########.#.#.#.#.###.#####.###.# -#.#...#.....#.........#.#.#.#.#...#.....#...#.#.......#...#.#.#.#.#.#.#...#...#.# -###.#####################.#.#.#.#####.###.#.#.#########.###.#.###.#.#.#.#.###.#.# -#...#.......#.............#..t#.#...#...#.#.#.#.......#.#...#...#.#.#.N.#.....#.# -#.###.#####.#.#########.#######.#.#D#.#.#.#.#.#.#####.#.#.#####.#.#.###########.# -#.#...#...#..z#.#.......#.....#...#.#.#.#.#.#...#...#...#.#.#..h#.#.....#......b# -#.#.###.#.#####.#.#######.###.#####.###.#.#.#####.#.#####.#.#.###.#.###.#.####### -#.......#.......#...........#...........#.#.....E.#.........#...V.#...#.........# -################################################################################# diff --git a/inputs/day_18_2.txt b/inputs/day_18_2.txt deleted file mode 100644 index 8fda759..0000000 --- a/inputs/day_18_2.txt +++ /dev/null @@ -1,81 +0,0 @@ -################################################################################# -#.............#.....#.................#.#.....#...#.......#...................#a# -#.#####.#######.#.###.#########.#####.#.#.###Y###.#.#####.#.#####.###########.#.# -#.#...#.#.....#.#..c#.........#...#.#...#...#.#...#.#.#...#.#.#...#...#...#.....# -#.#.###.#.###.#.###.#.###########.#.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.####### -#.#...#...#.#...#.#...#...........#.#...#.#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.....# -#.#.#.#####.#####.#####.###.#######.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.###.# -#.#.#.............#.#...#.#.#..e..#.....#.#...........#...#.#...#...#...#.....#.# -#.#########.#####.#.#.###.#.#.###.#####.#.###############.#T#.#.###############.# -#...#..k....#.....#.#.Z.#...#...#.....#.#.........#.#.....#.#.#.....#.L.....#...# -###.#.#.#######.###.###.#######.#####.#.#########.#.#.###.#.#.###.#.###.###.#.### -#...#.#.#.....#.#...#...#.....#.....#.#.#...#...#.#.#.#...#.#.#...#...#.#...#...# -#.###.#.#.###.#.#.###.###.###.#####.#.#.#.#.#.#.#.#.#.###.#.###.#####.#.#.#####.# -#.#...#.#.#...#.#...#.....#.#.....#.#.#.#.#...#...#.#...#.#.#...#.#...#.#.#.....# -#.###.#.#.#.###.###.#######.#.#####.#.#.#.#########.###.###.#.###.#.###.#.#.###.# -#...#.#.#.#...#...#.........#.#.....#.#.#.............#.......#...#.#...#.#...#.# -###.#.###.###.###.###.#.#####.#.#####.###############.#########.#.#.###.#.###.#.# -#.....#...#...#.J...#.#.#.....#.....#...#...........#.#...#...#.#.......#...#.#.# -#######.###.#######.#.###.#####.#######.#########.#.#.###.#.#.#########.#####.#.# -#.......#.#...#...#...#...#...#.#.......#.....O.#.#.#.#...#.#.......#...#.....#s# -#.#######.###.#.#.#####.###.#.#.#.#######.#####.#.#.#.#.###.#####.#.#.###.#####.# -#...#...#...#...#...#.#.#...#...#.......#.....#.#.#.#.#...#.#...#.#.#...#...#...# -###.#.#.#.#########.#.#.#.#######.#####.#.#####.#.###.###.#.###.###.#.#####.#.### -#.#...#.#.........#...#...#....d#.....#.#.#.....#.#...#...#.#.#...#.#.#.....#.#.# -#.#####.#######.#######.###.###.#####.#.#.#.#####.#.###.#.#.#.###.#.#.#.#####.#.# -#...#.#.......#.......#...#.#...#.....#.#.#.....#.......#.#.....#.#.#.#.#.......# -#.#.#.#######.#.#.#####.###.#.#####.###.#.#####.#############.###.#.#.#.#######.# -#.#...#.....#.#.#...#...#...#.....#...#.#.#...#.#...........#.#...#.#.#.#...#.#.# -#.###.###.#.#.#.###.#.###.#######.#####.#.###.#.#.#########.#.#.###.#.#.#.#.#.#.# -#...#.....#.#.#...#...#...#.......#.....#...#.#.#.....#...#...#...#.#.#...#.#...# -#.#.#######.#.###.#####.###.#######.#######.#.#.#####.###.#######.#.#####.#.#.### -#.#.#.....#.#.#.#.#.#...#.#.#...#...#...#...#.#.....#...#.....#...#.....#.#.#w#.# -#.#.#.###.#.#.#.#.#.#.###.#.#.#.###.#.#.#.###.#.###.###.#.###.#.###.###.###.#.#.# -#.#.#.#.#.#.#.#.#.#.#.#m..#...#...#...#.#.#...#...#...#.#...#.#.#.....#.#...#.#.# -###.#.#.#.###W#.#.#.#.#.#########.#####.#.#.#.###.#####.###.#.#.#######.#.###.#.# -#...#...#.#...#.....#.#.......#...#...#.#.#.#.#.#.....#.....#.#.........#.#.#...# -#.###.###.#.###.#####.#.###.###.###.#.#.#.#.#.#.#####.#######.###########.#.###.# -#.#...#...#.#...#.S...#...#.....#...#.#.#...#.....#.#.........#...#...#...#.....# -#.#.###.###.#####.#######.#######.###.#.#########.#.###########.#.#.#.#.###.##### -#.....#...........#.......F.......#....@#@...........f..........#...#...#.......# -################################################################################# -#.....#.#...........#.....#............@#@..........#...#.....#.M.......#.....#.# -###P#.#.#.#######.###.###.#.#######.###.#.#########.#.#.#.###.###.#####.###.#.#.# -#...#...#...#.#...#.....#.#.#.......#...#...#.........#...#.......#...#.....#.#.# -#.#.#######.#.#.###.#####.#.#.#######.#####.###############.#########.#######.#.# -#.#.#.....#.#.#.#...#...#.#.#.#.........#...#.......#...#.....#.....#.#.......#.# -#.###.###.#.#.#.#.###.#.#.#.#.###########.###.#####.#.#.#######.###.#.#.#######.# -#...#.#.#.#...#.#.#...#...#.#...........#...#...#.#...#.......#.#.#.#.#.........# -#.#.#.#.#.#.###.#.#.#####.#######.#####.###.###.#.###########.#.#.#.#.#.#######.# -#.#.#...#...#...#.#r#.....#.....#.....#.#...#.#.#.......#...#.....#.#...#.....#.# -#.#.###.#####.###.#.#######.###.#####.#.#.#.#.#.###.#####.#.#######.#.###.###.#.# -#.#...#.#...#...#.#.........#...#...#.#.#.#...#...#.#.....#.#......p#...#.#.#.#.# -###.#.#.#.#.###.#.###########.###.#.#.#.#.###.###.#.#.#####.#.###.#######.#.#.### -#...#.#.#.#...#.......#.....#.#...#...#.#...#.#...#.....#...#.#...#.K...#.#.#...# -#.#####.#.###.#######.#.###Q#.#.#######.###.#.#.#####.###.###.#.###.###.#.#.###.# -#.....#...#...#.#...#.#.#.#...#...#.....#...#.#.....#.#...#...#.#...#.#..j#.#...# -#.###.#####.###.#.#.###.#.#########.###.#.#########.###.#.#.###.#.###.#####.#.### -#...#.#.....#...#.#.B...#...#...#...#...#.#.......#.....#.#...#.#...........#.R.# -#.###.#.#######.#.#######.#.#.#.#.###.###.#.#.###.#######.###.###.#############.# -#.#...#.......#.#n....#...#.#.#...#...#.#...#...#.....#...#.#.....#..u..#.....#.# -###.#.#######.#.#####.#.###.#.#####.###.#.#####.###.###.###.###.###.###.#.###.#.# -#...#.#...#...#.....#.#.#...#...#.#...#.#...#...#...#...#...#.#.#...#...#.#...#.# -#.#####.#.#.###.#.#####.#.###.#.#.###.#.#####.#######.#####.#.###.###.###.###.#.# -#...#...#.#.#...#.......#.#...#.#...#...#.....#.......#.....#.U...#.#...#...#...# -#.#.#.###.#.#.#########.#.#####.###.###.#.#.###.#######.###########.###X#.#.###.# -#.#..l#...#.#...#.......#.....#...#...#.#.#o#...#.#.....#...#......x....#.#.#...# -#.#####C###.#.###.###########.###.#.###.#.###.###.#.###.#.#.#I#############.#.### -#.....#...#.#.#...#...#.....#.#...#.#...#.#...#.....#...#.#...#v......G.#...#..q# -###.#####.#.###.###.#.#.###.#.#.###.#.###.#.###.#####.#.#.#####.#######.#.#####.# -#.#y#...#.#...#.#...#.#...#.#...#...#...#.#.#...#.....#.#..i..#...#.....#...#...# -#.#.#.#.#.###.#.#.###.#.#.#.#####.#.###.#.#.###.#.###########H#.#.#.#####.#.#.### -#...#.#.#...#.#.....#.#.#.#.#...#.#.....#.#...#.#...........#.#.#.#g..#...#.#...# -#.###.#.###A#.#######.#.#.#.#.###.#######.###.#.#########.#.#.#.#.###.#####.###.# -#.#...#.....#.........#.#.#.#.#...#.....#...#.#.......#...#.#.#.#.#.#.#...#...#.# -###.#####################.#.#.#.#####.###.#.#.#########.###.#.###.#.#.#.#.###.#.# -#...#.......#.............#..t#.#...#...#.#.#.#.......#.#...#...#.#.#.N.#.....#.# -#.###.#####.#.#########.#######.#.#D#.#.#.#.#.#.#####.#.#.#####.#.#.###########.# -#.#...#...#..z#.#.......#.....#...#.#.#.#.#.#...#...#...#.#.#..h#.#.....#......b# -#.#.###.#.#####.#.#######.###.#####.###.#.#.#####.#.#####.#.#.###.#.###.#.####### -#.......#.......#...........#...........#.#.....E.#.........#...V.#...#.........# -################################################################################# diff --git a/inputs/day_19.txt b/inputs/day_19.txt deleted file mode 100644 index e85881e..0000000 --- a/inputs/day_19.txt +++ /dev/null @@ -1 +0,0 @@ -109,424,203,1,21102,11,1,0,1106,0,282,21101,0,18,0,1106,0,259,1201,1,0,221,203,1,21102,1,31,0,1106,0,282,21101,0,38,0,1106,0,259,20102,1,23,2,21202,1,1,3,21101,1,0,1,21101,0,57,0,1105,1,303,2101,0,1,222,20101,0,221,3,21001,221,0,2,21102,1,259,1,21101,0,80,0,1105,1,225,21101,185,0,2,21102,91,1,0,1106,0,303,1202,1,1,223,21001,222,0,4,21102,259,1,3,21101,225,0,2,21102,1,225,1,21101,0,118,0,1106,0,225,20102,1,222,3,21102,1,131,2,21101,133,0,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1105,1,259,2101,0,1,223,21002,221,1,4,21002,222,1,3,21101,0,16,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21101,0,195,0,106,0,109,20207,1,223,2,20101,0,23,1,21102,1,-1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,1201,-4,0,249,22101,0,-3,1,22101,0,-2,2,21201,-1,0,3,21101,0,250,0,1106,0,225,21201,1,0,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22102,1,-2,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,21201,-2,0,3,21101,343,0,0,1106,0,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,22101,0,-4,1,21102,384,1,0,1106,0,303,1105,1,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21201,1,0,-4,109,-5,2106,0,0 diff --git a/inputs/day_2.txt b/inputs/day_2.txt deleted file mode 100644 index dd34cff..0000000 --- a/inputs/day_2.txt +++ /dev/null @@ -1 +0,0 @@ -1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,9,1,19,1,19,5,23,1,23,6,27,2,9,27,31,1,5,31,35,1,35,10,39,1,39,10,43,2,43,9,47,1,6,47,51,2,51,6,55,1,5,55,59,2,59,10,63,1,9,63,67,1,9,67,71,2,71,6,75,1,5,75,79,1,5,79,83,1,9,83,87,2,87,10,91,2,10,91,95,1,95,9,99,2,99,9,103,2,10,103,107,2,9,107,111,1,111,5,115,1,115,2,119,1,119,6,0,99,2,0,14,0 diff --git a/inputs/day_20.txt b/inputs/day_20.txt deleted file mode 100644 index 09d6330..0000000 --- a/inputs/day_20.txt +++ /dev/null @@ -1,113 +0,0 @@ - K Z V U I F - Q T Y Y E E - ###################################.#####.###.###########.#####.#.##################################### - #.......#.#.............#.........#.#.......#.#.#.........#.....#...#...#...........#...#.....#.#.....# - ###.#####.###.###.###.###########.#.###.#####.#.###.#.#.#.###.###.###.#####.#######.###.#####.#.###.### - #.#...#.#.#.#.#.#.#.#.....#...........#.....#.#...#.#.#.#...#.#.#.#.....#.#.#...#.#.#...#.#.#.....#...# - #.#.###.#.#.###.###.#.#########.###.#######.#.#.#.#######.#.#.#.#.#.###.#.#.#.###.#####.#.#.#.#####.### - #.....#...#...............#.#.#.#.#.#.....#.#.#.#...#.....#.#.#.#.#...#.....#.#.#.........#...#.#...#.# - #.#######.###########.###.#.#.###.#.###.#.#.#.#.###.###.###.#.#.#.#.###.#.###.#.#.#.#######.###.###.#.# - #...#.......#...#.#...#...#...#.#.#.#...#...#.....#.#.#.#...#...#...#...#.........#.#.#.#...#.......#.# - #.#######.#.###.#.#######.###.#.#.#.#.#.###.###.#####.#####.###.#.#####.#####.#.#.###.#.###.#.#######.# - #.#.#...#.#...#.......#.......#.#...#.#...#.#.#...#.#.......#...#.#.........#.#.#...............#.....# - #.#.#.#######.#####.#####.###.#.###.#.#####.#.#.###.#####.###.#####.###.###########.###############.### - #.#...#...#.......#...#...#.#.......#.....#.#.....#.#.......#.#...#.#.#.#.......#.......#...#...#.#...# - #.###.###.#####.#.###.#####.#####.#.###.#######.#.#.#######.#.#.#####.#.#.###########.#####.###.#.#.### - #.#.#.#...#...#.#.#...#.#.#.#.#.#.#.#...#.......#.#.#.#.....#.....#...............#...#.#...#.........# - #.#.#.#.#####.#.#####.#.#.#.#.#.###.#.#####.###.###.#.#####.#.#######.#.#######.#######.#.#.###.#####.# - #.......#.#.#...#.#...............#.#...#.#.#.......#...#...#.......#.#.#.#.#...#.#.....#.#.#...#.#...# - #.#######.#.###.#.#.###.#.#.#.###.#.###.#.###.#.###.#.###.#.#.#.#######.#.#.#####.#.#######.#.###.###.# - #.#.#.#.#.#.......#.#.#.#.#.#.#.#.#.#...#...#.#.#.#.#.....#.#.#.#.#.#...#.......#.#.#.#...#.#.#...#.#.# - #.#.#.#.#.#####.#####.#.#####.#.#.#.#.###.#.#.###.#####.#####.#.#.#.#.#####.#.###.#.#.#.###.#.###.#.### - #.#.#.#.#.#.....#.#.....#.......#.#.#.#...#.#...#...#.......#.#.#.#.........#.#...#.......#.#.#.#.#.#.# - #.#.#.#.#.#.###.#.#.#####.###.#.#.#.#.#.###.#.###.#.###.#######.#.#.###.###.#####.#.#.#.###.#.#.#.#.#.# - #.......#.#.#.#.#.#.#...#.#.#.#.#...#...#...#...#.#.#.....#.#...#...#...#.......#...#.#...#.#.#.#...#.# - #####.###.#.#.###.#####.###.###.###.#####.#####.#.#.#.#####.#.#.#####.#######.#####.#######.#.#.#.###.# - #.#...#.........#...#.#.......#...#...#.....#...#.#.#.....#...#.#...........#.#.#.#...#.#.........#...# - #.###.#.#.#######.#.#.#.#########.#########.#.###.#.#.#.###.#.#########.###.###.#.#.###.###.#######.### - #.#.....#...#...#.#...#.....#.......#.......#.....#.#.#...#.#.....#.....#.....#...#.#...#.........#...# - #.###.#.#.#####.###.###.#######.#####.#############.#.#########.###.###########.###.#.#.#.###.#.###.#.# - #...#.#.#.#.#...#.#.#.....# U N Q W Z N #.......#.#...#...#...#.#.# - ###.###.###.###.#.#.###.### Y D P L W J #####.#########.#######.### - #.#.#.#.#...#...#.#...#.#.# #.....#...#...........#.#.# - #.#.#.#.###.###.#.#.###.#.# ###.#.###.###.###.#####.#.# - #...................#.#...# #.#.#.........#...#........CB - #.###.#######.#.###.#.#.#.# #.#.#.###.#####.###.#.#.#.# - #.#.........#.#...#.....#.# #...#.#.....#...#...#.#.#..AA - #######.#######.###.#####.# #.#######.#.###.#.#.###.### - #.....#.......#...#...#...# QJ..#.#...#.#.#.#...#...#.#.# - ###.#.#.###.###########.### ###.#.#######.###########.# -YG....#.....#.#.......#......TY #.........#...........#...# - #.#.#.###########.#.#.##### #.#####.###.#########.#.#.# - #.#.#.#...#...#...#.#.#...# CB..#.#.......#.#.#.#.....#..DN - #######.#####.#.#.#####.### ###.#########.#.#.######### - #.....#...#...#.#.#...#.#.# #...#.........#...#.......# - #.###.#.#.#.#.#.#.#.#.#.#.# ###.###.#####.#.#.#.#####.# -SP..#.....#...#...#...#......YG #.......#...#...#.#.#.....# - ########################### #.#.###.###.#.###.#.#.##### -NJ....#.................#.#.# KQ..#.#.......#.#...#.#.....# - #.#.#.#####.#.#.#####.#.#.# ###.###.###.###.#.#.###.#.# - #.#.#.....#.#.#.#.....#...# #.#...#.#.#.#.#.#.....#.#..IT - ###.#####.###.#####.#####.# #.#.#####.###.############# - #.#.....#...#.....#........WE IE..#.#.#.#...............#.# - #.#.#.#.#.#########.#.###.# #.#.#.#.#.###.###.###.###.# - #...#.#...#.#.#.#...#.#...# #.#.#...#.#.#...#.#...#.#.# - #.#######.#.#.#.#####.##### #.#####.#.#.#.#.#####.#.#.# - #.#.....#.#.........#.#...# #...........#.#.#.#...#....QJ - #######.###.#.#.###.#####.# #######.#.#######.#.#.###.# - #.#.....#...#.#.#.........# #.....#.#.#...#.#...#.....# - #.###.#.#.#######.#.#####.# ###.#########.#.########### -YV..#...#.#...#.#.#.#.#.....# #.......#.........#.#.....# - #.#.###.#.#.#.#.#.###.#.### #.#####.###.#####.#.#.#.#.# - #.....#...#.#...#.#.#.#....QX #.#...#.........#.#...#.#..QP - ###.###.#######.###.###.#.# #.###.#.###.#####.#.#####.# - #.#.#.....#.....#.....#.#.# #.#.#.#.#...#.....#...#...# - #.#####.#######.###.#.##### #.#.#.#####.#.###.###.#.#.# - #.#...#.#.....#.#.#.#...#..DM FE..#.#...#.#.#.#.......#.#.# - #.#.#####.#.###.#.#.###.#.# #.#.#.#.#.###############.# - #.#.......#...#.#.....#...# #.#...#.#.#.....#.......#.# - #.#.#.#.#.###.#.#####.###.# #######.#.#.#######.#.##### -QX....#.#.#.#.............#.# #.......#.#.......#.#.....# - #####.#.#.#.#.#.########### ###.###.#.#.#.###.#.#####.# - #.#.#.#.#.#.#.#.#.........# GX..#.#.......#.#.#.......#..DM - #.#.###############.###.#.# #.#.#####.#.###.###.###.#.# - #.#.#.........#...#...#.#..CS #.....#.#.#.#.#...#.#.#.#.# - #.#.#######.#####.###.#.### #######.#.###.#.#####.##### -WE........#.#.#.#.#.#...#...# MX........#.#.........#......CS - #####.###.#.#.#.#.#.#.##### #####.###.###.#####.###.### - #...#...............#.#.#.# #.#.....#.#.......#...#...# - ###.###################.#.# #.#.###########.#.###.#.#.# - #...............#.#........ME #.#.#.#...#...#.#.#...#.#.# - #.#.#####.#####.#.#.###.#.# #.#.#####.#######.#.#####.# -GX..#...#.#.#...........#.#.# #.................#.......# - #.#.###.#######.###.#####.# J D Z V S I Y #.###.###.#.###.###.#.#.#.# - #.#.......#.......#.....#.# I N T Y P T V #...#...#.#.#.#.#.#.#.#.#.# - #.#.#.#########.#.#.#############.#########.###.#.#.#############.###.###########.###.#.#.#.#.#.#####.# - #.#.#.....#.....#.#...#.......#.....#.......#.....#.#.#.#.#...#...#.........#.....#...#.#.....#...#...# - #.#############.###.#######.#.#####.#.###.###.#####.#.#.#.###.#.#####.#.#.#####.#.#.#.#.#####.###.##### - #...........#.....#.....#...#.......#...#.#.#.....#.#.....#.#.......#.#.#...#...#.#.#.#.#.....#.#.....# - ###.#######.#######.#####.###.#######.#.###.###.#.#.#.###.#.#.#######.#############.#.#######.#.#.###.# - #.#.....#.#.#.#.......#.#.#.#...#...#.#...#...#.#.#.....#...#.......#.....#.#...#...#...#.......#.#...# - #.#.#.###.#.#.#.#.###.#.###.###.#.#.###.#.###.#.#########.#####.#.###.#.###.#.#########.#####.#####.#.# - #...#...#.....#.#.#...#...#.#...#.#...#.#.#.....#.#.#.....#...#.#.#...#.............#.....#.....#...#.# - #####.###########.#####.###.#.###.#.###.#####.#.#.#.###.#.#.#.###.#.#######.###.#########.#.#.######### - #.........#.....#.#...........#...#.#...#.#...#.#...#...#.#.#.....#.......#...#.#.....#.#.#.#.....#.#.# - ###.###.#.###.#####.#.#.#.#.#.#.###.###.#.###.#####.#.#####.#.###.###.#####.#####.#####.#####.#####.#.# - #...#.#.#.#.........#.#.#.#.#...#...#.....#.....#.......#...#.#.#.#.......#.#.#...#.....#.#.#.........# - #.#.#.#.###.###.###########.###.#.###.#.#####.#.#.#.#.#.#.#.###.###.#.###.###.###.#.#.#.#.#.#.###.#.#.# - #.#.#...#...#.....#.........#.#.#...#.#.#.#...#.#.#.#.#.#.#.......#.#...#.#.....#...#.#.#.......#.#.#.# - #.#.###.#.#.#.#.#.#####.#####.#.###.#.###.###.#####.#######.###.###.#########.###.#######.#.#.#####.#.# - #.#.#...#.#.#.#.#.#.#.#.#.......#...#...#...#...#.....#.#.....#.#.#.......#...#.....#.#.#.#.#.#.#...#.# - #.#####.#.#####.###.#.#######.#.#.#.###.###.#.#.###.###.###.#####.#.#.#####.#####.#.#.#.###.#.#.#####.# - #...#...#.#.....#.#.....#.#...#.#.#.#...#.#...#.#.......#.#.#.#.#...#...........#.#.#...#.#.#.....#.#.# - ###.###.#########.#####.#.###.#####.#.###.###.#####.#####.#.#.#.#.#######.#######.###.###.#####.#.#.### - #.....#.#.....................#...#.#.......#.#.....#.....#.....#.#...........#.....#.#.#.#.#...#.#...# - #.###.#####.#.#.#.###.#.#.#.###.###.###.#.###.#####.###.#.#.#########.###########.###.#.#.#.###.###.### - #...#...#...#.#.#.#...#.#.#.#.......#.#.#...#.....#.#...#.#.......#.#.........#.............#.........# - ###.#.#####.#############.#####.#.###.#.###.#####.#.#.###.###.#.#.#.#####.#.###.###.###.###.#.#####.### - #...#.#.#.#...#.#...#.......#...#.....#.#...#.....#...#.#.#.#.#.#...#.....#.....#.....#...#.#...#.....# - #.###.#.#.###.#.###.###.#####.#####.#####.###.#########.#.#.#####.#######.#####.###.#####.#.#.###.###.# - #.#.........#.#.........#.....#.....#.....#.........#.....#.......#...........#...#...#...#.#...#.#...# - ###################################.###.#######.#.###.###.###.#######.################################# - N J W Z Z M M T - D I L W Z X E Y diff --git a/inputs/day_21.txt b/inputs/day_21.txt deleted file mode 100644 index cafb613..0000000 --- a/inputs/day_21.txt +++ /dev/null @@ -1 +0,0 @@ -109,2050,21102,1,966,1,21101,0,13,0,1106,0,1378,21101,20,0,0,1105,1,1337,21101,27,0,0,1105,1,1279,1208,1,65,748,1005,748,73,1208,1,79,748,1005,748,110,1208,1,78,748,1005,748,132,1208,1,87,748,1005,748,169,1208,1,82,748,1005,748,239,21101,0,1041,1,21102,73,1,0,1106,0,1421,21101,0,78,1,21101,0,1041,2,21101,88,0,0,1106,0,1301,21101,68,0,1,21102,1041,1,2,21102,103,1,0,1106,0,1301,1101,0,1,750,1105,1,298,21101,0,82,1,21101,0,1041,2,21102,1,125,0,1105,1,1301,1102,1,2,750,1105,1,298,21102,79,1,1,21102,1,1041,2,21101,147,0,0,1106,0,1301,21102,1,84,1,21102,1,1041,2,21101,0,162,0,1106,0,1301,1101,0,3,750,1106,0,298,21101,0,65,1,21101,1041,0,2,21101,0,184,0,1106,0,1301,21101,76,0,1,21102,1,1041,2,21101,199,0,0,1106,0,1301,21102,75,1,1,21102,1,1041,2,21101,214,0,0,1105,1,1301,21101,221,0,0,1106,0,1337,21101,10,0,1,21102,1041,1,2,21102,236,1,0,1105,1,1301,1106,0,553,21102,1,85,1,21102,1,1041,2,21101,254,0,0,1105,1,1301,21101,78,0,1,21101,0,1041,2,21102,1,269,0,1106,0,1301,21102,276,1,0,1105,1,1337,21101,10,0,1,21102,1,1041,2,21101,0,291,0,1105,1,1301,1101,1,0,755,1105,1,553,21101,32,0,1,21102,1,1041,2,21102,313,1,0,1106,0,1301,21102,1,320,0,1106,0,1337,21102,327,1,0,1105,1,1279,1202,1,1,749,21102,65,1,2,21101,0,73,3,21102,1,346,0,1106,0,1889,1206,1,367,1007,749,69,748,1005,748,360,1101,0,1,756,1001,749,-64,751,1106,0,406,1008,749,74,748,1006,748,381,1102,1,-1,751,1105,1,406,1008,749,84,748,1006,748,395,1102,1,-2,751,1105,1,406,21102,1100,1,1,21101,0,406,0,1105,1,1421,21101,32,0,1,21102,1,1100,2,21101,421,0,0,1105,1,1301,21102,1,428,0,1106,0,1337,21102,435,1,0,1105,1,1279,2102,1,1,749,1008,749,74,748,1006,748,453,1102,1,-1,752,1106,0,478,1008,749,84,748,1006,748,467,1101,0,-2,752,1105,1,478,21101,1168,0,1,21101,0,478,0,1106,0,1421,21102,485,1,0,1105,1,1337,21102,1,10,1,21101,1168,0,2,21101,0,500,0,1105,1,1301,1007,920,15,748,1005,748,518,21101,0,1209,1,21102,1,518,0,1106,0,1421,1002,920,3,529,1001,529,921,529,101,0,750,0,1001,529,1,537,101,0,751,0,1001,537,1,545,1001,752,0,0,1001,920,1,920,1105,1,13,1005,755,577,1006,756,570,21102,1100,1,1,21101,570,0,0,1105,1,1421,21102,1,987,1,1105,1,581,21101,1001,0,1,21102,1,588,0,1106,0,1378,1101,0,758,593,1001,0,0,753,1006,753,654,21001,753,0,1,21101,610,0,0,1106,0,667,21101,0,0,1,21101,621,0,0,1106,0,1463,1205,1,647,21101,1015,0,1,21101,635,0,0,1106,0,1378,21101,1,0,1,21101,646,0,0,1105,1,1463,99,1001,593,1,593,1106,0,592,1006,755,664,1101,0,0,755,1105,1,647,4,754,99,109,2,1102,1,726,757,21202,-1,1,1,21101,9,0,2,21102,1,697,3,21102,692,1,0,1105,1,1913,109,-2,2105,1,0,109,2,101,0,757,706,1201,-1,0,0,1001,757,1,757,109,-2,2106,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,255,63,95,191,159,223,127,0,155,123,163,249,179,110,200,117,68,60,61,190,197,250,196,186,111,187,99,158,244,217,222,246,94,205,35,54,115,239,218,243,62,241,229,168,79,199,215,178,182,118,43,228,125,203,214,113,231,120,77,153,141,157,253,143,87,102,86,207,213,177,57,181,156,85,78,204,247,174,109,172,248,92,98,53,93,232,69,242,212,237,152,70,216,183,47,49,124,121,116,122,230,114,100,103,201,51,55,84,171,234,254,238,233,76,185,34,50,175,219,140,42,189,136,38,226,169,39,184,198,166,137,220,251,245,202,142,56,139,167,206,126,252,106,107,71,162,235,236,101,108,119,58,173,170,46,221,227,59,154,188,138,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,73,110,112,117,116,32,105,110,115,116,114,117,99,116,105,111,110,115,58,10,13,10,87,97,108,107,105,110,103,46,46,46,10,10,13,10,82,117,110,110,105,110,103,46,46,46,10,10,25,10,68,105,100,110,39,116,32,109,97,107,101,32,105,116,32,97,99,114,111,115,115,58,10,10,58,73,110,118,97,108,105,100,32,111,112,101,114,97,116,105,111,110,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,78,68,44,32,79,82,44,32,111,114,32,78,79,84,67,73,110,118,97,108,105,100,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,44,32,66,44,32,67,44,32,68,44,32,74,44,32,111,114,32,84,40,73,110,118,97,108,105,100,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,74,32,111,114,32,84,52,79,117,116,32,111,102,32,109,101,109,111,114,121,59,32,97,116,32,109,111,115,116,32,49,53,32,105,110,115,116,114,117,99,116,105,111,110,115,32,99,97,110,32,98,101,32,115,116,111,114,101,100,0,109,1,1005,1262,1270,3,1262,20101,0,1262,0,109,-1,2106,0,0,109,1,21102,1,1288,0,1106,0,1263,21001,1262,0,0,1102,0,1,1262,109,-1,2106,0,0,109,5,21102,1310,1,0,1105,1,1279,22102,1,1,-2,22208,-2,-4,-1,1205,-1,1332,22101,0,-3,1,21101,1332,0,0,1106,0,1421,109,-5,2106,0,0,109,2,21101,1346,0,0,1105,1,1263,21208,1,32,-1,1205,-1,1363,21208,1,9,-1,1205,-1,1363,1105,1,1373,21102,1,1370,0,1106,0,1279,1106,0,1339,109,-2,2105,1,0,109,5,1202,-4,1,1386,20101,0,0,-2,22101,1,-4,-4,21102,0,1,-3,22208,-3,-2,-1,1205,-1,1416,2201,-4,-3,1408,4,0,21201,-3,1,-3,1106,0,1396,109,-5,2106,0,0,109,2,104,10,22102,1,-1,1,21101,0,1436,0,1106,0,1378,104,10,99,109,-2,2105,1,0,109,3,20002,593,753,-1,22202,-1,-2,-1,201,-1,754,754,109,-3,2105,1,0,109,10,21102,5,1,-5,21102,1,1,-4,21102,1,0,-3,1206,-9,1555,21101,3,0,-6,21101,5,0,-7,22208,-7,-5,-8,1206,-8,1507,22208,-6,-4,-8,1206,-8,1507,104,64,1105,1,1529,1205,-6,1527,1201,-7,716,1515,21002,0,-11,-8,21201,-8,46,-8,204,-8,1105,1,1529,104,46,21201,-7,1,-7,21207,-7,22,-8,1205,-8,1488,104,10,21201,-6,-1,-6,21207,-6,0,-8,1206,-8,1484,104,10,21207,-4,1,-8,1206,-8,1569,21102,1,0,-9,1105,1,1689,21208,-5,21,-8,1206,-8,1583,21102,1,1,-9,1106,0,1689,1201,-5,716,1588,21002,0,1,-2,21208,-4,1,-1,22202,-2,-1,-1,1205,-2,1613,21201,-5,0,1,21102,1613,1,0,1105,1,1444,1206,-1,1634,22101,0,-5,1,21101,0,1627,0,1106,0,1694,1206,1,1634,21101,2,0,-3,22107,1,-4,-8,22201,-1,-8,-8,1206,-8,1649,21201,-5,1,-5,1206,-3,1663,21201,-3,-1,-3,21201,-4,1,-4,1106,0,1667,21201,-4,-1,-4,21208,-4,0,-1,1201,-5,716,1676,22002,0,-1,-1,1206,-1,1686,21101,1,0,-4,1105,1,1477,109,-10,2106,0,0,109,11,21102,0,1,-6,21101,0,0,-8,21101,0,0,-7,20208,-6,920,-9,1205,-9,1880,21202,-6,3,-9,1201,-9,921,1724,21002,0,1,-5,1001,1724,1,1733,20101,0,0,-4,21202,-4,1,1,21101,1,0,2,21101,9,0,3,21101,1754,0,0,1105,1,1889,1206,1,1772,2201,-10,-4,1767,1001,1767,716,1767,20102,1,0,-3,1105,1,1790,21208,-4,-1,-9,1206,-9,1786,22101,0,-8,-3,1105,1,1790,22101,0,-7,-3,1001,1733,1,1795,21001,0,0,-2,21208,-2,-1,-9,1206,-9,1812,21201,-8,0,-1,1105,1,1816,22101,0,-7,-1,21208,-5,1,-9,1205,-9,1837,21208,-5,2,-9,1205,-9,1844,21208,-3,0,-1,1106,0,1855,22202,-3,-1,-1,1106,0,1855,22201,-3,-1,-1,22107,0,-1,-1,1106,0,1855,21208,-2,-1,-9,1206,-9,1869,21201,-1,0,-8,1105,1,1873,22101,0,-1,-7,21201,-6,1,-6,1105,1,1708,22102,1,-8,-10,109,-11,2106,0,0,109,7,22207,-6,-5,-3,22207,-4,-6,-2,22201,-3,-2,-1,21208,-1,0,-6,109,-7,2105,1,0,0,109,5,2102,1,-2,1912,21207,-4,0,-1,1206,-1,1930,21102,1,0,-4,22101,0,-4,1,21202,-3,1,2,21102,1,1,3,21102,1949,1,0,1105,1,1954,109,-5,2105,1,0,109,6,21207,-4,1,-1,1206,-1,1977,22207,-5,-3,-1,1206,-1,1977,21202,-5,1,-5,1105,1,2045,22102,1,-5,1,21201,-4,-1,2,21202,-3,2,3,21102,1,1996,0,1105,1,1954,22102,1,1,-5,21102,1,1,-2,22207,-5,-3,-1,1206,-1,2015,21101,0,0,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2037,21202,-2,1,1,21101,2037,0,0,106,0,1912,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2106,0,0 diff --git a/inputs/day_22.txt b/inputs/day_22.txt deleted file mode 100644 index b61e760..0000000 --- a/inputs/day_22.txt +++ /dev/null @@ -1,100 +0,0 @@ -deal with increment 34 -deal into new stack -cut 1712 -deal into new stack -cut 1984 -deal with increment 62 -deal into new stack -deal with increment 13 -deal into new stack -deal with increment 67 -cut -5590 -deal with increment 63 -cut -1086 -deal with increment 52 -cut 7894 -deal with increment 71 -cut -864 -deal into new stack -cut 239 -deal with increment 17 -cut -7187 -deal with increment 62 -deal into new stack -cut -7380 -deal with increment 14 -cut 3842 -deal into new stack -cut -5258 -deal with increment 40 -deal into new stack -deal with increment 45 -cut -6026 -deal with increment 21 -cut 3600 -deal with increment 56 -cut 2329 -deal into new stack -deal with increment 13 -cut -2409 -deal with increment 49 -cut 294 -deal into new stack -cut 4776 -deal with increment 17 -cut 5801 -deal with increment 43 -cut 8999 -deal with increment 46 -cut -8527 -deal with increment 4 -deal into new stack -cut -6767 -deal into new stack -deal with increment 33 -cut -532 -deal with increment 29 -deal into new stack -deal with increment 56 -cut 6867 -deal with increment 70 -cut 4276 -deal into new stack -cut -5621 -deal with increment 56 -cut -2966 -deal with increment 70 -deal into new stack -deal with increment 51 -cut -4097 -deal with increment 42 -deal into new stack -cut -5180 -deal with increment 61 -deal into new stack -cut 5367 -deal with increment 50 -cut 3191 -deal with increment 75 -cut 915 -deal with increment 72 -cut -3893 -deal with increment 22 -cut -3405 -deal with increment 30 -cut -6509 -deal with increment 31 -cut -7220 -deal with increment 45 -cut 6489 -deal with increment 70 -cut -4047 -deal into new stack -deal with increment 75 -cut 3980 -deal with increment 10 -cut 9677 -deal into new stack -deal with increment 45 -cut -6969 -deal into new stack diff --git a/inputs/day_23.txt b/inputs/day_23.txt deleted file mode 100644 index e4f8887..0000000 --- a/inputs/day_23.txt +++ /dev/null @@ -1 +0,0 @@ -3,62,1001,62,11,10,109,2215,105,1,0,1846,1780,1120,1959,571,2182,1083,631,1485,1306,1157,2153,1654,1592,1454,664,1815,951,2124,794,695,2023,1378,1248,1518,984,1887,2058,823,1019,891,1277,1685,2089,1341,1922,1186,765,1751,1413,602,922,858,1623,1217,1559,1050,1990,734,1720,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1106,0,73,3,65,20101,0,64,1,21001,66,0,2,21101,105,0,0,1105,1,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,133,1,133,68,133,101,0,0,62,1001,133,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1101,1,0,0,1001,161,1,169,101,0,65,0,1101,0,1,61,1101,0,0,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1105,1,178,21102,1,210,0,105,1,69,2101,0,1,70,1102,0,1,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1105,1,218,1105,1,73,109,4,21101,0,0,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1106,0,263,22102,1,-3,-3,109,-4,2106,0,0,109,4,21101,0,1,-3,21101,0,0,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,21202,-3,1,-3,109,-4,2106,0,0,109,1,101,1,68,358,21001,0,0,1,101,3,68,366,21001,0,0,2,21102,1,376,0,1106,0,436,22101,0,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21102,1,0,-4,21102,1,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,385,471,20102,1,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1106,0,547,21102,-1,1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1106,0,529,21201,-4,0,-7,109,-8,2106,0,0,109,1,101,1,68,564,20102,1,0,0,109,-1,2106,0,0,1102,97571,1,66,1101,1,0,67,1101,598,0,68,1101,556,0,69,1101,0,1,71,1101,0,600,72,1105,1,73,1,-1605712,28,112719,1102,1,48679,66,1102,1,1,67,1102,1,629,68,1102,556,1,69,1101,0,0,71,1102,631,1,72,1106,0,73,1,1782,1102,1,7877,66,1102,1,2,67,1101,658,0,68,1101,302,0,69,1102,1,1,71,1102,1,662,72,1105,1,73,0,0,0,0,26,81559,1101,0,22453,66,1101,1,0,67,1102,1,691,68,1101,0,556,69,1102,1,1,71,1102,1,693,72,1105,1,73,1,125,35,19959,1101,0,21493,66,1101,0,5,67,1102,1,722,68,1101,0,302,69,1102,1,1,71,1101,0,732,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,2,56893,1102,77191,1,66,1101,1,0,67,1102,1,761,68,1101,556,0,69,1101,1,0,71,1101,763,0,72,1105,1,73,1,1037327,8,179734,1101,57977,0,66,1101,0,1,67,1101,792,0,68,1102,556,1,69,1101,0,0,71,1101,0,794,72,1105,1,73,1,1430,1102,57173,1,66,1101,0,1,67,1101,0,821,68,1102,1,556,69,1101,0,0,71,1101,0,823,72,1106,0,73,1,1128,1101,0,37573,66,1102,1,3,67,1102,1,850,68,1102,253,1,69,1102,1,1,71,1101,856,0,72,1105,1,73,0,0,0,0,0,0,17,209158,1101,0,17569,66,1102,1,1,67,1101,0,885,68,1102,556,1,69,1101,2,0,71,1101,887,0,72,1106,0,73,1,8329,20,85972,34,54146,1101,84653,0,66,1101,1,0,67,1101,0,918,68,1102,1,556,69,1102,1,1,71,1101,0,920,72,1105,1,73,1,3167,20,64479,1101,0,88657,66,1102,1,1,67,1101,0,949,68,1101,556,0,69,1102,0,1,71,1102,1,951,72,1105,1,73,1,1419,1101,0,104579,66,1101,2,0,67,1101,0,978,68,1101,0,302,69,1101,0,1,71,1102,982,1,72,1105,1,73,0,0,0,0,6,76316,1102,33797,1,66,1101,0,1,67,1102,1011,1,68,1101,556,0,69,1102,1,3,71,1101,0,1013,72,1105,1,73,1,5,35,13306,35,26612,39,113194,1102,75781,1,66,1101,0,1,67,1102,1,1046,68,1102,1,556,69,1101,0,1,71,1101,1048,0,72,1106,0,73,1,1777,20,42986,1101,32183,0,66,1102,1,1,67,1102,1,1077,68,1102,556,1,69,1102,1,2,71,1102,1,1079,72,1105,1,73,1,10,35,6653,39,169791,1101,19079,0,66,1101,0,4,67,1102,1,1110,68,1102,253,1,69,1101,0,1,71,1102,1118,1,72,1105,1,73,0,0,0,0,0,0,0,0,7,7877,1102,1,56893,66,1101,0,4,67,1102,1147,1,68,1101,253,0,69,1102,1,1,71,1101,0,1155,72,1105,1,73,0,0,0,0,0,0,0,0,45,73189,1102,104651,1,66,1101,1,0,67,1102,1,1184,68,1101,556,0,69,1101,0,0,71,1101,0,1186,72,1105,1,73,1,1351,1101,0,43661,66,1101,1,0,67,1102,1213,1,68,1101,0,556,69,1102,1,1,71,1101,1215,0,72,1105,1,73,1,763676,28,75146,1101,16963,0,66,1102,1,1,67,1102,1,1244,68,1102,1,556,69,1102,1,1,71,1102,1246,1,72,1106,0,73,1,11,26,163118,1101,461,0,66,1101,1,0,67,1102,1275,1,68,1101,556,0,69,1101,0,0,71,1102,1,1277,72,1106,0,73,1,1263,1102,101483,1,66,1101,1,0,67,1102,1304,1,68,1102,556,1,69,1102,0,1,71,1102,1306,1,72,1106,0,73,1,1607,1101,0,14251,66,1101,0,3,67,1102,1333,1,68,1101,302,0,69,1102,1,1,71,1102,1,1339,72,1105,1,73,0,0,0,0,0,0,2,170679,1101,0,27073,66,1101,0,4,67,1102,1,1368,68,1102,1,302,69,1101,1,0,71,1101,0,1376,72,1106,0,73,0,0,0,0,0,0,0,0,1,154743,1101,0,15583,66,1101,0,1,67,1102,1,1405,68,1102,556,1,69,1101,0,3,71,1101,0,1407,72,1106,0,73,1,1,33,14998,21,302361,34,81219,1101,0,56597,66,1101,0,6,67,1102,1440,1,68,1102,1,302,69,1102,1,1,71,1101,1452,0,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,45,146378,1102,6991,1,66,1101,0,1,67,1102,1,1481,68,1102,1,556,69,1101,0,1,71,1102,1,1483,72,1106,0,73,1,902,21,201574,1102,1,89867,66,1101,2,0,67,1101,1512,0,68,1101,0,302,69,1101,1,0,71,1102,1516,1,72,1106,0,73,0,0,0,0,5,10798,1102,1,61553,66,1102,1,1,67,1102,1,1545,68,1102,556,1,69,1101,0,6,71,1101,0,1547,72,1106,0,73,1,2,20,21493,17,104579,7,15754,26,244677,39,282985,39,339582,1101,73189,0,66,1102,2,1,67,1101,0,1586,68,1101,0,351,69,1102,1,1,71,1101,0,1590,72,1105,1,73,0,0,0,0,255,60251,1101,0,91463,66,1102,1,1,67,1101,1619,0,68,1101,556,0,69,1102,1,1,71,1101,0,1621,72,1105,1,73,1,6467743,28,37573,1102,1,34369,66,1101,0,1,67,1101,1650,0,68,1102,556,1,69,1102,1,1,71,1101,1652,0,72,1105,1,73,1,8933,21,100787,1102,1,77081,66,1101,0,1,67,1101,1681,0,68,1102,1,556,69,1102,1,1,71,1101,1683,0,72,1105,1,73,1,2310,33,7499,1101,0,44699,66,1101,0,1,67,1102,1712,1,68,1101,556,0,69,1101,3,0,71,1101,1714,0,72,1105,1,73,1,3,8,89867,5,5399,34,108292,1101,97387,0,66,1102,1,1,67,1102,1747,1,68,1102,556,1,69,1102,1,1,71,1102,1749,1,72,1105,1,73,1,4,20,107465,1101,0,13463,66,1101,1,0,67,1101,1778,0,68,1101,0,556,69,1102,0,1,71,1102,1,1780,72,1106,0,73,1,1250,1102,51581,1,66,1102,1,3,67,1102,1807,1,68,1101,302,0,69,1101,0,1,71,1102,1,1813,72,1105,1,73,0,0,0,0,0,0,2,113786,1102,1,73679,66,1102,1,1,67,1102,1842,1,68,1102,556,1,69,1101,1,0,71,1102,1,1844,72,1105,1,73,1,160,39,56597,1101,0,60251,66,1101,0,1,67,1101,1873,0,68,1102,556,1,69,1102,6,1,71,1101,1875,0,72,1106,0,73,1,22677,47,94099,1,51581,1,103162,9,14251,9,28502,9,42753,1101,0,81559,66,1101,0,3,67,1102,1914,1,68,1101,0,302,69,1101,1,0,71,1102,1920,1,72,1105,1,73,0,0,0,0,0,0,47,188198,1101,0,6653,66,1101,4,0,67,1102,1949,1,68,1101,302,0,69,1101,0,1,71,1101,0,1957,72,1106,0,73,0,0,0,0,0,0,0,0,39,226388,1101,63659,0,66,1101,0,1,67,1101,0,1986,68,1102,556,1,69,1102,1,1,71,1102,1,1988,72,1105,1,73,1,-2,34,27073,1101,94099,0,66,1101,2,0,67,1101,0,2017,68,1101,0,302,69,1102,1,1,71,1102,2021,1,72,1106,0,73,0,0,0,0,2,227572,1101,100787,0,66,1101,0,3,67,1101,2050,0,68,1102,1,302,69,1101,1,0,71,1101,0,2056,72,1105,1,73,0,0,0,0,0,0,6,19079,1101,0,47599,66,1102,1,1,67,1101,0,2085,68,1102,556,1,69,1102,1,1,71,1101,2087,0,72,1105,1,73,1,2677,33,22497,1102,1,7499,66,1101,0,3,67,1101,2116,0,68,1102,1,302,69,1101,0,1,71,1101,0,2122,72,1105,1,73,0,0,0,0,0,0,6,38158,1101,0,101359,66,1102,1,1,67,1101,2151,0,68,1102,1,556,69,1102,1,0,71,1102,1,2153,72,1105,1,73,1,1752,1101,48091,0,66,1101,1,0,67,1102,1,2180,68,1101,0,556,69,1101,0,0,71,1101,0,2182,72,1106,0,73,1,1463,1102,5399,1,66,1101,0,2,67,1102,1,2209,68,1101,0,302,69,1102,1,1,71,1101,0,2213,72,1106,0,73,0,0,0,0,6,57237 diff --git a/inputs/day_24.txt b/inputs/day_24.txt deleted file mode 100644 index ba900ad..0000000 --- a/inputs/day_24.txt +++ /dev/null @@ -1,5 +0,0 @@ -##.#. -.##.. -##.#. -.#### -###.. diff --git a/inputs/day_25.txt b/inputs/day_25.txt deleted file mode 100644 index 5351575..0000000 --- a/inputs/day_25.txt +++ /dev/null @@ -1 +0,0 @@ -109,4795,21102,1,3124,1,21102,1,13,0,1106,0,1424,21102,1,166,1,21101,24,0,0,1105,1,1234,21102,31,1,0,1106,0,1984,1106,0,13,6,4,3,2,52,51,21,4,28,56,55,3,19,-9,-10,47,89,88,90,90,6,77,73,85,71,1,76,68,63,65,22,-27,70,76,81,87,5,105,105,107,108,95,4,97,92,109,109,5,110,105,110,108,95,4,115,96,109,109,13,-3,59,101,85,92,97,13,84,80,92,78,34,-15,26,-16,46,88,72,79,84,0,72,76,-3,85,74,79,75,-8,64,68,75,57,65,70,64,66,72,8,-41,32,-22,56,77,82,-4,60,76,62,70,-2,74,-11,55,52,68,67,73,56,60,52,-20,44,56,66,-24,48,58,42,49,54,-16,-53,10,0,56,99,96,95,82,94,83,45,-9,23,-13,61,85,88,74,71,82,73,79,73,89,67,65,-4,62,73,70,69,56,68,57,2,-35,24,-14,64,85,90,4,70,67,79,7,83,-2,68,75,-5,78,65,57,75,-10,76,53,76,0,-37,31,-21,57,78,83,-3,64,74,72,0,76,-9,73,58,57,-13,70,57,49,67,-18,54,64,48,55,-23,48,44,56,42,-14,-51,14,-4,74,95,100,14,97,77,86,79,9,92,79,75,5,27,-17,61,82,87,1,68,78,76,4,80,-5,66,58,78,60,-10,73,60,52,70,-15,57,67,51,58,-6,-43,14,-4,74,95,100,14,81,94,90,90,9,92,79,75,5,60,-50,23,42,38,-32,38,39,30,42,47,-38,30,36,28,25,41,38,34,31,18,23,29,19,33,-52,20,29,-55,27,27,27,8,15,-61,22,16,-64,24,13,18,-54,-69,-70,-14,7,12,-74,-8,-11,1,-71,5,-80,-4,-3,3,-15,-84,-85,-109,29,-19,59,80,85,-1,82,62,71,64,-6,77,64,60,-10,62,66,57,59,63,57,67,51,-19,56,58,57,57,-10,-47,44,-34,39,58,54,-16,60,61,57,64,48,56,-23,52,40,60,38,-28,44,53,-31,55,32,55,-35,48,42,41,-39,32,38,42,-42,-44,12,33,38,-48,28,19,25,32,-52,-76,-77,59,-49,13,55,-30,42,51,-33,49,50,32,31,31,39,36,48,-42,24,35,32,34,29,21,35,19,25,37,-53,14,10,26,18,-57,-59,-3,18,23,-63,1,17,3,-67,1,-4,14,-2,6,-73,-8,14,-76,-12,-78,-40,2,4,-13,-82,-106,-107,35,-25,53,74,79,0,74,60,-10,65,53,72,64,52,56,52,50,-19,53,57,62,56,-24,58,54,38,39,40,-29,-31,2,56,35,-34,-58,-59,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-94,-98,-103,-83,-97,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-90,-94,-97,-97,-86,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,263,-253,-199,-233,-158,-156,-151,-169,-226,-239,-158,-162,-176,-164,-160,-172,-179,-247,-162,-170,-177,-184,-183,-253,-171,-190,-167,-174,-258,-257,-227,-183,-197,-187,-175,-182,-193,-184,-268,-202,-191,-194,-192,-197,-205,-191,-207,-276,-278,-222,-201,-196,-282,-206,-219,-196,-286,-207,-206,-210,-223,-222,-223,-225,-280,-293,-296,-232,-220,-231,-300,-212,-223,-218,-304,-236,-228,-223,-239,-227,-310,-227,-240,-244,-314,-248,-237,-250,-243,-239,-247,-237,-308,-345,-273,-260,-248,-243,-263,-329,-252,-252,-248,-260,-267,-266,-253,-337,-249,-260,-255,-259,-342,-260,-267,-280,-270,-271,-348,-281,-268,-272,-279,-285,-342,-355,-280,-278,-279,-284,-277,-361,-282,-278,-274,-275,-290,-298,-300,-369,-300,-292,-290,-373,-309,-375,-299,-298,-301,-310,-302,-297,-370,-383,-302,-316,-321,-311,-315,-299,-321,-308,-392,-306,-322,-330,-312,-397,-326,-334,-317,-401,-330,-338,-324,-325,-337,-329,-339,-341,-398,-411,-347,-335,-346,-415,-334,-352,-350,-346,-341,-338,-422,-334,-345,-340,-344,-427,-345,-357,-357,-351,-432,-365,-361,-353,-367,-370,-354,-363,-351,-427,-464,-441,-397,-373,-434,-447,-376,-380,-374,-375,-373,-452,-454,-398,-377,-372,-458,-376,-388,-382,-377,-387,-396,-465,-400,-398,-468,-404,-404,-395,-403,-473,-390,-396,-476,-406,-409,-395,-480,-408,-404,-483,-418,-396,-486,-403,-399,-409,-417,-413,-421,-493,37,-5,73,71,-8,75,62,58,-12,62,55,74,64,48,50,-19,45,63,-22,61,48,44,-26,50,37,44,48,-31,33,40,48,41,43,30,37,-25,-38,-63,0,0,109,7,21101,0,0,-2,22208,-2,-5,-1,1205,-1,1169,22202,-2,-4,1,22201,1,-6,1,21202,-2,1,2,21102,1162,1,0,2105,1,-3,21201,-2,1,-2,1106,0,1136,109,-7,2106,0,0,109,6,2101,0,-5,1182,20101,0,0,-2,21102,0,1,-3,21201,-5,1,-5,22208,-3,-2,-1,1205,-1,1229,2201,-5,-3,1205,20101,0,0,1,22102,1,-3,2,21202,-2,1,3,21102,1,1222,0,2105,1,-4,21201,-3,1,-3,1105,1,1192,109,-6,2106,0,0,109,2,21202,-1,1,1,21101,1256,0,2,21102,1251,1,0,1106,0,1174,109,-2,2105,1,0,109,5,22201,-4,-3,-1,22201,-2,-1,-1,204,-1,109,-5,2106,0,0,109,3,1202,-2,1,1280,1006,0,1303,104,45,104,32,1201,-1,66,1291,21002,0,1,1,21101,1301,0,0,1105,1,1234,104,10,109,-3,2105,1,0,0,0,109,2,2101,0,-1,1309,1102,1,0,1308,21102,1,4601,1,21102,13,1,2,21101,4,0,3,21102,1,1353,4,21101,1343,0,0,1105,1,1130,20102,1,1308,-1,109,-2,2106,0,0,63,109,3,1201,-2,0,1360,20008,0,1309,-1,1206,-1,1419,1005,1308,1398,1102,1,1,1308,21008,1309,-1,-1,1206,-1,1387,21102,106,1,1,1106,0,1391,21101,0,92,1,21102,1,1398,0,1106,0,1234,104,45,104,32,1201,-2,1,1407,21002,0,1,1,21102,1417,1,0,1105,1,1234,104,10,109,-3,2105,1,0,109,3,1202,-2,1,1128,21102,1,34,1,21101,0,1441,0,1106,0,1234,1001,1128,0,1447,20101,0,0,1,21102,1,1456,0,1105,1,1234,21102,1,41,1,21101,1467,0,0,1105,1,1234,1001,1128,1,1472,21002,0,1,1,21101,1482,0,0,1105,1,1234,21102,46,1,1,21102,1493,1,0,1105,1,1234,21001,1128,3,1,21102,4,1,2,21102,1,1,3,21102,1,1273,4,21101,1516,0,0,1106,0,1130,21001,1128,0,1,21102,1,1527,0,1105,1,1310,1001,1128,2,1532,21002,0,1,-1,1206,-1,1545,21101,0,1545,0,2105,1,-1,109,-3,2106,0,0,109,0,99,109,2,1102,1,0,1550,21101,0,4601,1,21102,13,1,2,21101,4,0,3,21101,1664,0,4,21102,1,1582,0,1105,1,1130,2,2486,1352,1551,1102,0,1,1552,21001,1550,0,1,21102,1,33,2,21101,0,1702,3,21102,1,1609,0,1106,0,2722,21007,1552,0,-1,1205,-1,1630,20107,0,1552,-1,1205,-1,1637,21102,1,1630,0,1106,0,1752,21101,0,548,1,1106,0,1641,21101,687,0,1,21101,0,1648,0,1105,1,1234,21101,0,4457,1,21101,1659,0,0,1106,0,1424,109,-2,2105,1,0,109,4,21202,-2,-1,-2,2102,1,-3,1675,21008,0,-1,-1,1206,-1,1697,1201,-3,2,1687,20101,-27,0,-3,22201,-3,-2,-3,2001,1550,-3,1550,109,-4,2105,1,0,109,5,21008,1552,0,-1,1206,-1,1747,1201,-3,1901,1717,20101,0,0,-2,1205,-4,1736,20207,-2,1551,-1,1205,-1,1747,1102,-1,1,1552,1105,1,1747,22007,1551,-2,-1,1205,-1,1747,1102,1,1,1552,109,-5,2105,1,0,109,1,21101,826,0,1,21102,1765,1,0,1105,1,1234,21002,1550,1,1,21102,1776,1,0,1105,1,2863,21102,1090,1,1,21102,1787,1,0,1106,0,1234,99,1106,0,1787,109,-1,2106,0,0,109,1,21101,512,0,1,21101,0,1809,0,1106,0,1234,99,1105,1,1809,109,-1,2105,1,0,109,1,1102,1,1,1129,109,-1,2106,0,0,109,1,21102,1,377,1,21101,0,1842,0,1105,1,1234,1106,0,1831,109,-1,2106,0,0,109,1,21101,407,0,1,21101,1863,0,0,1105,1,1234,99,1106,0,1863,109,-1,2106,0,0,109,1,21102,1,452,1,21101,1885,0,0,1106,0,1234,99,1106,0,1885,109,-1,2105,1,0,1941,1947,1953,1958,1965,1972,1978,4083,3936,4362,4458,4463,4254,3769,4145,4116,3848,4384,3957,4371,4258,3951,4063,3935,4053,4163,4259,3817,4062,4500,3970,4331,4022,3969,4163,4483,4089,3810,4092,4196,2281,2468,2418,2450,2487,2125,2505,5,95,108,104,104,23,5,96,91,108,108,1,4,101,105,112,3,6,104,104,106,107,94,-1,6,109,104,109,107,94,-1,5,111,91,100,93,23,5,114,95,108,108,1,109,3,21102,1993,1,0,1106,0,2634,1006,1129,2010,21101,0,316,1,21101,0,2007,0,1106,0,1234,1106,0,2076,21101,0,0,-1,1201,-1,1894,2019,21001,0,0,1,21102,0,1,2,21102,1,0,3,21101,0,2037,0,1106,0,2525,1206,1,2054,1201,-1,1934,2050,21102,2051,1,0,106,0,0,1105,1,2076,21201,-1,1,-1,21207,-1,7,-2,1205,-2,2014,21101,0,177,1,21102,1,2076,0,1105,1,1234,109,-3,2105,1,0,109,3,2001,1128,-2,2088,21002,0,1,-1,1205,-1,2108,21101,201,0,1,21101,2105,0,0,1105,1,1234,1106,0,2119,22101,0,-1,1,21101,2119,0,0,1106,0,1424,109,-3,2105,1,0,0,109,1,1101,0,0,2124,21101,0,4601,1,21101,0,13,2,21101,0,4,3,21102,2173,1,4,21102,2154,1,0,1106,0,1130,1005,2124,2168,21102,226,1,1,21102,2168,1,0,1106,0,1234,109,-1,2106,0,0,109,3,1005,2124,2275,1201,-2,0,2183,20008,0,1128,-1,1206,-1,2275,1201,-2,1,2195,20102,1,0,-1,21202,-1,1,1,21102,5,1,2,21102,1,1,3,21102,2216,1,0,1106,0,2525,1206,1,2275,21102,1,258,1,21101,2230,0,0,1105,1,1234,21202,-1,1,1,21101,0,2241,0,1106,0,1234,104,46,104,10,1101,1,0,2124,1201,-2,0,2256,1101,0,-1,0,1201,-2,3,2262,21002,0,1,-1,1206,-1,2275,21101,2275,0,0,2105,1,-1,109,-3,2106,0,0,0,109,1,1101,0,0,2280,21101,4601,0,1,21101,0,13,2,21102,1,4,3,21102,1,2329,4,21102,1,2310,0,1106,0,1130,1005,2280,2324,21102,1,273,1,21102,1,2324,0,1105,1,1234,109,-1,2105,1,0,109,3,1005,2280,2413,1201,-2,0,2339,21008,0,-1,-1,1206,-1,2413,1201,-2,1,2351,20102,1,0,-1,22101,0,-1,1,21102,5,1,2,21101,1,0,3,21102,2372,1,0,1105,1,2525,1206,1,2413,21102,301,1,1,21102,2386,1,0,1106,0,1234,22102,1,-1,1,21102,2397,1,0,1106,0,1234,104,46,104,10,1102,1,1,2280,1201,-2,0,2412,101,0,1128,0,109,-3,2106,0,0,109,1,21101,0,-1,1,21102,1,2431,0,1105,1,1310,1205,1,2445,21102,1,133,1,21101,0,2445,0,1106,0,1234,109,-1,2106,0,0,109,1,21102,3,1,1,21101,2463,0,0,1106,0,2081,109,-1,2106,0,0,109,1,21101,4,0,1,21102,1,2481,0,1105,1,2081,109,-1,2106,0,0,70,109,1,21102,5,1,1,21102,2500,1,0,1105,1,2081,109,-1,2105,1,0,109,1,21102,6,1,1,21102,2518,1,0,1105,1,2081,109,-1,2106,0,0,0,0,109,5,2102,1,-3,2523,1101,0,1,2524,21202,-4,1,1,21101,0,2585,2,21101,2550,0,0,1105,1,1174,1206,-2,2576,2101,0,-4,2558,2001,0,-3,2566,101,3094,2566,2566,21008,0,-1,-1,1205,-1,2576,1102,0,1,2524,21001,2524,0,-4,109,-5,2105,1,0,109,5,22201,-4,-3,-4,22201,-4,-2,-4,21208,-4,10,-1,1206,-1,2606,21102,-1,1,-4,201,-3,2523,2615,1001,2615,3094,2615,21002,0,1,-1,22208,-4,-1,-1,1205,-1,2629,1101,0,0,2524,109,-5,2106,0,0,109,4,21101,0,3094,1,21102,30,1,2,21101,1,0,3,21102,1,2706,4,21102,1,2659,0,1105,1,1130,21101,0,0,-3,203,-2,21208,-2,10,-1,1205,-1,2701,21207,-2,0,-1,1205,-1,2663,21207,-3,29,-1,1206,-1,2663,2101,3094,-3,2693,2102,1,-2,0,21201,-3,1,-3,1106,0,2663,109,-4,2105,1,0,109,2,1201,-1,0,2715,1102,-1,1,0,109,-2,2105,1,0,0,109,5,2102,1,-2,2721,21207,-4,0,-1,1206,-1,2739,21102,1,0,-4,21202,-4,1,1,21202,-3,1,2,21102,1,1,3,21101,0,2758,0,1105,1,2763,109,-5,2106,0,0,109,6,21207,-4,1,-1,1206,-1,2786,22207,-5,-3,-1,1206,-1,2786,21201,-5,0,-5,1105,1,2858,22101,0,-5,1,21201,-4,-1,2,21202,-3,2,3,21101,0,2805,0,1105,1,2763,21202,1,1,-5,21101,0,1,-2,22207,-5,-3,-1,1206,-1,2824,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2850,22102,1,-2,1,21201,-4,-1,2,21101,0,2850,0,105,1,2721,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2105,1,0,109,3,21208,-2,0,-1,1205,-1,2902,21207,-2,0,-1,1205,-1,2882,1105,1,2888,104,45,21202,-2,-1,-2,21201,-2,0,1,21102,2899,1,0,1106,0,2909,1106,0,2904,104,48,109,-3,2106,0,0,109,4,22102,1,-3,1,21101,10,0,2,21101,0,2926,0,1105,1,3010,21201,1,0,-2,21201,2,0,-1,1206,-2,2948,22101,0,-2,1,21101,0,2948,0,1106,0,2909,22101,48,-1,-1,204,-1,109,-4,2105,1,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21101,0,0,-4,21101,0,0,-3,21102,1,51,-2,21201,-2,-1,-2,1201,-2,2959,3034,20101,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,3059,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,3078,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,3024,21202,-4,1,-7,21202,-3,1,-6,109,-8,2106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3131,3143,0,3252,3527,0,0,11,61,105,95,94,17,50,97,83,78,79,83,108,-19,2,7,-79,-9,-2,2,-83,-11,-7,-86,-3,-16,-7,-11,-6,-21,-21,-94,-30,-96,-25,-19,-23,-31,-101,-29,-25,-104,-21,-34,-38,-108,-39,-34,-32,-33,-31,-114,-43,-47,-35,-49,-105,-120,-69,-43,-123,-49,-56,-57,-47,-128,-40,-51,-46,-50,-133,-51,-63,-63,-57,-138,-69,-58,-62,-65,-143,-79,-69,-63,-68,-148,-79,-68,-82,-83,-63,-81,-77,-85,-145,-158,-75,-88,-92,-162,-91,-85,-89,-97,-167,-96,-104,-87,-171,-106,-104,-105,-97,-176,-94,-109,-114,-104,-112,-114,-169,3259,3267,0,3344,0,3124,0,7,65,89,99,98,108,85,108,76,8,27,27,36,-48,16,32,18,13,-53,18,10,27,-57,8,10,9,17,-62,16,16,19,7,10,5,21,-1,-3,-72,-3,5,7,-76,6,1,-2,-11,3,-10,-10,-6,-14,-59,-87,1,-10,-5,-84,-10,-24,-94,-21,-11,-14,-14,-99,-22,-22,-18,-103,-23,-20,-33,-23,-39,-109,-27,-26,-30,-44,-114,-28,-44,-52,-34,-105,3351,3359,0,0,3408,3252,0,7,76,108,102,104,86,91,88,48,36,55,51,-19,46,58,66,46,59,-25,48,58,55,55,-30,36,47,45,50,30,37,41,-38,38,39,41,27,-43,22,34,42,22,35,-35,-50,-51,-2,16,13,30,26,26,15,27,9,15,27,-49,3415,3423,0,0,3458,4392,3344,7,76,108,88,88,97,89,102,34,48,66,69,73,62,62,61,73,3,72,61,77,55,53,-2,-17,34,53,49,68,-15,59,45,-25,39,49,48,-29,39,46,48,51,55,-21,3465,3486,0,3584,0,4053,3408,20,51,84,80,93,8,62,88,70,84,83,75,79,71,-1,33,66,74,79,63,75,40,32,70,77,-11,57,63,69,54,-16,51,61,-19,69,58,63,-23,63,57,39,53,-28,51,52,38,51,36,44,49,47,-37,41,39,-40,43,30,26,-44,26,33,-16,3534,3548,0,0,0,0,3124,13,54,100,86,103,15,63,98,77,93,94,78,90,90,35,49,68,64,-6,59,61,59,73,-11,53,69,55,-15,49,59,58,-19,64,58,57,-23,59,52,39,49,48,-29,40,48,50,-33,55,44,49,-23,3591,3600,0,0,3732,3458,3673,8,75,96,89,96,20,53,83,106,72,11,44,38,37,35,37,38,36,-48,17,29,33,20,-53,-4,14,12,-44,-12,20,23,8,6,-63,-14,4,7,11,0,0,-1,11,-72,4,-5,-7,-3,-10,-5,-1,-11,-81,-17,-5,-16,-85,-4,-18,-17,-4,-14,-26,-10,-93,-12,-26,-23,-19,-30,-30,-31,-19,-102,-26,-35,-37,-33,-40,-35,-31,-41,-97,3680,3703,0,3901,3584,0,4241,22,50,88,92,7,41,77,83,70,81,77,65,83,67,-3,34,74,79,71,76,56,63,67,28,55,82,79,70,72,78,85,9,-4,68,78,0,75,-9,73,73,61,63,62,-15,71,62,64,56,53,57,49,-9,3739,3748,0,3828,0,3981,3584,8,59,102,104,103,93,87,97,99,79,5,24,20,-50,26,17,31,11,21,-56,30,7,17,16,22,-62,2,14,3,-66,17,4,0,-70,6,-3,11,-9,1,-76,-7,-2,0,-1,1,-82,-18,-2,-16,-86,-4,-12,-16,-19,-19,-8,-17,-5,-95,-28,-24,-28,-29,-31,-19,-33,-25,-20,-105,-39,-28,-32,-30,-28,-28,-98,-113,-67,-33,-116,-52,-36,-50,-120,-37,-50,-54,-35,-94,3835,3844,0,4166,0,3732,0,8,64,102,98,100,88,88,85,92,56,27,54,51,42,51,49,39,-31,51,36,35,42,47,-37,46,40,-40,31,23,43,25,-45,30,22,22,35,-50,22,32,-53,25,23,-56,27,14,10,-60,-22,11,2,14,19,-66,-28,14,4,-2,-71,11,-4,10,9,-3,1,-7,-65,3908,3920,0,0,0,3673,0,11,68,86,102,87,99,102,80,98,92,94,100,60,24,43,39,51,37,-33,31,47,33,-37,27,-39,30,28,45,-43,40,24,30,22,35,18,29,29,17,30,-27,-55,28,15,11,30,-53,21,7,-63,1,11,10,-67,-2,10,6,13,-3,-5,-74,-7,3,10,0,-67,-80,3,-10,-4,1,-14,-14,-73,3988,3997,0,3732,4095,0,0,8,72,88,105,104,85,90,87,100,55,29,48,44,63,-20,54,40,-30,34,-32,43,39,49,48,39,31,-39,44,46,31,40,40,44,-46,18,30,19,-50,32,32,12,28,29,17,21,13,-59,24,18,-62,13,15,14,9,-67,-3,7,6,-71,-7,3,-1,0,-7,-63,4060,4068,0,3458,0,0,0,7,68,97,107,89,93,89,97,26,43,91,73,85,91,85,72,72,76,68,3,78,-6,63,74,60,59,79,57,0,54,67,57,52,50,-5,4102,4114,0,0,0,4337,3981,11,58,98,90,91,95,85,84,96,86,90,82,51,38,59,64,-22,60,45,44,-26,38,-28,58,42,42,52,36,32,44,29,45,30,-39,47,32,42,29,-44,35,30,18,30,34,-50,19,27,29,-54,-4,24,25,15,19,11,7,20,16,9,3,-66,19,-50,-55,4173,4185,0,0,0,3828,0,11,72,87,92,87,95,83,84,14,57,77,77,55,34,55,60,-26,56,41,40,-30,38,54,40,34,34,42,30,31,-39,32,28,40,26,-44,34,24,-47,32,33,29,33,27,31,35,25,13,-57,22,20,16,28,15,6,18,-65,2,2,15,4,1,7,-72,14,5,7,-1,-63,4248,4259,0,0,3673,0,0,10,68,86,106,92,89,82,100,88,93,91,77,6,38,18,36,36,33,-25,-52,-2,30,27,9,21,10,10,8,-47,-62,-15,12,4,-1,16,1,-69,13,14,8,7,2,14,-76,0,-9,-14,3,4,0,-14,-7,-16,-8,-3,-5,-89,-20,-9,-13,-16,-94,-25,-23,-27,-14,-10,-100,-18,-18,-38,-22,-22,-106,-23,-29,-109,-28,-42,-45,-48,-38,-42,-50,-35,-53,-35,-51,-107,4344,4351,0,4095,0,0,0,6,59,107,91,88,90,90,40,38,70,68,58,-12,66,56,-15,68,55,51,-19,47,44,44,50,54,44,58,56,-28,54,39,38,45,-33,50,44,-36,35,27,47,29,-41,38,36,43,24,36,-33,4399,4422,0,3408,0,4457,0,22,65,74,90,87,6,41,86,76,88,70,0,44,63,70,74,79,63,71,57,69,57,58,34,39,81,-4,60,74,73,61,56,72,72,-12,71,65,-15,50,52,-18,68,59,61,53,50,54,46,-26,51,51,53,47,34,44,43,55,-21,4464,4484,0,4392,4556,0,0,19,64,81,78,95,91,81,91,95,5,39,75,71,68,75,79,77,70,74,79,71,2,38,-41,42,29,25,-45,32,22,40,35,-50,31,27,26,23,-43,-56,8,-58,21,22,8,21,20,21,17,3,-54,15,0,8,12,1,11,-1,11,-7,-77,-8,-3,-1,-2,0,-83,3,-12,-10,-11,-88,-3,-21,-9,-19,-23,-5,-95,-7,-18,-13,-17,-100,-28,-34,-34,-26,-21,-33,-23,-19,-95,4563,4588,1553,0,0,0,4457,24,56,89,75,88,87,88,84,70,13,50,67,75,79,68,78,66,78,60,-10,27,64,66,65,67,12,53,97,83,93,105,105,87,91,83,25,24,23,3981,4653,16777243,0,3344,4659,32796,0,4166,4672,67108893,0,3252,4683,46,0,3673,4699,31,1818,3527,4719,536870944,0,3408,4727,268435489,0,3584,4741,34,1829,3828,4755,35,1850,4241,4767,36,1796,4053,4778,1061,0,4337,4782,38,1872,3901,4790,41,0,5,110,98,94,100,99,12,95,95,87,90,94,15,80,92,96,95,86,78,10,106,86,97,85,97,102,98,88,92,82,15,104,85,80,98,85,81,93,10,86,73,74,78,78,82,72,19,84,85,76,88,93,8,76,82,74,71,87,84,80,77,64,69,75,65,79,7,90,102,107,91,99,98,84,13,102,98,96,95,91,14,92,82,11,77,74,92,29,13,92,96,87,89,93,87,97,81,11,86,88,87,87,11,98,99,95,102,86,94,15,90,78,98,76,10,91,104,87,84,98,86,16,95,93,81,3,106,113,98,7,105,96,102,106,100,98,102,4,95,92,101,94 diff --git a/inputs/day_3.txt b/inputs/day_3.txt deleted file mode 100644 index 504e9fe..0000000 --- a/inputs/day_3.txt +++ /dev/null @@ -1,2 +0,0 @@ -R995,D882,R144,U180,L638,U282,L907,D326,R731,D117,R323,U529,R330,U252,R73,U173,R345,U552,R230,U682,R861,U640,L930,U590,L851,D249,R669,D878,R951,D545,L690,U392,R609,D841,R273,D465,R546,U858,L518,U567,L474,D249,L463,D390,L443,U392,L196,U418,R433,U651,R520,D450,R763,U714,R495,D716,L219,D289,L451,D594,R874,U451,R406,U662,R261,D242,R821,D951,R808,D862,L871,U133,R841,D465,R710,U300,R879,D497,R85,U173,R941,U953,R705,U972,R260,D315,L632,U182,L26,D586,R438,U275,L588,U956,L550,D576,R738,U974,R648,D880,R595,D510,L789,U455,R627,U709,R7,D486,L184,U999,L404,U329,L852,D154,L232,U398,L587,U881,R938,D40,L657,D164,R45,D917,R106,U698,L824,D426,R879,U700,R847,D891,L948,U625,R663,D814,R217,U30,R610,D781,L415,D435,L904,U815,R152,U587,R287,U141,R866,D636,L290,D114,L751,D660,R6,U383,L263,U799,R330,U96,L6,U542,L449,D361,R486,U278,L990,U329,L519,U605,R501,D559,R916,U198,L499,D174,R513,U396,L473,D565,R337,D770,R211,D10,L591,D920,R367,D748,L330,U249,L307,D645,R661,U266,R234,D403,L513,U443,L989,D1,L674,D210,L537,D872,L607,D961,R894,U632,L195,U744,L426,U531,R337,D821,R113,U436,L700,U779,R555,U891,R268,D30,R958,U411,R904,U24,R760,D958,R231,U229,L561,D134,L382,D961,L237,U676,L223,U324,R663,D186,R833,U188,R419,D349,L721,U152,L912,U490,R10,D995,L98,U47,R140,D815,R826,U730,R808,U256,R479,D322,L504,D891,L413,D848,L732,U375,L307,U7,R682,U270,L495,D248,R691,D945,L70,U220,R635,D159,R269,D15,L161,U214,R814,D3,R354,D632,R469,D36,R85,U215,L243,D183,R140,U179,R812,U180,L905,U136,L34,D937,L875 -L999,D22,L292,U843,R390,U678,R688,D492,L489,U488,R305,U951,L636,U725,R402,U84,L676,U171,L874,D201,R64,D743,R372,U519,R221,U986,L393,D793,R72,D184,L553,D137,L187,U487,L757,U880,L535,U887,R481,U236,L382,D195,L388,D90,R125,U414,R512,D382,R972,U935,L172,D1,R957,U593,L151,D158,R396,D42,L30,D178,R947,U977,R67,D406,R744,D64,L677,U23,R792,U864,R259,U315,R314,U17,L37,D658,L642,U135,R624,U601,L417,D949,R203,D122,R76,D493,L569,U274,L330,U933,R815,D30,L630,D43,R86,U926,L661,D491,L541,D96,R868,D565,R664,D935,L336,D152,R63,U110,L782,U14,R172,D945,L732,D870,R404,U767,L907,D558,R748,U591,R461,D153,L635,D457,R241,U478,L237,U218,R393,U468,L182,D745,L388,D360,L222,D642,L151,U560,R437,D326,R852,U525,R717,U929,L470,U621,R421,U408,L540,D176,L69,U753,L200,U251,R742,U628,R534,U542,R85,D71,R283,U905,L418,D755,L593,U335,L114,D684,L576,D645,R652,D49,R86,D991,L838,D309,L73,U847,L418,U675,R991,U463,R314,D618,L433,U173,R869,D115,L18,U233,R541,U516,L570,U340,R264,D442,L259,U276,R433,D348,R524,D353,R336,D883,R580,U157,R79,D27,L134,D161,L748,D278,R322,D581,R654,D156,L930,D293,L156,U311,R807,D618,R408,U719,R366,D632,R307,D565,R478,D620,R988,D821,R365,D581,L946,D138,L943,U69,R620,U208,L407,U188,L122,U353,L751,U565,R849,D874,R668,D794,L140,D474,R289,D773,R344,D220,L55,D385,L394,U208,R305,U736,L896,D376,R331,D855,L466,U516,L741,U124,L825,U467,L525,D911,R76,U220,L610,U102,L261,D891,L585,U397,L152,U753,R822,D252,R106,U145,L7,U524,R343,U352,L357,D399,L446,D140,L723,U46,R687,D409,R884 diff --git a/inputs/day_4.txt b/inputs/day_4.txt deleted file mode 100644 index f62320b..0000000 --- a/inputs/day_4.txt +++ /dev/null @@ -1,2 +0,0 @@ -138241 -674034 diff --git a/inputs/day_5.txt b/inputs/day_5.txt deleted file mode 100644 index f8c2724..0000000 --- a/inputs/day_5.txt +++ /dev/null @@ -1 +0,0 @@ -3,225,1,225,6,6,1100,1,238,225,104,0,1102,57,23,224,101,-1311,224,224,4,224,1002,223,8,223,101,6,224,224,1,223,224,223,1102,57,67,225,102,67,150,224,1001,224,-2613,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,2,179,213,224,1001,224,-469,224,4,224,102,8,223,223,101,7,224,224,1,223,224,223,1001,188,27,224,101,-119,224,224,4,224,1002,223,8,223,1001,224,7,224,1,223,224,223,1,184,218,224,1001,224,-155,224,4,224,1002,223,8,223,1001,224,7,224,1,224,223,223,1101,21,80,224,1001,224,-101,224,4,224,102,8,223,223,1001,224,1,224,1,224,223,223,1101,67,39,225,1101,89,68,225,101,69,35,224,1001,224,-126,224,4,224,1002,223,8,223,1001,224,1,224,1,224,223,223,1102,7,52,225,1102,18,90,225,1101,65,92,225,1002,153,78,224,101,-6942,224,224,4,224,102,8,223,223,101,6,224,224,1,223,224,223,1101,67,83,225,1102,31,65,225,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1007,226,226,224,102,2,223,223,1005,224,329,1001,223,1,223,108,677,226,224,1002,223,2,223,1005,224,344,1001,223,1,223,1007,677,677,224,1002,223,2,223,1005,224,359,1001,223,1,223,1107,677,226,224,102,2,223,223,1006,224,374,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,389,101,1,223,223,8,677,677,224,102,2,223,223,1006,224,404,1001,223,1,223,1008,226,226,224,102,2,223,223,1006,224,419,1001,223,1,223,107,677,226,224,102,2,223,223,1006,224,434,101,1,223,223,7,226,226,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,226,226,224,1002,223,2,223,1006,224,464,1001,223,1,223,1107,226,677,224,1002,223,2,223,1005,224,479,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,494,1001,223,1,223,1108,226,677,224,1002,223,2,223,1006,224,509,101,1,223,223,1008,677,677,224,1002,223,2,223,1006,224,524,1001,223,1,223,1008,677,226,224,102,2,223,223,1006,224,539,1001,223,1,223,1108,677,677,224,102,2,223,223,1005,224,554,101,1,223,223,108,677,677,224,102,2,223,223,1006,224,569,101,1,223,223,1108,677,226,224,102,2,223,223,1005,224,584,1001,223,1,223,108,226,226,224,1002,223,2,223,1005,224,599,1001,223,1,223,1007,226,677,224,102,2,223,223,1005,224,614,1001,223,1,223,7,226,677,224,102,2,223,223,1006,224,629,1001,223,1,223,107,226,226,224,102,2,223,223,1005,224,644,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,659,101,1,223,223,107,677,677,224,1002,223,2,223,1005,224,674,1001,223,1,223,4,223,99,226 diff --git a/inputs/day_6.txt b/inputs/day_6.txt deleted file mode 100644 index 49d849c..0000000 --- a/inputs/day_6.txt +++ /dev/null @@ -1,2306 +0,0 @@ -21X)BWV -YZJ)YLQ -FQS)PZW -R64)71F -ZH4)QVZ -LWB)H4Q -4HQ)PVJ -TZ5)VBV -LF1)FKZ -GKS)BGN -45B)2NS -14W)2JY -1XY)FJ8 -ZRC)WR9 -GCL)6PB -LP4)GQ8 -26V)HTK -3M8)1GJ -47Q)JYK -WDB)N2R -KH8)TGY -LFX)N2X -VSZ)7PC -M6W)4WL -HH9)8PC -L59)8Y8 -Q49)LWH -CJ5)XDG -K51)FGH -H31)2RJ -39M)Y4M -12C)VLF -PZW)7DW -MP2)19Q -R76)CHH -N6J)KBW -WR9)W25 -T99)ZF1 -1TS)8SM -8WW)YX7 -PW6)B2J -7KX)YM5 -HM6)GVX -DNB)2YP -6WC)2LW -BG5)SB6 -KK1)JTF -YDT)244 -GGQ)2DJ -GCP)Q8H -S1Y)J69 -LBV)DYG -ZKN)JBS -8XY)Y8Z -XMH)NHD -XVM)2LX -SYP)BC8 -PXH)YYG -F29)G9Y -BYX)4QS -8MY)S1D -N2Y)BZK -FRC)72W -S2K)YH5 -7JF)K65 -DJ9)K4L -P26)WXT -DW9)1DJ -NP4)3SB -XS7)CDL -6XH)4ZT -2DJ)GCP -2K4)VV1 -Q6P)NNN -HQW)ZR9 -9G2)FNB -H9N)5ZJ -13Z)GKD -9MW)37Y -VDY)BG9 -BL3)12C -LNN)JST -Z3V)T39 -XS3)WYG -8J5)QFQ -7DW)DXY -JMV)DM4 -VL3)V7Q -GZC)ZHV -3N6)R2H -FQ6)7LG -SR9)D66 -1M8)K2L -24N)M94 -JST)WM9 -7SB)99Q -58J)YN7 -WWH)5KS -C39)X9J -58S)KBP -TVF)VNG -TKC)Y34 -KKP)4S6 -XSP)939 -N6J)DZP -JXP)N6R -KNJ)7FS -N3V)LMJ -JVF)R94 -21C)R4Z -NYK)5GN -GVJ)Q6C -R69)NRS -GLS)C7D -T4J)46R -5GB)51S -9WD)7PN -HHX)KK2 -H2P)ZML -DWD)Q9F -FKZ)LC3 -Q9F)M8N -CRZ)LM1 -6DP)YML -NSR)L2X -PMX)Q7K -37R)1GF -L4G)P4W -17N)X6D -JTF)89B -JGJ)DVJ -VF9)GMW -NHD)DJ3 -TRY)F6S -J11)BVW -95X)XB5 -3XD)HPM -7BB)1LW -FJ8)TV4 -JV3)M9W -T7L)6SS -R48)LSB -F2P)9D2 -PTY)QBY -KXM)6G1 -N1H)Q2R -P27)SR9 -1S2)N3G -V7Q)642 -891)TW7 -B9Y)BRL -GW4)3XZ -QWM)G46 -WVK)S6N -N82)317 -8PG)S21 -NT3)1VX -QB5)Y3H -PTT)639 -G8M)WM8 -B36)LX9 -M9M)4P3 -3F9)Q3R -DND)TJL -VQB)6N3 -PJT)JTK -BBN)T4L -LYP)M3V -T9R)HH9 -XBR)3X5 -MX3)SWF -SF1)MXT -X67)6DQ -82Z)FQ4 -L64)FNG -CDG)5D9 -JKZ)XZ5 -MH1)1KD -5NW)ZH4 -P3T)76Z -2M4)CKW -54L)8P7 -JSH)5H5 -LGR)P2V -QNV)SJ7 -KPS)XMQ -F2H)49M -8NJ)KKP -XZ1)LRZ -RVK)J5Z -QT9)NGQ -1TK)P7X -39M)595 -DN9)HKY -HK1)ZRH -SH1)JV5 -B25)GQ6 -QZC)WYC -6CJ)F5D -5R1)HQ7 -FNT)P4J -4R6)P49 -LG4)QT9 -GWH)RY1 -1FX)ZK8 -HK4)G2N -4WL)GPR -SQT)KK1 -RT4)FCN -NRF)P84 -DQW)4L4 -52N)T4J -69D)2FV -RMV)J7N -S9J)1WM -B88)9GT -5M7)GXN -3XF)6FX -FL9)8VZ -X88)JZR -ZVZ)8J2 -Q83)94V -82Y)HT7 -7Y7)7X3 -KNK)R1W -469)PMG -D9Z)GD1 -Z62)WR1 -YDF)6B6 -5KS)6GW -57T)ML7 -GXC)R89 -S2N)99C -JFH)RP9 -KPH)R26 -DZX)93P -CWT)C2H -VKN)5M7 -VNG)SH1 -G2N)F6Q -NFV)FK3 -R65)TQL -Z6T)4NG -RQN)KPR -972)9TB -KZ1)6TY -8K2)HKL -KHJ)H1W -6N3)XTR -25Q)T49 -8HF)K9M -GQX)PHP -5ZJ)9S7 -C7D)VMJ -JXV)SJD -J17)64C -5XN)WN7 -PH9)WQH -43T)Q9V -Z5F)NZ8 -VHQ)D95 -244)7KX -6N7)JPH -HC8)HND -ZF1)39F -24X)ZPF -BWV)HQW -R3N)5R1 -QB9)6XY -KHW)KFZ -S2V)DRQ -S21)1RQ -C9V)TSD -Q1Y)LC2 -93Y)W5C -8ST)T4P -R5Z)CL4 -424)WNZ -R7M)5JS -4R6)H97 -ZXZ)S62 -FRH)SBJ -ZK8)N82 -6FX)MTK -Z5M)BRQ -YYP)FX8 -RZJ)DRK -V8G)TKQ -5L9)J1G -RZG)69H -R9G)X79 -WFS)ZJQ -4P8)GXC -TYW)S54 -R2H)QH7 -6HX)F2H -BBD)DC5 -DDB)6WC -2G3)4JN -FKC)K7V -XTK)8BD -Z7X)QGY -8CG)3F9 -F39)MM9 -F1L)1R7 -ZVH)JDC -BVW)PXM -PRV)BF7 -FX8)1XR -FB2)XN6 -R9L)Z1V -YDT)H52 -6Z5)XZ1 -QD2)Z7Y -TLS)6T3 -54C)DL7 -KPR)4TY -19N)415 -1QG)GNN -S6N)4MK -4L8)LD2 -5Z7)PRY -5C4)2MC -94B)DY3 -CVK)GTS -7N7)P27 -5MW)GGH -2HQ)JYL -L9J)HLP -5Y4)NGN -2BZ)GWN -HD8)CZS -HQ7)M9D -DC5)RK6 -66W)2VT -3D4)GHZ -T49)VTP -PL4)ZS9 -SJ7)TRC -NKT)G5Y -K1G)3GN -37V)4LG -KWL)VDZ -7XF)1P8 -64C)FX4 -DY4)J3F -RV8)8KF -DRQ)KQ7 -HND)2N7 -HQS)HMW -J24)9VX -7DK)3PM -467)VBK -Q6C)TZC -SZY)9TC -BMM)4S4 -HFH)2S6 -K5K)4QP -N6W)RZG -TKQ)489 -4R1)F22 -J1G)YDF -FVW)9WD -CV7)TMC -R6K)H31 -GDL)X14 -H1B)NKT -XTR)PL6 -BSC)SM7 -MLT)S7B -22S)R7T -X8Y)4WX -NR9)NK9 -FSM)J3S -WHF)VSG -ZBG)Q3D -RMY)7KM -XBX)1M8 -MHY)1C2 -GSS)X9G -86F)Y4W -VL6)6H9 -1VH)L3B -SF8)CDG -GTK)45F -49M)NLL -FN6)PN3 -KSC)R3Z -6TN)3QN -FNG)742 -X45)WWH -SF5)2WH -JSJ)B1H -95L)M8F -L59)C4Y -93P)M89 -K1C)6ZZ -21T)8M6 -X9M)7NX -WPK)LNG -393)F6N -M4L)JXP -VKN)X88 -NFK)ZVZ -LKV)C2V -SWX)TM8 -V7F)8ZN -3RW)FD8 -9SM)H27 -TP3)1YB -6MG)D8X -8S7)345 -9SV)X67 -25P)JDD -BFX)TNG -36J)VBH -HN7)WVK -ZR3)3NR -M3V)GPY -52M)MFV -MZB)CJ5 -MX3)XLQ -LCG)PHS -HZD)RNC -GWN)DWD -XBM)WP4 -2FV)YXW -ZTP)QD2 -R1G)JY6 -KY4)8CG -H54)RVK -5HG)WYQ -BVC)SK1 -948)P3T -SV8)5MW -V4D)YLT -69X)LNZ -BL3)Y97 -DXG)WLZ -VV1)SS3 -ZCD)VXB -X6D)XL2 -B9H)2NB -KHK)WPK -YLT)KFT -P49)CC5 -KBW)CRH -8KQ)LJ4 -8JJ)VTJ -TKM)428 -3SB)273 -GPY)R2Z -WTX)P6W -LB1)3PR -Y1R)DJM -25P)CY5 -SVB)PJM -56N)S2V -H82)8D5 -CYB)GP4 -HJ2)BSH -2J1)F1T -C4Y)PRM -TZC)PM5 -K55)NBJ -X43)LPP -WYG)3FW -WFG)N2Y -Q37)5L9 -WSF)KSH -V2H)S9J -HN2)DW9 -3LL)PFH -6X3)XVM -8XZ)991 -26L)WTX -Y97)5C5 -XXL)79Y -NK9)RR8 -L7W)83Q -8TX)45B -GMJ)1H4 -ZRW)58J -36X)PRS -8B2)HTL -8JZ)L94 -PRY)QTW -PL4)X8Y -89N)1RJ -DFJ)62K -5QZ)CN3 -RYQ)SL6 -1H4)PGZ -B1H)J88 -JCC)111 -V6W)GG7 -BZK)97X -49J)WVY -1WM)21X -TCN)KSC -RRD)26V -VC6)WPS -Y5S)YJS -DVR)2J8 -LJF)839 -64D)GZC -79Y)SZY -JHT)D6J -K4K)L59 -YHB)QWM -6H9)MRR -X79)M62 -LW7)GGB -469)TRQ -14K)951 -L9Y)K51 -W7C)Y73 -XD1)CYL -1XQ)HYK -Q19)PWG -F4M)KHW -SM1)J3Q -MV1)1X9 -NMV)3SM -8ZD)L61 -VWX)6R6 -S4Z)JK4 -9GT)R13 -F66)89X -DLT)K6R -H4C)NW9 -R3D)6Z5 -MKN)M5V -H4C)22S -BFM)J2V -KQW)G8D -V61)6HG -JX4)LH3 -PHS)P68 -V9M)56X -1Q6)Y8V -319)KX2 -M8F)881 -974)KSL -LRP)XXL -M3Y)Q39 -LC3)B9H -4T8)ZRW -KYB)T7L -DXJ)72V -SRP)D3M -BRN)NGD -43S)NJ1 -KWJ)VGZ -DNY)F2J -DKW)YT1 -6B4)6N5 -GRQ)RYT -4KV)WFG -6PG)T9R -Q3T)V2P -4M5)HLG -WKZ)9ZP -XTP)JMC -PVZ)JN1 -5F2)26L -76Z)R5P -FVW)NS1 -MWS)PXD -Z7Z)8S7 -CTH)7C2 -837)48K -3SM)HYY -J2B)1TS -Y8V)BS6 -YYD)3XH -4F7)BFM -6S1)95D -4KN)JV3 -GSZ)HVF -9CP)GPZ -BFN)LB1 -N72)741 -K6R)3WF -P4J)QQW -54G)469 -36T)GJ4 -HXM)X6W -MR9)M29 -XMQ)SP9 -71F)TJR -95X)DLT -1ZX)QVK -F1L)1SY -B7X)XDB -FJW)ZCR -43X)1XH -D5H)93V -FQH)5RJ -CLW)1RG -X4Y)X9M -CRH)DWH -XWX)GWZ -36J)TKC -YFN)YJ6 -15X)MBT -6T3)NDG -8SY)4R7 -XMG)HR5 -KSZ)WKZ -PM5)3K8 -BR4)J1T -F72)GV7 -317)P1W -CV7)SPK -H53)PMX -NDG)56N -N68)ZXZ -X3W)XGJ -JRJ)S7X -MKN)DBW -8CM)953 -M2K)3XL -95K)95X -58S)4HL -D95)L9Y -FRH)KQW -NLL)C3D -X1H)FM1 -R1M)GGQ -Y8Z)W1B -KLD)G1V -6CJ)R5X -5C5)HN7 -T7M)ZXT -SZF)B5W -RPW)6TG -3VP)2W9 -X2J)RXH -DWG)C9V -9FB)524 -1PZ)8ZD -ZKZ)6S1 -L36)ZKN -F1J)2D4 -LWC)6SW -SWF)Y4V -51L)MWS -KFZ)52N -GD1)HFH -LFK)L36 -KPZ)ZQ6 -3NT)W48 -2CD)G3D -345)JXV -2LW)SWX -9ZY)XTJ -VWR)576 -STH)NHY -L4X)M4L -ZML)RN7 -RDF)7PB -7FK)3KR -GVX)DCF -1WX)DD2 -971)H6W -H6H)BPX -BWQ)Z4J -JPL)3SV -QWJ)TR8 -376)H9P -Q3D)1YS -1N2)FQ6 -2LM)53K -VSG)6DP -KNM)8B7 -S7B)YXF -YHB)JHP -Y7N)CPB -M29)3FB -J37)C8B -MK3)WHL -MRG)TQ8 -BFM)DLH -H4Q)9HF -D81)R7M -LRQ)ZKZ -C1B)413 -BKC)PW6 -GP4)6MX -C39)JSH -BW8)TL2 -71Q)3YP -415)H2V -DBH)BR4 -JJ7)J2H -G52)87N -YV2)JN3 -7PR)Z3V -999)G8M -S7Y)JRJ -G3D)88H -SR3)NTR -JY5)FC8 -MYL)B7X -K7V)HM6 -FXY)L47 -NNN)GYH -8JJ)Y5S -3G5)37V -FLP)4B2 -839)83S -H27)CV7 -X4F)RXV -S3P)WMZ -LD2)SF8 -DYG)77S -LGR)2LM -7BX)G2K -KNF)9S5 -JBS)R45 -T6C)CGH -CNV)2BZ -356)1KP -P93)54J -VGZ)31Y -GNG)HDL -RHW)222 -4T4)4T8 -WVY)M5Z -KQ7)XMG -K7F)S2N -X6Z)Z9S -XYH)WFC -7BM)J2B -H9F)LKV -WDJ)HWH -MWM)83M -YM5)7J5 -Z62)8NR -99Q)TVF -VDP)C2N -9VX)B5T -YS6)KNF -35R)ZH5 -JN5)Y4H -MSN)XSP -776)CJ4 -3FB)HXT -HZV)6HY -Q6N)HXS -MBT)FTN -3JP)YJ2 -4DC)KSD -8PG)5QZ -YSP)CNV -THM)CST -3X5)BPC -ZG9)4KY -8M6)MZ5 -FDF)XNB -H4X)N72 -ZH5)J79 -KN7)ZXV -1GP)R76 -K5R)CLZ -W8G)XVF -YJQ)HB8 -BWC)TB6 -WFH)T6C -DPB)VYF -K8N)KWJ -C2V)HMF -H93)HF3 -TR8)MFW -RJ4)F66 -BS6)FVW -QFW)5B2 -ML7)FB2 -TGY)X9Z -PRM)ZV3 -4YX)4YV -36D)N6X -XLQ)TLS -WMZ)NRF -BCM)2CV -M74)CHT -JYL)LQ4 -RSN)KXR -KNK)3Y2 -89X)BJK -C2H)4YQ -YYQ)VMB -164)11H -WYQ)WSF -1RG)DRH -GKD)LLT -H53)T2F -X2Q)F82 -B5D)5F8 -JK1)4F7 -1YB)P26 -B6F)552 -RTD)883 -ZPF)DWG -JRV)DL1 -MLQ)S1Y -TX8)5QV -NDT)2MF -HFS)61F -HD8)TCN -8BL)F2X -4MK)R6Z -WVN)RMY -GGX)JCC -GQ8)J11 -H4V)5FJ -3JD)VNC -7KS)9SM -NTR)YV2 -4LG)JK1 -3XZ)GGX -SVZ)P96 -4WG)N3V -QY7)8N9 -XMP)LKL -T4P)RLM -J7C)JJZ -7PC)Y23 -LPP)M6T -F82)9KL -9XR)VT4 -SF1)4T3 -FW6)N66 -QBY)D49 -BCM)17Y -H1W)R6K -ZVN)7QK -BRH)7JF -LKL)39C -LV1)BJS -8PC)FN6 -CHB)TBS -ZLR)3XD -8BD)BSC -NVC)9FB -Z9L)HK1 -FT3)BWL -446)S8V -LM1)D8G -KH3)Q6P -J8C)WFH -YT1)SDH -CGZ)X3V -77B)V9M -2RJ)H4V -NHY)H47 -89B)HM7 -Z1V)58S -17Y)1Q7 -J3F)891 -WDG)VSZ -PJM)21T -3YL)74D -8XJ)15N -Z2X)VHH -N6R)R93 -5QV)8XY -KSD)RYF -6DQ)X8F -Z2Q)MZB -ZFG)972 -5LK)FT3 -D25)1CF -RMQ)2HQ -85N)HDY -952)WFS -T4J)B88 -2MC)JFH -BRL)D64 -GJ4)65N -ZC2)QLQ -69T)3WV -W4F)WMG -74D)NCN -3YY)19K -JKG)6CJ -S68)GGZ -6N6)H2P -3XL)ZVG -S1D)14K -GMK)DW3 -HJF)1D5 -9DP)P9D -18K)Z2Q -248)YD2 -DTK)MR3 -LH8)1GZ -7ZC)RZJ -YJ2)ZVN -JN1)1FX -3WV)289 -53D)GJX -883)FXW -79K)ZXD -DLH)9X5 -BRQ)KHK -2XW)R65 -RGD)GCY -RNC)TR9 -HYV)54C -SJF)BBD -T81)F2T -GZ2)KBQ -G2K)48L -PL6)B5D -R76)Z4Z -QVK)TDX -F6N)M6X -8XQ)3JP -HXD)WNB -CLZ)37R -K6R)SY1 -X9G)8CM -2W9)W4X -ZXV)JC5 -HKY)1Q4 -KV1)QZC -LMT)CLW -Y4M)P57 -1YS)SJF -NGV)N1R -VLF)RGD -FJ5)8WN -PWG)V4K -XDC)KY2 -3DJ)RV8 -1RJ)2GN -WXT)MP2 -R89)JLR -GGB)RDG -Z6L)GQX -ZJQ)TLG -3WF)FQH -5YP)5Z3 -C1B)CCD -SBW)BQB -41C)W4H -1P5)YYP -R5X)36J -DZL)KNW -P57)CN4 -C85)78L -6YB)S7R -CYB)LNN -881)Z5X -642)B5K -X9J)SQT -BJK)M39 -BMW)SHT -2NS)VKN -1C2)JHT -H46)ZGD -JY6)RF8 -V1D)82Y -Z4Z)FW6 -CRP)JRG -1VX)77V -M2F)MHH -B7X)JJV -H29)7JR -Z4C)N13 -HN2)PRV -FTN)5FY -8HS)Z4M -JTP)GLS -JST)8XZ -4GX)T2P -1GZ)V8W -5MW)RT4 -9G2)QPQ -X6C)NGV -GP8)8SY -J67)ZBL -R45)BWC -DDF)S37 -31R)PHR -V4K)2L6 -J69)SYP -DVF)R29 -DLS)1BQ -72W)JKH -JPV)FL9 -TSK)69T -93V)T9M -CST)WPW -37Y)BJ8 -JR2)V4Z -B7C)X1V -WN7)GCD -K65)TM5 -HFS)KYB -1XR)TX8 -7L2)NXY -57Z)M6W -WMG)5HG -F6S)3YF -FMB)N6Q -HS4)QNV -XN6)X2C -56X)Z5F -NJ1)3M8 -65K)S2S -MSJ)Z3P -3RW)YJQ -YRB)L4G -5DZ)5YP -TB6)TGV -PDM)H9F -MTR)B36 -GGH)2LS -4S6)4KV -SVB)MV1 -JQN)18K -SRN)ZFK -ZFX)HXD -YNR)GCL -8QM)GDK -17G)B9Y -JKZ)19N -MJD)5BH -NSR)24N -T48)CF2 -Q3R)3TZ -741)T7M -P2C)G9Q -V8G)17G -GCC)54L -53K)TC8 -ZGD)F7V -J5Z)Z7X -4YV)HZV -GPZ)69X -RYT)RTK -Z6T)7ZC -FMT)ZVJ -56X)7KS -M89)YDR -F6Q)V8G -Y4V)MY7 -1Q7)17N -YV7)HQS -YLQ)GJ2 -5WT)VQB -YN7)DR2 -MPX)JBC -LFL)DPB -TNG)5Q1 -LW7)HC8 -HBR)Q6N -9K2)DNB -GXN)MHW -SGZ)1HF -WFS)N4R -3GN)2K4 -5Y4)1MH -M9W)7PR -WCK)DMQ -COM)TKH -6XY)LTM -WQF)1S2 -Z6N)3BD -CF2)LFL -GDX)ZQ4 -PGZ)1VH -X5D)6CP -TDX)MKV -3XX)BHR -SPL)DXS -GM5)TZR -M8W)DBH -PFH)KGJ -W4H)MKN -SPK)LRQ -V4P)63V -5LQ)WDG -L2G)49J -HB2)6Q9 -YV4)NTM -H47)9MW -ZB8)Y8J -C3D)HTQ -9HF)9K2 -XDG)GDX -FMS)239 -JJP)PKV -6C1)BL3 -FNX)JX4 -SN2)237 -TSD)PNN -RY1)JL3 -TX5)B2R -BS5)HJK -TBS)JNC -1BQ)PR5 -NRS)FX1 -5GX)BKC -8Y8)FRH -GP1)KFR -H1W)ZLJ -FX1)WT6 -HJK)WFT -7Z4)GT9 -FD8)RGG -8VZ)5PJ -1LW)PTY -PTT)15X -QVZ)6LR -Q9V)WMP -BLW)4DX -554)35D -YML)DND -997)CTW -L2L)6WB -PR9)K5K -6TY)5Y4 -2RQ)DVF -5PL)NK7 -3WB)KJ7 -PXM)HN2 -NBJ)FMB -BGN)BRP -BTH)C2B -9X5)MLT -XGJ)KGD -TDC)SBW -56Q)K7F -HF3)Z2X -RP9)952 -PKV)K4K -222)95K -LX9)4WG -RYF)HB2 -5CL)C4P -J2H)6PG -CXP)5GB -38R)L7N -NJ1)YDZ -LBC)42B -6WB)NCK -524)YOU -D8X)YNZ -KY2)BRH -W5X)DZX -SP9)G1J -JKT)LGJ -J2V)PJT -6SS)R9G -8MF)2L8 -X4J)8JJ -T1P)DLS -NWC)76R -YXW)RMQ -Y64)9NF -XB5)52M -JKP)YC1 -FZ2)ZCD -Q3S)CWT -YCS)QDR -S3M)792 -Q7K)N5M -952)MYL -GPR)F37 -Y7G)TFK -V7H)2G3 -CHW)BVC -FSM)TRY -RS7)BFX -KF6)3RW -TGV)6BJ -3TP)CXP -DXS)BW8 -8QM)NT3 -R4Z)X43 -7X3)7N7 -JJZ)3WB -GWZ)K7Z -XQF)R1M -2L8)4YX -891)F1D -S73)KS9 -289)3TB -XJF)PDZ -C29)K7N -YH5)8F3 -9NF)8LD -YX7)1NW -ZLJ)ZGS -DWS)CY2 -Z4P)XBM -HKY)K55 -P6W)BWQ -P1H)L64 -54T)25P -W38)6KP -CNV)9S2 -7FS)75T -9SV)PQQ -H46)VL3 -3FW)W91 -JBW)T99 -J89)MLR -CJC)4B6 -NYK)189 -R2K)3CT -S54)BHJ -98D)HRL -F1T)GRQ -T9M)NZJ -5B2)FNX -PQJ)D89 -WG3)2W2 -ZS9)WW8 -FSG)5SS -DW4)ZFG -78L)49Z -NGQ)2TJ -M6X)GDP -KXR)95L -1WQ)FNT -BRP)L4X -J3F)5C4 -2NB)JJD -SZL)5PT -FNB)DN9 -LNZ)ZBG -Z4J)NQV -D6J)H54 -1CF)SZF -QQF)1N2 -FFS)VF9 -NK7)KRM -6HY)TDQ -C2Q)16T -JTK)ZLR -1KD)N3R -2XH)JKP -BJ8)QHR -G9Y)5F2 -4R7)HGM -JGH)XS7 -72G)LLM -QLQ)Q1Y -TJL)8JW -N8F)8SX -JY8)HZD -3W9)JPV -WK4)HBD -8X9)6XH -YYG)WJQ -HZL)NQZ -BLY)JJG -6CH)CR4 -GQ6)248 -DWH)5LK -LQM)Z7Q -SN2)4DC -BF7)BTH -Z9S)NG8 -F5D)HK4 -2S6)5NW -LTM)757 -FC8)89N -SBJ)4T4 -XLM)XQR -S29)TDC -1YK)RL3 -6J2)7NB -SK1)7CS -GBD)H77 -9KL)HJF -LJ4)VST -S9W)4KN -99C)Z6N -L58)M2K -5JS)LR8 -WR5)9XR -V6W)WK4 -9S7)FRC -TM8)C39 -F4Q)Y86 -BN1)MTR -BGG)GP8 -GJN)MV8 -TLG)XYH -83S)CHW -Z1H)GX4 -3TB)HHX -J3Q)JQL -5Q1)75N -W91)57T -DVJ)HBR -B6F)M9M -WMP)5XN -WXQ)B17 -83M)XMH -8N9)SAN -LVG)8ZV -L2J)7SB -FNT)KM7 -BPC)B9T -1TQ)K27 -JZR)RJ4 -L9S)H93 -189)36D -TZG)2Z4 -5LZ)HXM -SJD)Q3S -WJQ)D81 -GP8)GZ2 -1TP)ZNV -X2J)837 -DJM)KDJ -7GP)NYK -TQ8)446 -HZL)4L8 -29G)3VP -4LZ)XTK -KFX)6N6 -HPM)WWQ -X1V)KVV -Y64)V4C -5GN)54T -SJ1)QS3 -DM4)83W -KDT)ZB8 -DL7)DKC -TML)SPL -LC2)K1W -MHW)5Z7 -MXT)RQN -9KL)K9L -M3T)YRM -KFR)Q49 -1DJ)SN2 -F82)2J1 -PWN)5PX -YT1)V7F -T6S)T1F -B8L)WB2 -Q79)LKF -853)RTD -KBQ)356 -HTL)54G -43T)53D -B5W)PH9 -7KQ)8TX -T2Z)1WQ -8HY)29M -552)M74 -STR)6HX -FRV)HMM -45F)J7C -4Y9)HFS -GNN)WJ6 -HXT)JQ8 -PNN)51L -PHR)RK5 -MM8)H1B -N66)G85 -C4P)W7Z -991)FSM -7QK)SLP -GDP)71Q -5MC)MRG -F2X)HY1 -B9B)CWM -SVZ)HN8 -XDB)4P8 -BS3)VFP -VXM)KCL -9G6)831 -9Z8)FNJ -GX4)C2Q -WFB)MZ9 -63V)MX3 -V8W)82Z -RTK)319 -427)WY1 -4T3)VVN -T2P)4LC -CR4)FQS -K4L)DTK -HLP)WCK -4YQ)H9N -RK5)QFW -GT9)SRN -YXF)FXY -V74)L3W -MY7)2RQ -JLR)JNS -9S5)LPH -H54)J37 -8XR)BLY -QMC)T48 -4TY)1QG -Z4J)H82 -BZC)LKD -4CP)86F -Z24)L58 -1FN)X15 -5FJ)QWJ -K27)2CD -3Z9)3W9 -L6V)J1J -51V)HJ2 -WD5)Q99 -49Z)G6N -Y4V)DDF -MFV)3GH -B1T)9CM -X9Z)BG5 -2M6)1XQ -2J8)3G5 -VMB)13Z -51S)BMW -1MH)LFK -VBK)3D4 -SDM)8XR -7NX)S2K -52L)4NL -LRS)664 -JDD)43S -JJV)H6X -62K)7L2 -WR1)L3D -LN4)WXQ -S52)C85 -F22)9SV -LH3)8B2 -YBD)8MY -TGM)N6H -ZVJ)MSN -S2S)5HV -2MF)GP1 -9ZP)3ZK -1LW)H44 -QTW)T9P -GHZ)YV7 -W7Z)M3Y -5FK)NWC -97X)36T -G7X)K5R -GLP)XQF -WQH)ZM7 -8YP)KF6 -WNB)WG1 -W21)1TQ -VBH)XM4 -CY5)3N6 -G1V)K1G -L2X)L9S -2CV)3LL -BKC)LC8 -R5P)JDL -JL3)T5B -HDY)FRM -XL2)F29 -8Y8)N86 -C8B)FDF -L3W)Z9L -WJ6)6FW -5HV)157 -DW9)1WX -C2B)JR2 -6HK)7GP -N86)971 -GZ6)KHJ -V4Z)376 -WT6)F4Q -H97)FP5 -M4L)MCT -D8G)BCQ -XPG)NP5 -8CG)GBD -6SD)6X3 -54L)1TP -N1W)MJD -ZXT)VXM -QH7)JN5 -S7H)4M5 -QSC)44B -19K)QLJ -951)25C -PJZ)W21 -X8F)X4F -CZW)SV8 -ZYJ)F5C -XNR)KPH -658)47Q -D66)3GD -ZGK)D65 -4ZT)YBT -3NR)K3P -WMD)HRP -VGN)554 -2GN)WH3 -8SX)DXJ -Z4M)MR9 -R1V)VDY -1D1)CRZ -CC5)MH1 -2NS)PXH -SLP)1FN -PTB)LYC -V4D)Z5M -Z2N)X77 -DR4)7KQ -646)98D -9PN)F21 -PB8)728 -WXT)4S9 -3YP)TGM -6PG)776 -9KY)T7C -5SS)LV1 -8HR)53Z -972)FZ2 -XJ8)9PN -6PB)Q35 -ZCR)42N -NNP)YPG -SL6)XL4 -1CG)YZJ -QKG)5GX -L94)HD8 -ZVH)GVJ -R93)3YL -4GC)2XH -FNJ)ZL5 -2LR)YBD -YDW)HMN -S8V)YRB -YV2)HS4 -6B6)6WZ -SVG)LB5 -DMQ)VWX -72Y)997 -MHY)3YY -JX9)XHT -MTV)DSB -413)6SD -DSB)25Q -9HF)BRG -B5W)P93 -9TB)XTP -JN3)6W2 -TFK)MKW -T49)4NY -742)MSJ -8F6)ZKW -TRQ)3JD -F2T)R8H -LQ4)GMJ -B9T)H46 -T2F)ZC2 -VC6)TJF -YDZ)R48 -RGG)974 -DTK)H4C -DTF)QCP -7KM)Z4C -GTS)MLJ -296)424 -664)H86 -2YP)ZYJ -V18)VC6 -7CS)SQH -DZS)3X8 -QYT)8HS -62Y)SQW -D8X)YXX -N2X)D3B -P84)6J2 -JPH)DZL -WM9)KWM -TM5)GM5 -W4X)YYR -TNG)LRP -1KP)ZQX -MZ9)72Y -WJZ)MPF -NP5)SQ3 -D66)5QS -H7H)ZCB -16T)V74 -X15)1WS -8NR)Y7N -237)DYP -N4Y)CGZ -Z8K)BYX -8KF)N6W -RF8)NMV -WFC)7XF -449)DDB -D49)X1H -TM8)78Q -G6N)73R -HGM)GD7 -F21)Y1R -TRC)5HH -N14)S73 -ZXT)BS5 -NG8)4L5 -8ZN)Q79 -4HJ)Q3T -837)NDT -1R7)R2K -77S)6YB -S7R)1XY -2VT)KNJ -WQ4)64D -M5Z)PVZ -RQN)8V9 -VVN)K2K -V2B)N3K -B17)7BX -1W5)LMT -1YW)X2J -XJC)XJF -P4W)4J1 -PRS)Q4P -BMM)QB5 -L7N)H29 -4W5)GKS -8WN)KH8 -N4R)39M -4NY)14W -19Q)ZG9 -W6W)J8C -PWZ)4RW -8F3)JBW -BC8)F4N -QG8)VDP -YG1)GBY -KRM)WJZ -4HL)2TH -W1V)FMT -1BL)NC2 -RTN)R6C -QLJ)PLT -SQH)93Y -KM7)9G2 -5Z3)JY8 -WB2)YSP -3S1)4W5 -5BH)SXV -28Q)5Q7 -PDZ)XD1 -D79)WHF -6BJ)DQT -5F8)C29 -46R)XNR -NC2)2Y8 -T5B)863 -TJF)PDM -L47)5QW -F59)JX9 -RK6)QG8 -GD7)RWP -863)7DK -97R)LJF -6N7)X32 -WLZ)XDM -RXH)79K -WG1)NQW -BNR)1P5 -ZXV)QQF -ZJX)GSZ -X2C)L5L -NVC)L2G -T1F)FK2 -GGZ)KH3 -TZC)R9K -157)FRV -3CX)Z1J -NS1)BGG -MFW)36X -DW3)C53 -88H)LP4 -FX4)F4M -676)7BB -9TR)Q3H -P5H)Z1H -LB1)XBR -SWS)FLP -4S4)QMC -KNW)5LZ -3PR)TVL -JYK)46F -ZM7)Z6T -Q99)427 -5R1)MYP -3TZ)YHB -QPD)L6V -HB8)K7P -2W2)ZFX -BS3)GWH -953)S2C -1BC)WKC -S7X)9PL -1RQ)KLD -1XY)JRV -D37)SF5 -PXD)P2C -4L4)CVV -MYP)2VZ -WPW)SFQ -N6H)8D7 -8B7)9RM -297)Q93 -LNG)R64 -BXB)NSR -DKC)MTV -6C1)81V -75N)21C -XY7)THS -BRG)YY2 -F37)RMV -831)LYP -M1P)GZ6 -ZXD)NR9 -6G1)35R -H2V)51V -Q9F)RRD -FXW)3XX -ZV3)CDP -JC5)JGH -Y73)KFX -V6G)1W5 -7BB)DR7 -RN7)56M -3GV)8X9 -HMM)41C -JK4)V1D -MFV)2J4 -QQW)H62 -N1R)CCC -B5T)3GV -G8D)8QM -JNB)Z75 -8D7)ST5 -JXX)C1B -G5Y)Y92 -G46)DW4 -3CQ)R9L -FR9)Q83 -N6Q)JR4 -ZG2)S4Z -JDC)NCF -ZLX)2XW -JJD)QLN -YY2)FJ5 -Z3P)W7C -LSB)N68 -64D)8BL -PR9)J67 -N6X)M2F -SQ3)XZ7 -MKW)KVM -L61)PL4 -R2Z)2BF -HGM)KQK -222)RJQ -4LC)PY4 -54C)N14 -MLR)Z7Z -BBD)W1V -JK1)32M -SY1)3S1 -65N)3TK -1X9)4HQ -6F3)H6H -489)GFB -Y86)52L -HN7)R1G -48K)5MC -4P3)Z6L -CHT)8R9 -3M8)HKP -RK6)PP4 -X77)V4D -YDR)LCG -DZP)3CY -75T)TKM -ZFK)5LQ -6R6)8NV -TVL)RHW -HMN)BNR -PG2)VN1 -FVQ)SQ5 -1HF)W5X -WVY)TGX -VYF)2N1 -BJS)LTJ -72V)GCC -8NV)BS3 -ZL5)P1H -3KR)69D -CZS)8WW -4N2)72G -KK2)JXX -5Q7)KPZ -4QP)HYV -1SY)V7H -CN4)JTP -9TC)SVG -K7P)T6S -QFQ)999 -NGN)QKG -BHR)DR4 -TGX)XPG -DY3)YG1 -M5Z)PHZ -KBQ)HVY -9D2)N5J -GMF)4LZ -1P8)BFN -GBY)KY4 -49M)LWB -FNZ)FFS -JL3)V2H -LB5)7FK -PM5)1BL -PHZ)LH8 -NCF)YNR -HSK)W6W -5RJ)C95 -RPK)ZRK -Y34)54N -5QW)TZ5 -KGJ)43X -P2V)Q9T -NQZ)L7W -WP4)S29 -J3S)C9G -5C2)TX5 -3PM)PK2 -3GD)393 -CCD)3Z9 -QKQ)PB8 -FCN)LRS -FQ4)M3T -45B)B1T -NPJ)MK3 -KGD)JJP -F5Y)JKZ -C6D)HSK -TR9)7SS -2TX)H73 -NFV)X5D -C2V)43T -M6T)KPS -PK2)1CG -TP1)N4Y -1D5)D9Z -MTR)97R -3TK)X3W -R7T)3VC -PHP)1LV -5GB)2H5 -YC1)24X -S5H)W79 -FQS)JVF -DML)6F3 -Z75)LXP -DMJ)29G -54N)GSS -RWP)D79 -VBV)XWX -VST)CMS -GZ2)676 -N72)FP3 -792)ZJX -H73)J17 -M8N)WQ4 -H6X)L5G -3VC)LBC -YBT)YR2 -LYC)4GX -3VP)17F -F5Y)9ZY -8LD)BCM -7JR)X45 -MV8)FY7 -JN6)31R -MZ5)CVK -239)S7Y -DJ3)S7H -RVK)6HK -G85)WR5 -LKF)TZG -SQ5)NP4 -HN8)H53 -CTW)MCJ -8ZV)6YF -2RQ)SR3 -MRR)Z4P -WQ3)TYW -6SW)L2J -HFC)CTH -N5M)1TK -757)RDF -R5Z)MHY -NW9)V3P -K3P)PWN -GD7)GDL -B2J)FN2 -BRJ)GK8 -S62)3NT -9BH)38R -KQK)WXW -2LS)T8V -4J1)5WT -7J5)H3D -W1B)F72 -F4N)NFK -QCP)4HJ -DWH)V5B -87N)XY7 -F13)LWC -7VH)67W -PMG)DY4 -JMC)WQ3 -6HY)PTT -YJ8)DML -9CM)DM1 -54J)DNJ -1Q6)8ST -CKW)XS3 -ZKW)JPL -111)YFN -H6W)R5Z -THS)X4J -DTM)PWZ -ZH5)8PG -JR4)Z24 -NCN)8HF -3BD)B8L -76R)LN4 -N3K)97M -JJG)N1H -5JW)P48 -YJS)XMP -4RW)T2Z -D65)DNY -KWM)ZGK -5FY)9BK -Y8J)7DR -5PJ)1YW -24L)PTB -XTR)PJZ -LLM)QSC -R6Z)V6W -H62)PQJ -HT7)V18 -6CP)S3M -WXW)N6J -GJX)F5Y -Q35)QY7 -3K8)F59 -8SX)SWS -B2R)6N7 -R8H)CRP -CGH)HFC -NWC)QKQ -P9D)BLW -NK3)YLD -CDP)2M4 -Q39)QB9 -F2J)X7D -J79)QHD -VXM)948 -X7D)GLP -NP4)Q37 -69H)K1C -FF1)65K -P7X)YDW -HTK)B6F -273)CTT -D25)164 -QGY)DXG -G46)BMM -QPQ)SZL -HM7)G7X -VMJ)J24 -5QS)RD6 -KVV)4CP -6W2)8KQ -1JP)PR9 -4B2)SF1 -FX4)NNP -2N7)ZRC -JQ8)N1W -LKD)83V -345)CJC -HVF)QYT -Y4H)7VH -5LR)4MJ -S2C)FSG -V5B)BBN -5X5)SJ1 -MKC)NPJ -BWL)F39 -VDZ)Z27 -7GP)YB3 -8R9)R3N -SQW)GNG -3X8)V2B -D89)SM1 -Z4P)RSN -YB3)5LR -V4C)1JP -FGH)FF1 -GKS)R69 -M5V)H4X -3CY)KXM -G4S)D5H -12P)1YK -3Y2)R1V -KTZ)DQW -KD3)L2L -KSL)F13 -R3Z)JKT -G9Q)1D1 -2J4)5DZ -X3V)MM8 -Z7Y)1BC -G1J)G4S -W4X)LFX -YJ6)JMV -FP5)KN7 -PCQ)8HR -FN2)W8G -31P)WFB -YXX)CYB -NXY)77B -NCK)Z8K -VPX)3TG -CN3)JY5 -HXS)WQF -FK3)DZS -WFT)9DP -XZ5)F1L -639)T81 -R26)PCQ -2VZ)YYD -4S9)1PZ -HVY)V4P -K55)K8N -2Y8)WMD -69T)24L -MHH)SRP -WPS)YWV -9PL)NHB -D3B)KDT -SHT)GJN -42N)6MG -K9F)YDT -N2R)FVQ -F3Q)296 -YML)8XQ -6YF)B9B -R13)Y64 -DNJ)DKW -H44)ZTP -1Q4)5JW -RLM)BRJ -LMJ)8HY -CL4)LF1 -6GW)TMM -VTP)JWQ -TQL)G52 -3QN)VWR -BFN)VPX -T39)TSK -Z1J)S3R -F7V)XBX -VNC)LW7 -WM8)788 -HBD)K9F -JQL)JGJ -3SV)WVN -DM1)297 -VHQ)467 -PVJ)12P -3GH)2M6 -6MG)KD3 -1NW)4GC -VTJ)FKC -Q8H)P86 -5QW)BXB -ML7)V61 -94V)NK3 -XM4)TML -V2P)5Y3 -CR6)JKG -7LG)S9W -8TX)V6G -2JY)ZG2 -DVR)57Z -VN1)Z2R -ZC3)N2C -SB6)RPW -58W)1ZX -VFP)X6C -JQN)ZC3 -53Z)LQM -KWL)TP1 -HKP)4BW -S9T)Q19 -K2K)WD5 -WLM)YV4 -SFQ)4R1 -6KP)CTQ -V3P)XDC -CXM)MKC -31Y)Z62 -XHT)L7R -FK2)S52 -LVY)HFP -RJQ)KV1 -9S2)2LR -NZ8)DVR -JKH)PG2 -ZQX)3TP -81V)9CP -42B)WDJ -7PB)S68 -39C)6C1 -RR8)KSZ -XL4)RTN -3XH)RYQ -78Q)TP3 -GCD)5YQ -R29)LVG -Q3H)646 -TMM)ZLX -4B2)WDB -6N5)449 -3XL)NFV -CDL)6JS -TMC)B7C -R1W)ZWC -LH3)XJC -CHH)DFJ -1FN)MLQ -LMT)658 -HK8)BN1 -73R)1GP -ZQ6)6B4 -Z5X)D37 -YPG)GTK -8SM)VL6 -W5C)C6D -4BW)YS6 -DYP)2TX -R9K)BRN -KS9)L9J -XTJ)B25 -Y23)CHB -NHB)LG4 -L5L)7Z4 -DRK)9SL -ST5)NVC -2WH)DTM -1LV)SDM -788)256 -TW7)6TN -6FW)3CX -BG9)4Y9 -67W)JJ7 -2D4)FR9 -Z8K)F1J -LTJ)31P -R94)YJ8 -5PT)MPX -9SL)LGR -FKZ)9G6 -DR7)SGZ -SM7)9KY -TKH)8MF -VXB)4N2 -XQR)W38 -21F)HK8 -Y3H)XLM -DBW)M8W -11H)853 -1WS)66W -DW4)KNK -NQV)SVB -6ZZ)8YP -ZWC)5PL -PP4)3CQ -T8V)THM -J1J)HMK -CPB)Y7G -GYH)9BH -WPK)FMS -95D)FJW -HM7)CJJ -ZGS)LBV -HMK)BZC -2BF)DWS -LWC)85N -L3B)M1P -7C2)WG3 -3ZK)7BM -GDK)8XJ -LGJ)4R6 -DL1)JSJ -44B)6T9 -KFT)CXM -Q4P)STR -LBC)6ZD -GDK)STH -6MX)F2P -Y92)21F -6ZD)YYQ -HYK)58W -3YF)KNM -X9G)8K2 -QWN)JQN -17F)KTZ -CJ4)62Y -KQW)GMF -15N)S9T -G1V)GMK -M62)X6J -8V9)SVZ -WW8)DJ9 -FP3)28Q -PMX)F3Q -N3G)56Q -46F)ZN3 -D3M)S3P -D64)LVY -72Y)ZHM -LPH)WLM -HY1)HZL -L3D)QPD -Q9T)X6Z -6HG)3DJ -KBP)9TR -25C)9Z8 -ZR9)RYK -TJR)5C2 -56M)X4Y -TL2)5CL -939)ZVH -595)DTF -Z27)D25 -54T)MWM -ZBL)W4F -6JS)H7H -YWV)QWN -5D9)S5H -P96)KZ1 -TDQ)8JZ -NQW)VHQ -K9L)DMJ -H6W)8F6 -2TJ)8NJ -MCJ)T1P -M94)JNB -5ZJ)9BG -KCL)RS7 -X6J)ZGQ -PQQ)JN6 -S2K)5FK -K7N)X2Q -HTQ)GW4 -LTJ)RPK -DD2)8J5 -7NX)Z2N -6LR)R3D -YR2)7Y7 -JBS)CZW -ZRK)XJ8 -4L5)3XF -GJ2)FNZ -XTP)YCS -HRP)P5H -BRJ)J89 -RD6)ZR3 -YNZ)N8F -2N1)XGH -JDL)DLD -YLD)94B -ZNV)1Q6 -6TG)CR6 -GMW)KWL -TZR)698 -RDG)VGN -F1D)5X5 -3CT)6CH diff --git a/inputs/day_7.txt b/inputs/day_7.txt deleted file mode 100644 index b21d6af..0000000 --- a/inputs/day_7.txt +++ /dev/null @@ -1 +0,0 @@ -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/inputs/day_8.txt b/inputs/day_8.txt deleted file mode 100644 index 21110e8..0000000 --- a/inputs/day_8.txt +++ /dev/null @@ -1 +0,0 @@ -211202121222222222221222212222202022222222222122221220222222222222222222222202222222222222122121022222212222222222212212222222210222202212222222012222200222021222222222220222222222202222222222222022220221222222222222222222222222222222222222022022022222222222222222222212222222221222222202220222202222220202021222222222221222202222212222222222222122222220222222222222222222222222222222222222122220022222212222222222202222222222220222202212221222102222211202020222222222221222222222212222222222222022220221222222222222222222222212222222222222122022122222202222222222212202222222212222202212222222202222220222022222222222221222212222202022222222222222221220222222222222222222222212222222222222022122222222222222222222202202222222220222222202222222212222210002122222222222221222212222222022222222222122221221222222222222222212222202222222222222022220222222202222222222212222222222221222222222220222112222211012121222222222222222222222222221222222222122220222222222222222222212222212222222222222022120222222222222222222212202222222221222212202221222122222212122121222222222222222212222122022222222222222221220222222222222222212222212222220222222122021022222222222222222212202222222221222222202220222102222200212020222022222222222212222012221222222222122221221222222222222222212222202222222222222222121122222212222222222212212222222221222212222222222111222212022021222122222220222202222022022222222222122220221222222222222222202222222222222222222122120222222222222222222202212222222210222212212221222020222201222222222022222222222222222122222222222222022221220222222222222222202222212222222222222222222022222222222222222202222222222221222212202221222002222220202020222122222220222202222112221222222222022220222222222222222222222222212222220222222022120022222212222022222202202222222200222202202221222210222220022122222222222222222212222022021222222222222220221222222222222222202222202222221222222222020122222212220122222202212222222201222202212221222112222220002222222022222220222222222122121222222222022222221222222222222222212222202222201222222222120222222222221222222222202222222212222202222220222101222200212021222022222221222202222122222222222222222221220222222222222222222222212222210222222022022122222222220022222202202222222222222222222222222220222221022022222122222220222222222012020222220222122220221222222222222222212222212222212222222222220022222212222022222212222222222212222212212221222011222222012022222122222220222202222220122222222222122220221222222222222222222222212222221222222122020022222222222222222222222222202220222202212220222022222212102221222122222222222202222112021222222222022222220222222222222222222222222222202222222022120020222212221022222202202222212210222212202220222211222210102220222222222220222222222120122222222222022220220222222222222222222222222222202222222222222120222222220122222222202222202200222202222222222220222200012022222122222220222202222220122222222222122220222222222222222222202222212222220220222122122022222212222022222222222222202201222212212221222221222212122221222022222220222200222112022222222222222220020222222222222222202222202222220221222222020222222202221122222212212222212212222222212221222212222211012221222022222222222220222201121222220222022222021222222222222222212222222222200221222122220221222202220122222222202222222211222222202220222022222212002120222222222220222220222100222222221222022222122222222202222222212222212222221222222022121122222202222022222202202222212200222222202220222010222212102222222002222221222221222011022222222222022222120222222202222222222222212222210221222022221021222212220222222202212222212202222222202220222001222220012020222112222222222221222121122222220222122220020222222212222222212222212222220222222122022221222202220022222222202222222210222202202220222010222211022120222212222221222220222202120222221222122221122222222220222222202222202222210221222222221122222222220022222202212222202201222202212220222012222200212022222122222222222222222212222222222222122220121222222210222222202222212222201220222122121122222222222022222222222222212210222212212220222200222200012122222112222221222202222201220222222222222221221222222201222222212222222222210220222222122121222222221022222222222222212220222202212220222202222202012220222212222220222201222010121222220222222220020222222201222222212222212222220220222222122221222222221022222202202222202202222212222220222211222201112021222012222220222221222101121222220222222221121222222201222222212222202222022220222022221122222222222122222212222222222201222222222222222220222201202122222102222222222201222102220222222222122220222222222220222222222222202222211222222122120221222212221122222212202222202200222222222222222020222222222121222222222222222212222012021202222222022220021222222222222222202222222222200220222022221020222212220122222202222222222221222222212220212220222210122220222222222222222212222110222212220222222220021222222212222222222222212222001221222122020021222212222022222202202222212212222222202222212102222210022121222102222121222210222021121202221222122221022222222210222222222222202222001221222222121120212222220022222202212222202220222222212222212012222200022221222022222020222200222222122222221222022222122222222201222222202222202222110222222122221121222202221222222222202222222222222222202222212220222220202121222222222121222201222111221212221222022220120222222210222222202222212222202222222020021020202212222122222202212222202211222222202221212002222212122222222022222121222202222102121212221222022220022222202200222222212220222222211222222121221021222222221022222202222222222212222222202222212010222202102121222022222120222220222201021202222222022222222222222220222222212221212222200221222122221120222212221122222222222222202201222222212222212222222221222120222002222121222201222100021222221222222222120222212211222222222222202222001221222022020122210222221022222222212222222212222202222222212120222202022221222122202122222221222002221212222222022222222222202200222222212220222222111221222122221220210212221022222222202222212202222212212221222010222222102222222002220020222210222212120222222222022220022222202212222222222222212222002222222220121221210202221122222212212222222222222202202222202122222200222111222122220122222210222000020202221222022222221222222222222222202222212222211220222022220020212222220222222212212222222211222212212220202200222222102112222222222222222221222112021222221222222221222222222200222222202221222222212221022020220022220202222122222222202222210222222212202222202122222220112100222002200020222212222010120202220222022221020222212210222222202220202222011220220121121022022222221222222202212222222222222202222220222221222211012110222102221021222222222200220002222222022220121222212201222222202222212222212222221120220020121202222222222222202222222220222222212222202210222200022210222212220122222221222012220102220222222022221222212222222222202221212222021222022122222121012212222022222222222222200222222212212222212202222221102110222012212122222220222001222202221222222120021222212201222222212222222222011221120020221220111202220022222222202222201221222222222220202110222202012021222122220020222202222121220002222222122122122222222222222222212221212222220221122120020221110202222122222222212222212210222212112222222010222200112110222022222121222221222212020002220222222222121222202211222222212220202222222222220122120121011222221222222202202222222220222212102221222101222210222002222110221222202211222001021022222222022121220222212221222222222220222222012221121121021020121202220221222202212222001220222212112222202210222220212101222110211020222202222000220022222222122020222222222221222222222220222222022221122121121222002222221221222222202222210210222212212222202101222211102022222100220120212220222010020102220222222020222222222211222222202220222222221220121001022021110222221221222222222222011222222222022221202000222221022201222200221221010200222011220202220222022220220222212202222222222221222222212221220221220021210202221120222202012222112221222222022220202111222222102112222200220121110202222011020112221222222122101222212220222222202222202222101222222121122220001212221121222222202222220222222202112221222200212212112110222201201020101220222000220002221222022220011222212211222222202222202222012222122001122022210222220222222222022222222220222212102221222120202221202010222011201220010212222001221212220222122121100222222222222222212220212221001220221001120220221212221120222212002222010212222212222220202200212212112022222020220022001201222000020222222222122121002222202220222222212222202221200222220112120122211222222122222222212222012210222202212221212121212201202110222002200220211201222210022222220222122222010222222222222222222220212222122220222222122122200222221122222222012222221201222222112221212002212211022212222122211121222210222212222112222222022222211222220210222222222221222222102221221211022121110222222020222222012222201212222212202221212110222202102021222210211222210221222010020212021222022221021222200212222222222221202200111221121110122021020202221222222222202222022121222212012220212212212202212122222021220020120222222202122102220222122021211222201111222222222221212220101222022200022120002222222220222222002222022110222202202221222202222212202221222120220021210202222020122102020222022020102222220112022222202220202210100222122221122022202202222221222212012222110001222212202221212202212222212100222220211121101220222210021002122222022222222222212102222222202221222200002221020021022022002212222121222212112222100100212212112222202212222212002220220100211220102211222020021012120222022221222222211222022222202220212220102221021111020021201202220120222202222222012200212202102221212212202211022221222121212020221210222210100202222222122220212222201102022222222220212202000221222202222120212212221122222212102222111010222212122222202210212212002120221202221222002200222212020022221222022120000222210211122222202221212220012222022212020121120212222222222202112222111011202202022220202220212212002201220002212021002200222122222112221222122121222222210211222222222220222200111221020122122022121202220121222222022222220210212222022222222020222202022102221222202120112212222200112212020222122122111222212020222222202220212211101221222211221220120202220120222212102222120222222202102222222021202221122212222010210021122210222102120022220222122222210222202220122222202220222220001222020211220220020212220221022212222122010102212212222221202112222220002220221101212221021211222221200202021222222222012222221011222222222220222220222221120112221221012212220122222212022122122101222202022221212020212210022112221000220221102221222100120022221222022022001222210212022222222220222202220222222120121022002202221220222212012122200201202222202222222210212201012011221020221222212222222200220202122222022220102222222011222222212222222202012221221100221121212212222222122212112122222002202202112222222002212202212212221112220221111211222201000122121222122022020222201010222222202222212202221220122120120120120212221021222202012122021021212222112222212112210200122222220002212220112210222110021012022222222021021222212011122222222220202220110221020202121022212202221022022212212222101020222202202222222000222201202110221200222222010201212200221222022222222020000222201112222222220221212222012221120111220022102212221122122222112222012122222222122221202200222212122101221210210022001221222112122222122222122221111222212002222222210221212201120211021110120021201222222021022202022022101000222200022222212120220201212210221210222220222220212011221202220222222122000222210120022222220221202222021210020120120020221222221221122222122222202222222201022221210112212222122122220110202121112202222210022112022222122020122021210212222222011221222210010221222221022222121222221120122222122022012022202202012222222210200201002012221012221020200220202120211102222222222022110022202001122222112220212211120221222200221021020212220222122222112122201111202212102221220010200211002101221111211120121222212120102222022222222022000222212220022222021222212221012212122120021021100202222022222212012222002221222000002221212121201220222010222012210122002211202202201202020222222121101212202112122222212221102211011222120012221221210222221222122202122122212122202022102222202010221201002010221121210020102211222210220112021222122020221200210202222222200222122221200201222121122221112202222121022202022122001102222022112221220120222201212200221011200221212220202200211102020222022122212101221022022221122220112210220212220112222121012222222222222212012022201202212122212200200122210211122100222002210021201200222212202012021222222120112001220220122221102220012221201220221120002022011202221220022202212122210002202001202220212110222222002201221111222221220200212122022222220222222020120010211200022222212221212202110210222110000221120222220220222222102022122211222010222211221202202220112001222010211201201211222112002222220212222220112202221122222220101020022002211202221112210022212022220021120212202122122220222122001202222012201202102100221112210110120210212222111222222212022020111000222122022221202220002111220212121222222221020102222222222212222222222001222020022211221221200221012212220222202212101211222120010222121200022020200002210210222222102221022200220222020210212201101202221121021202122122220110212101100220220101202210202201220121200102211210212201122022020201022020000221202200122221011222012001022221022002211101122122221222120202202222222101212212201210220202211212102222222200200012220011212121100022222201122021212200201001122222022020012120011002222021201010021122221121022202122122110122222211021220200212202222222220221020200001011010202122210002020202022021012002202201222220011022110210112121221222112102000122221220220220012222102002202101112221211222210222222020022210210120112200222211111122021220122022002000211020022222010020022201021221121000100000202212221022021212112222202112212222222200221021200222102100121121221221010212202102200012220212120022212102222011022220220220211200121211220211001122222102221221020202202222010121212200100221202012222212112011222020210010010221212122200102022220221020002000212022122221202021122000112210021200010000210222220120121201122222021102212102111222201121202201202002020120200201212110202101010102022200121222211012221121122221000122021100210212222122211220212102221020122210202222110002212200011201200021201220022012110200222202010110002212220010120010022120110012200120022222122021212000212022122022010021101012221222020212102122120000212202002202202222222210012200102200200111220022112012202102021122021120011121200020122220001221102112201201020102122212202112220122122212222022110111222010201211210002212202112020020222212100211112122120200002020201020021202021200200022222010120111011000012120121101212002212222122121200022022212122202211001220201122201201012022011111200001112022002112002200220221121202120002212010122222010222121211010100220111112122101222222021021211212122121120212202000200210112220002211221002010102121110201000000011200112100002201220112102201101001200002222202202212002201221110202000102001202000200100102121000220100101111222110 diff --git a/inputs/day_9.txt b/inputs/day_9.txt deleted file mode 100644 index 6ec0b92..0000000 --- a/inputs/day_9.txt +++ /dev/null @@ -1 +0,0 @@ -1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,23,1,1004,1102,1,26,1000,1102,897,1,1028,1101,27,0,1012,1102,33,1,1001,1102,32,1,1007,1101,39,0,1005,1101,0,29,1018,1101,0,0,1020,1101,1,0,1021,1101,0,21,1002,1102,1,35,1014,1101,0,36,1009,1102,1,38,1006,1102,1,251,1024,1102,28,1,1017,1102,37,1,1008,1102,1,329,1026,1102,25,1,1011,1102,31,1,1013,1102,892,1,1029,1102,242,1,1025,1102,1,881,1022,1102,22,1,1003,1102,874,1,1023,1101,20,0,1016,1101,24,0,1019,1101,0,326,1027,1101,0,34,1015,1102,1,30,1010,109,-2,2102,1,7,63,1008,63,36,63,1005,63,205,1001,64,1,64,1105,1,207,4,187,1002,64,2,64,109,9,21101,40,0,6,1008,1013,43,63,1005,63,227,1105,1,233,4,213,1001,64,1,64,1002,64,2,64,109,26,2105,1,-9,4,239,1001,64,1,64,1106,0,251,1002,64,2,64,109,-15,1205,2,263,1105,1,269,4,257,1001,64,1,64,1002,64,2,64,109,-9,2102,1,0,63,1008,63,36,63,1005,63,295,4,275,1001,64,1,64,1106,0,295,1002,64,2,64,109,-14,1207,10,38,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,28,2106,0,4,1106,0,335,4,323,1001,64,1,64,1002,64,2,64,109,-8,1206,6,351,1001,64,1,64,1106,0,353,4,341,1002,64,2,64,109,-1,2107,33,-7,63,1005,63,369,1106,0,375,4,359,1001,64,1,64,1002,64,2,64,109,-9,2108,26,-1,63,1005,63,395,1001,64,1,64,1106,0,397,4,381,1002,64,2,64,109,3,1201,-2,0,63,1008,63,38,63,1005,63,419,4,403,1105,1,423,1001,64,1,64,1002,64,2,64,109,-13,2101,0,9,63,1008,63,23,63,1005,63,445,4,429,1105,1,449,1001,64,1,64,1002,64,2,64,109,11,1208,1,32,63,1005,63,471,4,455,1001,64,1,64,1106,0,471,1002,64,2,64,109,17,21108,41,38,-4,1005,1019,487,1105,1,493,4,477,1001,64,1,64,1002,64,2,64,109,6,1206,-9,511,4,499,1001,64,1,64,1106,0,511,1002,64,2,64,109,-23,21102,42,1,8,1008,1014,42,63,1005,63,533,4,517,1106,0,537,1001,64,1,64,1002,64,2,64,109,-3,2107,36,5,63,1005,63,555,4,543,1106,0,559,1001,64,1,64,1002,64,2,64,109,-6,1202,5,1,63,1008,63,21,63,1005,63,581,4,565,1106,0,585,1001,64,1,64,1002,64,2,64,109,1,1208,10,40,63,1005,63,605,1001,64,1,64,1106,0,607,4,591,1002,64,2,64,109,7,1201,0,0,63,1008,63,42,63,1005,63,631,1001,64,1,64,1106,0,633,4,613,1002,64,2,64,109,1,21107,43,42,7,1005,1013,649,1105,1,655,4,639,1001,64,1,64,1002,64,2,64,109,7,21108,44,44,3,1005,1016,677,4,661,1001,64,1,64,1106,0,677,1002,64,2,64,109,-7,21102,45,1,9,1008,1015,44,63,1005,63,701,1001,64,1,64,1106,0,703,4,683,1002,64,2,64,109,13,21101,46,0,-7,1008,1012,46,63,1005,63,729,4,709,1001,64,1,64,1105,1,729,1002,64,2,64,109,-13,2101,0,3,63,1008,63,33,63,1005,63,753,1001,64,1,64,1106,0,755,4,735,1002,64,2,64,109,14,1205,1,773,4,761,1001,64,1,64,1105,1,773,1002,64,2,64,109,-23,1202,10,1,63,1008,63,30,63,1005,63,797,1001,64,1,64,1105,1,799,4,779,1002,64,2,64,109,13,2108,22,-7,63,1005,63,817,4,805,1106,0,821,1001,64,1,64,1002,64,2,64,109,-11,1207,5,24,63,1005,63,843,4,827,1001,64,1,64,1105,1,843,1002,64,2,64,109,11,21107,47,48,7,1005,1017,861,4,849,1106,0,865,1001,64,1,64,1002,64,2,64,109,15,2105,1,-2,1001,64,1,64,1106,0,883,4,871,1002,64,2,64,109,10,2106,0,-7,4,889,1106,0,901,1001,64,1,64,4,64,99,21102,1,27,1,21102,1,915,0,1105,1,922,21201,1,28510,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,22102,1,1,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,21202,-2,1,-2,109,-3,2106,0,0 diff --git a/readme.org b/readme.org deleted file mode 100644 index c674de4..0000000 --- a/readme.org +++ /dev/null @@ -1,26 +0,0 @@ -* Advent of Code 2019 - -** Personal challenge - -Try to keep the solution pure. Only main can do IO things, like return -different results when it's called differently. The rest of the -program should only be pure expressions. - -** Optimizations - -- Limit the use of statements. Try to use expressions instead, or move - the statement out to a function. - -** Findings - -- Having iterators that you can't clone (like stdin) makes certain - things difficult. Eg, doing part 1 and 2 together. -- Using "new type" structs can be a pain. derive_more crate made most - of that pain go away. -- With immutable types, 'reset the machine to try again' type - constraints were handled for free. This made many later puzzles easier. -- The 'no statement' constraint meant that some functions ended up - nested in a way that makes it harder to name and read. -- The persistent data structures don't integrate with Rayon iterators. -- Easier to test subsets, but harder to inspect and audit runtime behaviour. -- Although it isn't frequently used, Rust supports functions inside functions. diff --git a/src/bin/day_1.rs b/src/bin/day_1.rs deleted file mode 100644 index 572d287..0000000 --- a/src/bin/day_1.rs +++ /dev/null @@ -1,93 +0,0 @@ -use derive_more; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::process; - -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 1: The Tyranny of the Rocket Equation")] -/// Calculates the fuel needed for your rocket to save Santa. -/// -/// The weight of each module is read from stdin, one module weight -/// per line. See https://adventofcode.com/2019/day/1 for details. -struct Opt { - /// Includes the weight of fuel - #[structopt(short = "i", long = "include-fuel-weight")] - include_fuel_weight: bool, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let input = stdin.lock().lines().map(|l| match l { - Ok(s) => match s.parse::() { - Ok(module) => module, - Err(e) => { - eprintln!("Invalid input \"{}\": {}", s, e); - process::exit(1); - } - }, - Err(e) => { - eprintln!("Error reading input: {}", e); - process::exit(1); - } - }); - - println!("{}", fuel_required(input, opt.include_fuel_weight)) -} - -fn fuel_required(it: impl Iterator, include_fuel_weight: bool) -> Fuel { - it.map(if include_fuel_weight { - Module::fuel_including_fuel_weight - } else { - Module::fuel_excluding_fuel_weight - }) - .sum() -} - -#[derive(Debug, derive_more::FromStr, Clone, Copy)] -struct Module { - weight: Weight, -} - -impl Module { - fn fuel_excluding_fuel_weight(self) -> Fuel { - self.weight.required_fuel() - } - - fn fuel_including_fuel_weight(self) -> Fuel { - iter::successors(Some(self.weight.required_fuel()), |fuel| { - if fuel.is_zero() { - None - } else { - Some(fuel.weight().required_fuel()) - } - }) - .sum() - } -} - -#[derive(Debug, derive_more::FromStr, Clone, Copy)] -struct Weight(u32); - -impl Weight { - fn required_fuel(self) -> Fuel { - Fuel((self.0 / 3).saturating_sub(2)) - } -} - -#[derive(Debug, derive_more::Add, derive_more::Sum, Clone, Copy, derive_more::Display)] -struct Fuel(u32); - -impl Fuel { - fn weight(self) -> Weight { - Weight(self.0) - } - - fn is_zero(self) -> bool { - self.0 == 0 - } -} diff --git a/src/bin/day_10.rs b/src/bin/day_10.rs deleted file mode 100644 index f25c3d2..0000000 --- a/src/bin/day_10.rs +++ /dev/null @@ -1,158 +0,0 @@ -use aoc2019::*; -use std::io; -use std::io::prelude::*; -use std::iter::FromIterator; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 10: Monitoring Station")] -/// Finds the asteroid with the best view of the other asteroids. If -/// an n is provided, then it will print the nth asteroid destroyed by -/// a laser from the asteroid with the best view. Otherwise, it will -/// print the number of asteroids visible. -/// -/// Takes a map of asteroids in on stdin. -/// -/// See https://adventofcode.com/2019/day/10 for details. -struct Opt { - /// indexed from 0 - #[structopt(short = "n")] - n: Option, -} - -fn main() { - let opt = Opt::from_args(); - let stdin = io::stdin(); - let map: AsteroidMap = stdin - .lock() - .lines() - .map(|l| exit_on_failed_assertion(l, "Error reading input")) - .collect(); - - match opt.n { - Some(n) => println!("{:?}", map.nth_destroyed_asteroid(n)), - None => println!("{}", map.best_asteroid_line_of_sight_count()), - }; -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -#[derive(Debug)] -struct AsteroidMap { - asteroids: Vec, -} - -impl FromIterator for AsteroidMap { - fn from_iter>(iter: T) -> Self { - AsteroidMap { - asteroids: iter - .into_iter() - .enumerate() - .flat_map(move |(y, line)| { - line.chars() - .enumerate() - .map(move |(x, c)| (x, y, c)) - .collect::>() - }) - .filter(|(_x, _y, c)| *c == '#') - .map(|(x, y, _x)| Asteroid { - x: x as i32, - y: y as i32, - }) - .collect(), - } - } -} - -impl AsteroidMap { - fn best_asteroid_line_of_sight_count(&self) -> usize { - self.optimal_view_asteroid() - .map(|a| self.count_visible_from(&a)) - .unwrap_or(0) - } - - fn nth_destroyed_asteroid(&self, n: usize) -> Option { - self.optimal_view_asteroid() - .and_then(|source| self.nth_destroyed_asteroid_from(&source, n)) - } - - fn nth_destroyed_asteroid_from(&self, source: &Asteroid, n: usize) -> Option { - if self.asteroids.len() - 1 < n { - None - } else if self.count_visible_from(source) >= n { - sort_by_key( - self.asteroids - .iter() - .filter(|b| self.has_line_of_sight(source, b)), - |b| (source.angle_to(b) * 100000.) as i32, - ) - .nth(n) - .cloned() - } else { - self.remove_visible_to(source) - .nth_destroyed_asteroid_from(source, n - self.count_visible_from(source)) - } - } - - fn optimal_view_asteroid(&self) -> Option { - self.asteroids - .iter() - .max_by_key(|a| self.count_visible_from(a)) - .cloned() - } - - fn count_visible_from(&self, a: &Asteroid) -> usize { - self.asteroids - .iter() - .filter(|b| a != *b && self.has_line_of_sight(a, b)) - .count() - } - - fn remove_visible_to(&self, source: &Asteroid) -> AsteroidMap { - AsteroidMap { - asteroids: self - .asteroids - .iter() - .filter(|b| self.has_line_of_sight(source, b)) - .cloned() - .collect(), - } - } - - fn has_line_of_sight(&self, a: &Asteroid, b: &Asteroid) -> bool { - a != b - && !self.asteroids.iter().any(|c| { - a != c - && b != c - && a.angle_to(b) == a.angle_to(c) - && a.distance_squared(b) > a.distance_squared(c) - }) - } -} - -#[derive(Debug, Clone, PartialEq, Eq)] -struct Asteroid { - x: i32, - y: i32, -} - -impl Asteroid { - fn angle_to(&self, other: &Asteroid) -> f32 { - ((self.x as f32 - other.x as f32).atan2(other.y as f32 - self.y as f32) - + std::f32::consts::PI) - % (2. * std::f32::consts::PI) - } - - fn distance_squared(&self, other: &Asteroid) -> i32 { - (self.x - other.x).pow(2) + (self.y - other.y).pow(2) - } -} diff --git a/src/bin/day_11.rs b/src/bin/day_11.rs deleted file mode 100644 index da3e1fd..0000000 --- a/src/bin/day_11.rs +++ /dev/null @@ -1,205 +0,0 @@ -use aoc2019::*; -use rpds::list; -use rpds::list::List; -use rpds::RedBlackTreeMap; -use std::fmt; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 11: Space Police")] -/// Calculates how many blocks a painting robot would paint. -/// -/// Takes the program to run on the robot in on stdin. -/// -/// See https://adventofcode.com/2019/day/11 for details. -struct Opt { - /// debug mode prints the size of the painted area on a black background - #[structopt(short = "d", long = "debug")] - debug: bool, -} - -fn main() { - let opt = Opt::from_args(); - let stdin = io::stdin(); - 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::(); - - let finished_robot = exit_on_failed_assertion( - Robot::new(program, !opt.debug).execute(), - "Robot encountered an error", - ); - if opt.debug { - println!("{}", finished_robot.canvas.size()); - } else { - println!("{}", finished_robot); - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -#[derive(Debug, Clone)] -struct Robot { - program: IntcodeProgram, - position: (i32, i32), - facing: Direction, - canvas: RedBlackTreeMap<(i32, i32), bool>, - background: bool, -} - -impl fmt::Display for Robot { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (self.min_white_y()..=self.max_white_y()) - .map(move |y| { - (self.min_white_x()..=self.max_white_x()) - .map(move |x| (x, y)) - .map(|coord| self.canvas.get(&coord).cloned().unwrap_or(self.background)) - .map(|c| write!(f, "{}", if c { '#' } else { ' ' })) - .collect::() - .and_then(|_| writeln!(f, "")) - }) - .collect() - } -} - -#[derive(Debug, Clone)] -enum Direction { - Up, - Down, - Left, - Right, -} - -impl Robot { - fn new(program: IntcodeProgram, background: bool) -> Robot { - Robot { - program: program.run_to_termination_or_input(), - position: (0, 0), - facing: Direction::Up, - canvas: RedBlackTreeMap::new(), - background, - } - } - - fn execute(&self) -> Result { - iter::successors(Some(self.clone()), |robot| Some(robot.next())) - .find(|robot| { - robot.program.error.is_some() - || (robot.program.halted && robot.program.output.is_empty()) - }) - .unwrap() // infinite iterator won't terminate unless this is Some - .as_result() - } - - fn as_result(&self) -> Result { - match self.program.error { - Some(ref error) => Err(error.clone()), - None => Ok(self.clone()), - } - } - - fn next(&self) -> Robot { - match ( - self.program.output.get(0).map(intcode_to_bool), - self.program.output.get(1).map(intcode_to_bool), - ) { - (Some(paint), Some(rot)) => Robot { - program: self - .program - .with_cleared_output() - .with_input(list![bool_to_intcode( - self.canvas - .get(&self.facing.rotate(rot).move_position(self.position)) - .cloned() - .unwrap_or(self.background), - )]) - .run_to_termination_or_input(), - position: self.facing.rotate(rot).move_position(self.position), - facing: self.facing.rotate(rot), - canvas: self.canvas.insert(self.position, paint), - background: self.background, - }, - _ => Robot { - program: self - .program - .with_input(list![bool_to_intcode( - self.canvas - .get(&self.position) - .cloned() - .unwrap_or(self.background), - )]) - .run_to_termination_or_input(), - ..self.clone() - }, - } - } - - fn min_white_x(&self) -> i32 { - self.white_blocks().map(|(x, _y)| x).min().unwrap_or(0) - } - fn min_white_y(&self) -> i32 { - self.white_blocks().map(|(_x, y)| y).min().unwrap_or(0) - } - fn max_white_x(&self) -> i32 { - self.white_blocks().map(|(x, _y)| x).max().unwrap_or(0) - } - fn max_white_y(&self) -> i32 { - self.white_blocks().map(|(_x, y)| y).max().unwrap_or(0) - } - - fn white_blocks<'a>(&'a self) -> impl 'a + Iterator { - self.canvas - .iter() - .filter(|(_, val)| **val) - .map(|(coord, _)| coord) - .cloned() - } -} - -impl Direction { - fn rotate(&self, clockwise: bool) -> Direction { - use Direction::*; - - if clockwise { - match self { - Up => Right, - Right => Down, - Down => Left, - Left => Up, - } - } else { - match self { - Up => Left, - Left => Down, - Down => Right, - Right => Up, - } - } - } - - fn move_position(&self, position: (i32, i32)) -> (i32, i32) { - use Direction::*; - match self { - Up => (position.0, position.1 + 1), - Down => (position.0, position.1 - 1), - Left => (position.0 - 1, position.1), - Right => (position.0 + 1, position.1), - } - } -} diff --git a/src/bin/day_12.rs b/src/bin/day_12.rs deleted file mode 100644 index 7e42f4c..0000000 --- a/src/bin/day_12.rs +++ /dev/null @@ -1,205 +0,0 @@ -use std::io; -use std::io::prelude::*; -use std::iter; -use std::num::ParseIntError; -use std::ops; -use std::process; -use std::str::FromStr; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 12: The N-Body Problem")] -/// Simulates N bodies, physically interacting -/// -/// See https://adventofcode.com/2019/day/12 for details. -struct Opt { - #[structopt(short = "n")] - n: Option, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let planets: Vec = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid planet")) - .collect(); - - match opt.n { - Some(n) => println!("{}", energy(simulate_planets_n_iterations(planets, n))), - None => println!("{}", simulate_planets_to_duplicate(planets)), - }; -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -fn energy(planets: Vec) -> i32 { - planets.into_iter().map(|p| p.energy()).sum() -} - -fn simulate_planets_n_iterations(planets: Vec, n: u64) -> Vec { - simulate_planets_iter(planets) - .find(|(i, _)| *i == n) - .unwrap() - .1 -} - -fn simulate_planets_to_duplicate(planets: Vec) -> u64 { - lowest_common_multiple( - simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_x(o)), - simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_y(o)), - simulate_planets_to_duplicate_1d(planets.clone(), |(p, o)| p.equal_z(o)), - ) -} - -fn simulate_planets_to_duplicate_1d( - planets: Vec, - eq: impl FnMut((&Planet, &Planet)) -> bool + Copy, -) -> u64 { - simulate_planets_iter(planets.clone()) - .skip(1) - .find(|(_i, ps)| ps.iter().zip(planets.iter()).all(eq)) - .unwrap() - .0 -} - -fn lowest_common_multiple(x: u64, y: u64, z: u64) -> u64 { - (1..) - .map(|i| x * i) - .find(|mx| multiples(y, *mx) && multiples(z, *mx)) - .unwrap() -} - -fn multiples(x: u64, target: u64) -> bool { - target % x == 0 -} - -fn simulate_planets_iter(planets: Vec) -> impl Iterator)> { - iter::successors(Some((0, planets.clone())), |(i, planets)| { - Some((i + 1, simulate_planets(planets.clone()))) - }) -} - -fn simulate_planets(planets: Vec) -> Vec { - simulate_velocity(simulate_gravity(planets)) -} - -fn simulate_gravity(planets: Vec) -> Vec { - planets - .iter() - .map(|p| Planet { - pos: p.pos.clone(), - vel: planets - .iter() - .filter(|o| p != *o) - .map(|o| p.acc(o)) - .fold(p.vel, |acc, next| acc + next), - }) - .collect() -} - -fn simulate_velocity(planets: Vec) -> Vec { - planets - .into_iter() - .map(|p| Planet { - pos: p.pos + p.vel, - vel: p.vel, - }) - .collect() -} - -#[derive(Debug, Default, Clone, PartialEq)] -struct Planet { - pos: Vec3d, - vel: Vec3d, -} - -#[derive(Debug, Default, Clone, Copy, PartialEq)] -struct Vec3d { - x: i32, - y: i32, - z: i32, -} - -impl FromStr for Planet { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result { - s.replace(|c| "<>xyz= ".contains(c), "") - .split(',') - .map(|i| i.parse::()) - .collect::, _>>() - .and_then(|v| match &v[..] { - [x, y, z] => Ok(Planet { - pos: Vec3d { - x: *x, - y: *y, - z: *z, - }, - vel: Vec3d::default(), - }), - _ => "wrong number of fields" - .parse::() - .map(|_x| Planet::default()), - }) - } -} - -impl Planet { - fn acc(&self, other: &Planet) -> Vec3d { - Vec3d { - x: gravity(self.pos.x, other.pos.x), - y: gravity(self.pos.y, other.pos.y), - z: gravity(self.pos.z, other.pos.z), - } - } - - fn energy(&self) -> i32 { - (self.pos.x.abs() + self.pos.y.abs() + self.pos.z.abs()) - * (self.vel.x.abs() + self.vel.y.abs() + self.vel.z.abs()) - } - - fn equal_x(&self, other: &Planet) -> bool { - self.pos.x == other.pos.x && self.vel.x == other.vel.x - } - - fn equal_y(&self, other: &Planet) -> bool { - self.pos.y == other.pos.y && self.vel.y == other.vel.y - } - - fn equal_z(&self, other: &Planet) -> bool { - self.pos.z == other.pos.z && self.vel.z == other.vel.z - } -} - -fn gravity(this: i32, that: i32) -> i32 { - if that > this { - 1 - } else if this > that { - -1 - } else { - 0 - } -} - -impl ops::Add for Vec3d { - type Output = Vec3d; - fn add(self, rhs: Vec3d) -> Self::Output { - Vec3d { - x: self.x + rhs.x, - y: self.y + rhs.y, - z: self.z + rhs.z, - } - } -} diff --git a/src/bin/day_13.rs b/src/bin/day_13.rs deleted file mode 100644 index ac1c478..0000000 --- a/src/bin/day_13.rs +++ /dev/null @@ -1,149 +0,0 @@ -use aoc2019::*; -use rpds::list; -use rpds::list::List; -use rpds::vector::Vector; -use rpds::RedBlackTreeMap; -use std::cmp::Ordering; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 13: Care Package")] -/// Executes an Intcode game -/// -/// The program is read from stdin as a series of comma-separated -/// values. Newlines are ignored. -/// -/// See https://adventofcode.com/2019/day/13 for details. -struct Opt { - #[structopt(short = "q", long = "quarters")] - quarters: 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.quarters { - Some(quarters) => { - let result = score_on_won_game(program.with_mem_0(quarters)); - println!("{}", result); - } - None => { - let result = exit_on_failed_assertion(program.execute(), "Program errored"); - println!("{}", count_blocks(&result)); - } - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -#[derive(Default, Clone)] -struct Screen { - screen: RedBlackTreeMap<(Intcode, Intcode), Intcode>, - previous_ball: (Intcode, Intcode), - ball: (Intcode, Intcode), - paddle: (Intcode, Intcode), - score: Intcode, -} - -impl Screen { - fn render(output: &Vector) -> Screen { - (0..output.len() / 3) - .map(|i| i * 3) - .map(|i| { - ( - output[i].clone(), - output[i + 1].clone(), - output[i + 2].clone(), - ) - }) - .fold(Screen::default(), |acc, (x, y, tile)| { - if x == Intcode::from(-1) && y == Intcode::from(0) { - Screen { score: tile, ..acc } - } else if tile == Intcode::from(4) { - Screen { - ball: (x, y), - previous_ball: acc.ball, - ..acc - } - } else if tile == Intcode::from(3) { - Screen { - paddle: (x.clone(), y.clone()), - screen: acc.screen.insert((x, y), tile), - ..acc - } - } else if tile == Intcode::from(0) { - Screen { - screen: acc.screen.remove(&(x, y)), - ..acc - } - } else { - Screen { - screen: acc.screen.insert((x, y), tile), - ..acc - } - } - }) - } - - fn paddle_required_direction(&self) -> Intcode { - match self.paddle.0.cmp(&self.ball.0) { - Ordering::Less => Intcode::from(1), - Ordering::Equal => Intcode::from(0), - Ordering::Greater => Intcode::from(-1), - } - } -} - -fn count_blocks(output: &Vector) -> usize { - Screen::render(output) - .screen - .values() - .filter(|val| **val == Intcode::from(2)) - .count() -} - -fn score_on_won_game(program: IntcodeProgram) -> Intcode { - Screen::render( - &iter::successors(Some(program.run_to_termination_or_input()), |program| { - Some(next_game_state(program.clone())) - }) - .take_while(|program| !program.halted) - .find(|program| count_blocks(&program.output) == 0) - .unwrap() - .output, - ) - .score -} - -fn next_game_state(program: IntcodeProgram) -> IntcodeProgram { - program_with_next_input(program.run_to_termination_or_input()) -} - -fn program_with_next_input(program: IntcodeProgram) -> IntcodeProgram { - program.with_input(list![next_input(&program.output)]) -} - -fn next_input(output: &Vector) -> Intcode { - Screen::render(output).paddle_required_direction() -} diff --git a/src/bin/day_14.rs b/src/bin/day_14.rs deleted file mode 100644 index 0532f5f..0000000 --- a/src/bin/day_14.rs +++ /dev/null @@ -1,221 +0,0 @@ -use rpds::map::red_black_tree_map::RedBlackTreeMap; -use rpds::rbt_map; -use rpds::vector::Vector; -use std::fmt; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::process; -use std::str::FromStr; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 14: Space Stoichiometry")] -/// Finds how much ore you need to produce one fuel. -/// -/// Recipes are passed in on stdin, one per line. -/// -/// See https://adventofcode.com/2019/day/14 for details. -struct Opt { - #[structopt(long = "available-ore")] - available_ore: Option, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let recipes = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid recipe")) - .collect::>(); - - match opt.available_ore { - Some(ore) => println!("{}", max_fuel_production(ore, &recipes)), - None => println!("{}", Desires::new(1).min_ore_required(&recipes)), - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -fn max_fuel_production(ore_max: i64, recipes: &[Recipe]) -> i64 { - binary_search_max_fuel_production( - ore_max / Desires::new(1).min_ore_required(&recipes), - 2 * ore_max / Desires::new(1).min_ore_required(&recipes), - ore_max, - recipes, - ) -} - -fn binary_search_max_fuel_production( - fuel_min: i64, - fuel_max: i64, - ore_max: i64, - recipes: &[Recipe], -) -> i64 { - if fuel_max - fuel_min <= 1 { - fuel_min - } else if Desires::new((fuel_min + fuel_max) / 2).min_ore_required(recipes) <= ore_max { - binary_search_max_fuel_production((fuel_min + fuel_max) / 2, fuel_max, ore_max, recipes) - } else { - binary_search_max_fuel_production(fuel_min, (fuel_min + fuel_max) / 2, ore_max, recipes) - } -} - -#[derive(Debug, Clone)] -struct Recipe { - ingredients: Vector, - output: Chemical, -} - -#[derive(Default, Debug, Clone)] -struct Chemical { - name: String, - quantity: i64, -} - -impl FromStr for Recipe { - type Err = ParseErr; - fn from_str(s: &str) -> Result { - // 2 XSNKB, 15 ZVMCB, 3 KDFNZ => 2 RFLX - s.replace(" => ", "=") - .replace(", ", ",") - .split(|c| c == ',' || c == '=') - .map(|chem| chem.parse::()) - .collect::, ParseErr>>() - .map(|chemicals| Recipe { - ingredients: chemicals - .drop_last() - .expect("Assertion failed: line did not have any chemicals"), - output: chemicals - .last() - .cloned() - .expect("Assertion failed: line did not have any chemicals"), - }) - } -} - -impl Recipe { - fn required_scale(&self, desired_quantity: i64) -> i64 { - (desired_quantity + self.output.quantity - 1) / self.output.quantity - } -} - -impl FromStr for Chemical { - type Err = ParseErr; - fn from_str(s: &str) -> Result { - // 1 FUEL - match s.split(' ').collect::>()[..] { - [quantity, name] => quantity - .parse::() - .map_err(|_| ParseErr) - .map(|q| Chemical { - name: name.to_string(), - quantity: q, - }), - _ => Err(ParseErr), - } - } -} - -impl Chemical { - fn scale(&self, scale: i64) -> Chemical { - Chemical { - name: self.name.clone(), - quantity: self.quantity * scale, - } - } -} - -#[derive(Debug, Clone, Copy)] -struct ParseErr; - -impl fmt::Display for ParseErr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Error parsing input") - } -} - -impl std::error::Error for ParseErr {} - -#[derive(Debug, Clone)] -struct Desires { - chemicals: RedBlackTreeMap, -} - -impl Desires { - fn new(fuel: i64) -> Desires { - Desires { - chemicals: rbt_map!["FUEL".to_string() => fuel, "ORE".to_string() => 0], - } - } - - fn min_ore_required(&self, recipes: &[Recipe]) -> i64 { - iter::successors(Some(self.clone()), |prev| Some(prev.next(recipes))) - .find(|desires| desires.is_only_ore()) - .unwrap() - .chemicals - .get("ORE") - .cloned() - .unwrap() - } - - fn is_only_ore(&self) -> bool { - !self - .chemicals - .iter() - .any(|(name, quantity)| *quantity > 0 && name != "ORE") - } - - fn next(&self, recipes: &[Recipe]) -> Desires { - self.chemicals - .iter() - .find(|(name, quantity)| **quantity > 0 && *name != "ORE") - .map(|(mixing, quantity)| { - self.with_mixed_recipe( - recipes - .iter() - .find(|recipe| recipe.output.name == *mixing) - .expect("Required chemical without a recipe"), - *quantity, - ) - }) - .unwrap_or(self.clone()) - } - - fn with_mixed_recipe(&self, recipe: &Recipe, desired_quantity: i64) -> Desires { - recipe.ingredients.iter().fold( - self.with_chemical( - recipe - .output - .scale(-1 * recipe.required_scale(desired_quantity)), - ), - |acc, next_ingredient| { - acc.with_chemical(next_ingredient.scale(recipe.required_scale(desired_quantity))) - }, - ) - } - - fn with_chemical(&self, chemical: Chemical) -> Desires { - Desires { - chemicals: match self.chemicals.get(&chemical.name) { - Some(existing_quantity) => self - .chemicals - .insert(chemical.name.clone(), existing_quantity + chemical.quantity), - None => self - .chemicals - .insert(chemical.name.clone(), chemical.quantity), - }, - } - } -} diff --git a/src/bin/day_15.rs b/src/bin/day_15.rs deleted file mode 100644 index b2205bb..0000000 --- a/src/bin/day_15.rs +++ /dev/null @@ -1,183 +0,0 @@ -use aoc2019::*; -use rpds::list; -use rpds::list::List; -use rpds::rbt_set; -use rpds::set::red_black_tree_set::RedBlackTreeSet; -use rpds::vector; -use rpds::vector::Vector; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 15: Oxygen System")] -/// Executes an Intcode robot that's searching a map. Prints the -/// time taken for oxygen to propagate to the whole area. -/// -/// See https://adventofcode.com/2019/day/15 for details. -struct Opt { - /// Run in 'find' mode, find the oxygen tank but don't see how long it takes the oxygen to propagate - #[structopt(short = "f")] - find: 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::(), "Invalid number")) - .collect::(); - - if opt.find { - println!("{}", shortest_distance(program)); - } else { - println!("{}", max_depth_from_oxygen(program)); - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -fn shortest_distance(program: IntcodeProgram) -> usize { - iter::successors( - Some(( - rbt_set![(0, 0)], - vector![((0, 0), program.run_to_termination_or_input())], - )), - |(visited, programs)| { - Some(next_depth_states( - visited.clone(), - next_program_states(programs, visited), - )) - }, - ) - .enumerate() - .find(|(_i, (_visited, programs))| { - programs - .iter() - .any(|(_location, program)| program.output == vector![2.into()]) - }) - .unwrap() - .0 -} - -fn max_depth_from_oxygen(program: IntcodeProgram) -> usize { - max_depth( - iter::successors( - Some(( - rbt_set![(0, 0)], - vector![((0, 0), program.run_to_termination_or_input())], - )), - |(visited, programs)| { - Some(next_depth_states( - visited.clone(), - next_program_states(programs, visited), - )) - }, - ) - .find(|(_visited, programs)| { - programs - .iter() - .any(|(_location, program)| program.output == vector![2.into()]) - }) - .unwrap() - .1 - .iter() - .find(|(_location, program)| program.output == vector![2.into()]) - .cloned() - .unwrap() - .1, - ) -} - -fn max_depth(program: IntcodeProgram) -> usize { - iter::successors( - Some(( - rbt_set![(0, 0)], - vector![((0, 0), program.run_to_termination_or_input())], - )), - |(visited, programs)| { - Some(next_depth_states( - visited.clone(), - next_program_states(programs, visited), - )) - }, - ) - .take_while(|(_visited, programs)| programs.len() > 0) - .count() - - 1 -} - -fn inputs() -> [((i32, i32), Intcode); 4] { - [ - ((0, 1), Intcode::from(1)), - ((0, -1), Intcode::from(2)), - ((1, 0), Intcode::from(3)), - ((-1, 0), Intcode::from(4)), - ] -} - -fn next_program_states( - programs: &Vector<((i32, i32), IntcodeProgram)>, - visited: &RedBlackTreeSet<(i32, i32)>, -) -> Vector<((i32, i32), IntcodeProgram)> { - let inputs = inputs(); - programs - .iter() - .flat_map(|(location, program)| { - inputs.iter().map(move |(vec, input)| { - ( - (location.0 + vec.0, location.1 + vec.1), - program - .with_cleared_output() - .with_input(list![input.clone()]) - .run_to_termination_or_input(), - ) - }) - }) - .filter(|(location, program)| { - !visited.contains(location) && program.output != vector![0.into()] - }) - .collect() -} - -fn next_depth_states( - previous_visited: RedBlackTreeSet<(i32, i32)>, - programs: Vector<((i32, i32), IntcodeProgram)>, -) -> ( - RedBlackTreeSet<(i32, i32)>, - Vector<((i32, i32), IntcodeProgram)>, -) { - ( - programs - .iter() - .fold(previous_visited, |acc, (next, _)| acc.insert(*next)), - dedup_locations(programs), - ) -} - -fn dedup_locations( - programs: Vector<((i32, i32), IntcodeProgram)>, -) -> Vector<((i32, i32), IntcodeProgram)> { - programs.iter().fold(Vector::new(), |acc, next| { - if acc.iter().any(|(loc, _)| *loc == next.0) { - acc - } else { - acc.push_back(next.clone()) - } - }) -} diff --git a/src/bin/day_16.rs b/src/bin/day_16.rs deleted file mode 100644 index aa53127..0000000 --- a/src/bin/day_16.rs +++ /dev/null @@ -1,112 +0,0 @@ -use rayon::prelude::*; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::num::ParseIntError; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 16: Flawed Frequency Transmission")] -/// Performs the flawed frequency transform of a number. -/// -/// See https://adventofcode.com/2019/day/16 for details. -struct Opt { - /// the offset after which you start reading output - #[structopt(short = "o", long = "offset", default_value = "0")] - offset: usize, - input_repeats: usize, - fft_repeats: usize, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .map(|x| exit_on_failed_assertion(parse(&x), "Input was not a valid recipe")) - .for_each(|input| { - println!( - "{}", - transform(input, opt.input_repeats, opt.fft_repeats, opt.offset) - .into_iter() - .map(|c| c.to_string()) - .collect::() - ); - }); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -fn parse(s: &str) -> Result, ParseIntError> { - s.chars().map(|c| c.to_string().parse::()).collect() -} - -fn transform(input: Vec, input_repeats: usize, fft_repeats: usize, offset: usize) -> Vec { - iter::successors( - Some( - input - .iter() - .cycle() - .take(input.len() * input_repeats) - .cloned() - .collect::>(), - ), - |input| Some(next_phase(input, offset)), - ) - .nth(fft_repeats) - .unwrap() - .into_iter() - .skip(offset) - .take(8) - .collect() -} - -fn next_phase(input: &Vec, offset: usize) -> Vec { - if offset > input.len() / 2 { - (0..input.len()) - .into_par_iter() - .map(|digit| { - if digit < offset { - 0 - } else { - input.iter().skip(digit).sum::().abs() % 10 - } - }) - .collect() - } else { - (0..input.len()) - .into_par_iter() - .map(|digit| { - input - .iter() - .zip(pattern(digit)) - .map(|(x, y)| x * y) - .sum::() - .abs() - % 10 - }) - .collect() - } -} - -fn pattern(digit: usize) -> impl Iterator { - iter::repeat(0) - .take(digit + 1) - .chain(iter::repeat(1).take(digit + 1)) - .chain(iter::repeat(0).take(digit + 1)) - .chain(iter::repeat(-1).take(digit + 1)) - .cycle() - .skip(1) -} diff --git a/src/bin/day_17.rs b/src/bin/day_17.rs deleted file mode 100644 index e85373c..0000000 --- a/src/bin/day_17.rs +++ /dev/null @@ -1,78 +0,0 @@ -use aoc2019::*; -use std::io; -use std::io::prelude::*; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 17: Set and Forget")] -/// Pilots a vacuum robot around on a scaffold. What could go wrong? -/// -/// See https://adventofcode.com/2019/day/17 for details. -struct Opt { - /// Draw the map and exit - #[structopt(short = "d")] - draw_map: 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::(), "Invalid number")) - .collect::(); - - let result = exit_on_failed_assertion( - if opt.draw_map { - program.execute() - } else { - // L,12,L,8,R,10,R,10,L,6,L,4,L,12,L,12,L,8,R,10,R,10,L,6,L,4,L,12,R,10,L,8,L,4,R,10,L,6,L,4,L,12,L,12,L,8,R,10,R,10,R,10,L,8,L,4,R,10,L,6,L,4,L,12,R,10,L,8,L,4,R,10 - // | | || - - let input = vec![ - "A,B,A,B,C,B,A,C,B,C\n", - "L,12,L,8,R,10,R,10\n", - "L,6,L,4,L,12\n", - "R,10,L,8,L,4,R,10\n", - "y\n", - ]; - program - .with_mem_0(Intcode::from(2)) - .with_input( - input - .iter() - .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) - .collect(), - ) - .execute() - }, - "Program failed", - ); - - println!( - "{}", - result - .drop_last() - .unwrap() - .iter() - .flat_map(|c| c.to_signed_bytes_be()) - .map(|c| c as char) - .collect::() - ); - println!("{}", result.last().unwrap()); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} diff --git a/src/bin/day_18.rs b/src/bin/day_18.rs deleted file mode 100644 index 255baa0..0000000 --- a/src/bin/day_18.rs +++ /dev/null @@ -1,365 +0,0 @@ -use rpds::rbt_set; -use rpds::vector::Vector; -use rpds::RedBlackTreeMap; -use rpds::RedBlackTreeSet; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::iter::FromIterator; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 18: Many-Worlds Interpretation")] -/// Finds the shortest path through a maze with keys -/// -/// See https://adventofcode.com/2019/day/18 for details. -struct Opt {} - -fn main() { - let stdin = io::stdin(); - let _opt = Opt::from_args(); - - let maze: Maze = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .collect(); - - println!("{}", maze.shortest_route()); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -struct Maze { - blocks: Vec>, - start: BoardState, - keys: KeySet, -} - -impl FromIterator for Maze { - fn from_iter>(iter: T) -> Self { - Maze::from_blocks( - iter.into_iter() - .map(|line| line.chars().collect()) - .collect(), - ) - } -} - -impl Maze { - fn from_blocks(blocks: Vec>) -> Maze { - Maze { - start: BoardState { - robots: blocks - .iter() - .enumerate() - .flat_map(|(y, line)| { - line.iter() - .enumerate() - .filter(|(_x, ch)| **ch == '@') - .map(move |(x, _ch)| Location { x, y }) - }) - .collect(), - keys: KeySet::default(), - }, - keys: blocks - .iter() - .flat_map(|line| line.iter()) - .fold(KeySet::default(), |acc, next| acc.add_key(*next)), - blocks, - } - } - - fn block_at(&self, location: &Location) -> Option { - self.blocks - .get(location.y) - .and_then(|line| line.get(location.x)) - .cloned() - } - - fn shortest_route(&self) -> usize { - iter::successors( - Some(( - ExploredStates::default().insert(&self.start), - rbt_set![self.start.clone()], - )), - |(explored, locations)| { - Some(Maze::next_depth_states( - explored.clone(), - self.next_locations(locations, explored), - )) - }, - ) - // .inspect(|(explored, states)| eprintln!("{:?}", states)) - .take_while(|(_explored, states)| states.size() > 0) - .enumerate() - .find(|(_i, (_explored, states))| states.iter().any(|state| state.keys == self.keys)) - .unwrap() - .0 - } - - fn next_depth_states( - explored: ExploredStates, - locations: RedBlackTreeSet, - ) -> (ExploredStates, RedBlackTreeSet) { - ( - locations - .iter() - .fold(explored, |acc, next| acc.insert(next)), - locations, - ) - } - - fn next_locations( - &self, - locations: &RedBlackTreeSet, - explored: &ExploredStates, - ) -> RedBlackTreeSet { - locations - .iter() - .flat_map(|current| { - (0..current.robots.len()).flat_map(move |i_robot| { - [(-1, 0), (1, 0), (0, -1), (0, 1)] - .iter() - .map(move |(dx, dy)| current.next(i_robot, *dx, *dy)) - .map(move |(state, new_location)| { - self.block_at(&new_location) - .map(|c| state.with_key(c)) - .unwrap_or(state) - }) - }) - }) - .filter(|state| self.is_open(state)) - .filter(|state| !explored.contains(state)) - .collect() - } - - fn is_open(&self, state: &BoardState) -> bool { - state.robots.iter().all(|location| { - self.block_at(location) - .map(|c| Maze::char_is_open(c, state.keys)) - .unwrap_or(false) - }) - } - - fn char_is_open(c: char, keys: KeySet) -> bool { - c != '#' && !keys.door_is_locked(c) - } -} - -#[derive(Default, Debug, Clone)] -struct ExploredStates { - for_key: RedBlackTreeMap, -} - -#[derive(Default, Debug, Clone)] -struct ExploredStatesForKey { - robots: Vector>, -} - -impl ExploredStates { - fn insert(&self, new: &BoardState) -> ExploredStates { - ExploredStates { - for_key: self.for_key.insert( - new.keys.clone(), - self.for_key - .get(&new.keys) - .map(|current| ExploredStatesForKey { - robots: current - .robots - .iter() - .zip(new.robots.iter()) - .map(|(current_explored, robot)| current_explored.insert(robot.clone())) - .collect(), - }) - .unwrap_or_else(|| ExploredStatesForKey { - robots: new - .robots - .iter() - .map(|robot| RedBlackTreeSet::new().insert(robot.clone())) - .collect(), - }), - ), - } - } - - fn contains(&self, state: &BoardState) -> bool { - self.for_key - .get(&state.keys) - .filter(|for_key| { - state - .robots - .iter() - .zip(for_key.robots.iter()) - .all(|(r_state, r_explored)| r_explored.contains(r_state)) - }) - .is_some() - } -} - -#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -struct BoardState { - robots: Vector, - keys: KeySet, -} - -impl BoardState { - fn next(&self, i_robot: usize, dx: isize, dy: isize) -> (BoardState, Location) { - ( - BoardState { - robots: self - .robots - .set(i_robot, self.robots[i_robot].next(dx, dy)) - .unwrap(), - ..self.clone() - }, - self.robots[i_robot].next(dx, dy), - ) - } - - fn with_key(&self, c: char) -> BoardState { - BoardState { - keys: self.keys.add_key(c), - ..self.clone() - } - } -} - -#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -struct Location { - x: usize, - y: usize, -} - -impl Location { - fn next(&self, dx: isize, dy: isize) -> Location { - Location { - x: (self.x as isize + dx) as usize, - y: (self.y as isize + dy) as usize, - } - } -} - -#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -struct KeySet { - bitset: u32, -} - -impl KeySet { - fn add_key(self, key: char) -> KeySet { - KeySet { - bitset: self.bitset | KeySet::key_to_bitset(key), - } - } - - fn door_is_locked(self, door: char) -> bool { - KeySet::door_to_bitset(door) & (!self.bitset) > 0 - } - - fn key_to_bitset(key: char) -> u32 { - if key.is_ascii_alphabetic() && key.is_ascii_lowercase() { - 1 << (key as u8 - b'a') - } else { - 0 - } - } - - fn door_to_bitset(door: char) -> u32 { - if door.is_ascii_alphabetic() && door.is_ascii_uppercase() { - 1 << (door as u8 - b'A') - } else { - 0 - } - } -} - -#[test] -fn doors_are_locked_without_key() { - assert_eq!(true, KeySet::default().door_is_locked('A')) -} - -#[test] -fn doors_are_unlocked_with_key() { - assert_eq!(false, KeySet::default().add_key('a').door_is_locked('A')) -} - -#[test] -fn example_1() { - let maze: Maze = r" -######### -#b.A.@.a# -######### -" - .split('\n') - .map(|s| s.to_string()) - .collect(); - - assert_eq!(maze.shortest_route(), 8); -} - -#[test] -fn example_2() { - let maze: Maze = r" -################# -#i.G..c...e..H.p# -########.######## -#j.A..b...f..D.o# -########@######## -#k.E..a...g..B.n# -########.######## -#l.F..d...h..C.m# -################# -" - .split('\n') - .map(|s| s.to_string()) - .collect(); - - assert_eq!(maze.shortest_route(), 136); -} - -#[test] -fn example_3() { - let maze: Maze = r" -############# -#DcBa.#.GhKl# -#.###@#@#I### -#e#d#####j#k# -###C#@#@###J# -#fEbA.#.FgHi# -############# -" - .split('\n') - .map(|s| s.to_string()) - .collect(); - - assert_eq!(maze.shortest_route(), 32); -} - -#[test] -fn example_4() { - let maze: Maze = r" -############# -#g#f.D#..h#l# -#F###e#E###.# -#dCba@#@BcIJ# -############# -#nK.L@#@G...# -#M###N#H###.# -#o#m..#i#jk.# -############# -" - .split('\n') - .map(|s| s.to_string()) - .collect(); - - assert_eq!(maze.shortest_route(), 74); -} diff --git a/src/bin/day_19.rs b/src/bin/day_19.rs deleted file mode 100644 index 73c8374..0000000 --- a/src/bin/day_19.rs +++ /dev/null @@ -1,102 +0,0 @@ -use aoc2019::*; -use cached::cached_key; -use cached::UnboundCache; -use rpds::list; -use rpds::list::List; -use rpds::vector; -use std::io; -use std::io::prelude::*; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 19: Tractor Beam")] -/// Finds the effective area of a tractor beam in an n x n square, and -/// how far away you need to be to capture Santa's ship. -/// -/// See https://adventofcode.com/2019/day/19 for details. -struct Opt { - /// The size for a diagnostics scan. - #[structopt(long = "diagnostics-size")] - diagnostics_size: Option, - /// The size of Santa's ship - #[structopt(long = "ship-size")] - ship_size: 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::(); - - if let Some(size) = opt.diagnostics_size { - println!("{}", count_active_in_area(program.clone(), 0, 0, size)); - } - if let Some(size) = opt.ship_size { - println!("{:?}", find_closest_ship_space(program, size)) - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -fn count_active_in_area(program: IntcodeProgram, left: usize, top: usize, size: usize) -> usize { - (left..left + size) - .flat_map(|x| (top..top + size).map(move |y| (x, y))) - .filter(|(x, y)| tractor_beam_is_active(program.clone(), *x, *y)) - .count() -} - -fn area_is_all_full(program: IntcodeProgram, left: usize, top: usize, size: usize) -> bool { - // This check with a grid that's aligned to 10 gives an early exit - // for most, that will have the program executions shared. This - // makes the memoized tractor function more effective at cutting - // down on execution, even though you need to do the whole lot - // again to verify if this passes. - (left..left + size) - .flat_map(|x| (top..top + size).map(move |y| (x, y))) - .filter(|(x, y)| x % 10 == 0 && y % 10 == 0) - .all(|(x, y)| tractor_beam_is_active(program.clone(), x, y)) - && (left..left + size) - .flat_map(|x| (top..top + size).map(move |y| (x, y))) - .all(|(x, y)| tractor_beam_is_active(program.clone(), x, y)) -} - -fn find_closest_ship_space(program: IntcodeProgram, size: usize) -> (usize, usize) { - (0..) - .flat_map(|radius| { - (0..radius) - .flat_map(move |x| (0..radius).map(move |y| (x, y))) - .filter(move |(x, y)| { - (radius - 1) * (radius - 1) < x * x + y * y && x * x + y * y <= radius * radius - }) - }) - .find(|(x, y)| area_is_all_full(program.clone(), *x, *y, size)) - .unwrap() -} - -cached_key! { - TRACTOR_BEAM_IS_ACTIVE: UnboundCache<(usize, usize), bool> = UnboundCache::new(); - Key = { (x, y) }; - fn tractor_beam_is_active(program: IntcodeProgram, x: usize, y: usize) -> bool = { - program - .with_input(list![Intcode::from(x), Intcode::from(y)]) - .execute() - == Ok(vector![Intcode::from(1)]) - - } -} diff --git a/src/bin/day_2.rs b/src/bin/day_2.rs deleted file mode 100644 index ba9e189..0000000 --- a/src/bin/day_2.rs +++ /dev/null @@ -1,96 +0,0 @@ -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)) -} diff --git a/src/bin/day_20.rs b/src/bin/day_20.rs deleted file mode 100644 index 953df75..0000000 --- a/src/bin/day_20.rs +++ /dev/null @@ -1,310 +0,0 @@ -use rpds::rbt_set; -use rpds::vector::Vector; -use rpds::RedBlackTreeMap; -use rpds::RedBlackTreeSet; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::iter::FromIterator; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 20: Donut Maze")] -/// Finds the shortest path through a maze with portals. -/// -/// See https://adventofcode.com/2019/day/20 for details. -struct Opt { - /// include the rule that going through portals changes your depth - #[structopt(short = "d")] - include_depth: bool, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let maze = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .collect::() - .build(); - - println!("{}", maze.shortest_route(opt.include_depth)); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -struct MazeBuilder { - map: Vector>, -} - -impl FromIterator for MazeBuilder { - fn from_iter>(iter: T) -> Self { - MazeBuilder { - map: iter - .into_iter() - .map(|line| line.chars().collect()) - .collect(), - } - } -} - -impl MazeBuilder { - fn build(self) -> Maze { - Maze { - walls: self - .map - .iter() - .map(|line| line.iter().map(|ch| *ch != '.').collect()) - .collect(), - portals: self.grouped_portals(), - entrance: self - .all_portals() - .find(|(id, _)| *id == ['A', 'A']) - .unwrap() - .1, - exit: self - .all_portals() - .find(|(id, _)| *id == ['Z', 'Z']) - .unwrap() - .1, - } - } - - fn grouped_portals(&self) -> Vector<(Point, Point)> { - self.all_portals() - .fold( - (Vector::new(), RedBlackTreeMap::new()), - |(matched, unmatched): ( - Vector<(Point, Point)>, - RedBlackTreeMap<[char; 2], Point>, - ), - (next_id, next_p)| match unmatched.get(&next_id) { - Some(pair) => ( - matched.push_back(pair.clone().inside_out( - next_p, - self.map[0].len(), - self.map.len(), - )), - unmatched.remove(&next_id), - ), - None => (matched, unmatched.insert(next_id, next_p)), - }, - ) - .0 - } - - fn all_portals(&self) -> impl Iterator + '_ { - self.horizontal_trailing_portals() - .chain(self.horizontal_leading_portals()) - .chain(self.vertical_trailing_portals()) - .chain(self.vertical_leading_portals()) - } - - fn horizontal_trailing_portals(&self) -> impl Iterator + '_ { - // .XX - (0..self.map.len()) - .flat_map(move |y| (0..self.map[y].len() - 2).map(move |x| Point { x, y })) - .filter(move |p| { - self.map[p.y][p.x] == '.' - && self.map[p.y][p.x + 1].is_alphabetic() - && self.map[p.y][p.x + 2].is_alphabetic() - }) - .map(move |p| ([self.map[p.y][p.x + 1], self.map[p.y][p.x + 2]], p)) - } - - fn horizontal_leading_portals(&self) -> impl Iterator + '_ { - // XX. - (0..self.map.len()) - .flat_map(move |y| (0..self.map[y].len() - 2).map(move |x| Point { x, y })) - .filter(move |p| { - self.map[p.y][p.x + 2] == '.' - && self.map[p.y][p.x + 1].is_alphabetic() - && self.map[p.y][p.x].is_alphabetic() - }) - .map(move |p| { - ( - [self.map[p.y][p.x], self.map[p.y][p.x + 1]], - Point { x: p.x + 2, y: p.y }, - ) - }) - } - - fn vertical_trailing_portals(&self) -> impl Iterator + '_ { - // .XX - (0..self.map[0].len()) - .flat_map(move |x| (0..self.map.len() - 2).map(move |y| Point { x, y })) - .filter(move |p| { - self.map[p.y][p.x] == '.' - && self.map[p.y + 1][p.x].is_alphabetic() - && self.map[p.y + 2][p.x].is_alphabetic() - }) - .map(move |p| ([self.map[p.y + 1][p.x], self.map[p.y + 2][p.x]], p)) - } - - fn vertical_leading_portals(&self) -> impl Iterator + '_ { - // XX. - (0..self.map[0].len()) - .flat_map(move |x| (0..self.map.len() - 2).map(move |y| Point { x, y })) - .filter(move |p| { - self.map[p.y + 2][p.x] == '.' - && self.map[p.y + 1][p.x].is_alphabetic() - && self.map[p.y][p.x].is_alphabetic() - }) - .map(move |p| { - ( - [self.map[p.y][p.x], self.map[p.y + 1][p.x]], - Point { x: p.x, y: p.y + 2 }, - ) - }) - } -} - -#[derive(Debug)] -struct Maze { - walls: Vector>, - portals: Vector<(Point, Point)>, - entrance: Point, // AA - exit: Point, // ZZ -} - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -struct Point { - x: usize, - y: usize, -} - -impl Point { - fn add(&self, x: isize, y: isize) -> Point { - Point { - x: (self.x as isize + x) as usize, - y: (self.y as isize + y) as usize, - } - } - - fn inside_out(self, other: Point, width: usize, height: usize) -> (Point, Point) { - if self.closest_side(width, height) > other.closest_side(width, height) { - (self, other) - } else { - (other, self) - } - } - - fn closest_side(&self, width: usize, height: usize) -> usize { - self.x.min(width - self.x).min(self.y).min(height - self.y) - } -} - -impl Maze { - fn shortest_route(&self, include_depth: bool) -> usize { - iter::successors( - Some(( - rbt_set![(self.entrance.clone(), 0)], - rbt_set![(self.entrance.clone(), 0)], - )), - |(explored, locations)| { - Some(Maze::next_depth_states( - explored.clone(), - self.next_locations(locations, explored, include_depth), - )) - }, - ) - // .inspect(|(explored, states)| eprintln!("{:?}", states)) - .take_while(|(_explored, states)| states.size() > 0) - .enumerate() - .find(|(_i, (_explored, states))| { - states - .iter() - .any(|(p_state, depth)| *p_state == self.exit && (!include_depth || *depth == 0)) - }) - .unwrap() - .0 - } - - fn next_depth_states( - explored: RedBlackTreeSet<(Point, isize)>, - locations: RedBlackTreeSet<(Point, isize)>, - ) -> ( - RedBlackTreeSet<(Point, isize)>, - RedBlackTreeSet<(Point, isize)>, - ) { - ( - locations - .iter() - .fold(explored, |acc, next| acc.insert(next.clone())), - locations, - ) - } - - fn next_locations( - &self, - locations: &RedBlackTreeSet<(Point, isize)>, - explored: &RedBlackTreeSet<(Point, isize)>, - include_depth: bool, - ) -> RedBlackTreeSet<(Point, isize)> { - locations - .iter() - .flat_map(|(p, depth)| { - [(-1, 0), (1, 0), (0, -1), (0, 1)] - .iter() - .map(move |(dx, dy)| (p.add(*dx, *dy), *depth)) - .chain( - self.portals - .iter() - .filter(move |(from, _to)| p == from) - .map(move |(_from, to)| (to.clone(), depth + 1)), - ) - .chain( - self.portals - .iter() - .filter(move |(_to, from)| p == from) - .map(move |(to, _from)| (to.clone(), depth - 1)), - ) - }) - .filter(|(p_next, depth)| { - !self.walls[p_next.y][p_next.x] && (!include_depth || *depth >= 0) - }) - .filter(|state| !explored.contains(state)) - .collect() - } -} - -#[test] -fn portal_maze_example_1() { - let maze: Maze = r" A - A - #######.######### - #######.........# - #######.#######.# - #######.#######.# - #######.#######.# - ##### B ###.# -BC...## C ###.# - ##.## ###.# - ##...DE F ###.# - ##### G ###.# - #########.#####.# -DE..#######...###.# - #.#########.###.# -FG..#########.....# - ###########.##### - Z - Z " - .split('\n') - .map(|s| s.to_string()) - .collect::() - .build(); - - assert_eq!(maze.shortest_route(false), 23); - assert_eq!(maze.shortest_route(true), 26); -} diff --git a/src/bin/day_21.rs b/src/bin/day_21.rs deleted file mode 100644 index 7fa781c..0000000 --- a/src/bin/day_21.rs +++ /dev/null @@ -1,109 +0,0 @@ -use aoc2019::*; -use std::io; -use std::io::prelude::*; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 21: Springdroid Adventure")] -/// Pilots a springdroid around! -/// -/// See https://adventofcode.com/2019/day/21 for details. -struct Opt {} - -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::(); - - let walk_result = exit_on_failed_assertion( - { - let input = vec![ - "NOT T T\n", - "AND A T\n", - "AND B T\n", - "AND C T\n", - "NOT T J\n", - "AND D J\n", - "WALK\n", - ]; - program - .with_input( - input - .iter() - .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) - .collect(), - ) - .execute() - }, - "Program failed", - ); - - println!( - "{}", - walk_result - .drop_last() - .unwrap() - .iter() - .flat_map(|c| c.to_signed_bytes_be()) - .map(|c| c as char) - .collect::() - ); - println!("{}", walk_result.last().unwrap()); - - let run_result = exit_on_failed_assertion( - { - // (!A || !B || !C) && D && (E || H) - let input = vec![ - "OR E J\n", - "OR H J\n", - "AND D J\n", - "NOT T T\n", - "AND A T\n", - "AND B T\n", - "AND C T\n", - "NOT T T\n", - "AND T J\n", - "RUN\n", - ]; - program - .with_input( - input - .iter() - .flat_map(|line| line.chars().map(|c| Intcode::from(c as u8))) - .collect(), - ) - .execute() - }, - "Program failed", - ); - - println!( - "{}", - run_result - .drop_last() - .unwrap() - .iter() - .flat_map(|c| c.to_signed_bytes_be()) - .map(|c| c as char) - .collect::() - ); - println!("{}", run_result.last().unwrap()); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} diff --git a/src/bin/day_22.rs b/src/bin/day_22.rs deleted file mode 100644 index 5b999a6..0000000 --- a/src/bin/day_22.rs +++ /dev/null @@ -1,325 +0,0 @@ -use derive_more::Display; -use num::bigint::BigInt; -use num::traits::identities::Zero; -use num::traits::sign::abs; -use num::traits::Signed; -use std::fmt; -use std::io; -use std::io::prelude::*; -use std::process; -use std::str::FromStr; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 22: Slam Shuffle")] -/// Shuffles some cards. -/// -/// See https://adventofcode.com/2019/day/22 for details. -struct Opt { - /// The size of the deck - deck_size: BigInt, - /// At the end, query the position of card - card: BigInt, - /// Number of repetitions - repetitions: BigInt, - - /// Prints the card in position n, rather than the position of card n - #[structopt(short = "p")] - position_mode: bool, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let instructions = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .map(|x| exit_on_failed_assertion(x.parse::(), "Parse error")) - .collect::>(); - - //eprintln!("{:?}", instructions); - - if opt.position_mode { - println!( - "{}", - instructions - .iter() - .rev() - .fold( - StandardisedInstruction::identity(opt.deck_size.clone()), - |acc, next| acc.then(&(next.clone(), opt.deck_size.clone(), false).into()) - ) - .repeat(opt.repetitions) - .apply(opt.card.clone()) - ); - } else { - println!( - "{}", - instructions - .iter() - .fold( - StandardisedInstruction::identity(opt.deck_size.clone()), - |acc, next| { - eprintln!("{}", acc); - acc.then(&(next.clone(), opt.deck_size.clone(), true).into()) - } - ) - .repeat(opt.repetitions) - .apply(opt.card.clone()) - ); - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -fn mod_plus(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - mod_normalize(a + b, modulus) -} - -fn mod_sub(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - mod_normalize(a - b, modulus) -} - -fn mod_times(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - mod_normalize(a * b, modulus) -} - -fn mod_divide(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - mod_times(a, mod_inverse(b, modulus.clone()), modulus) -} - -fn mod_pow(a: BigInt, b: BigInt, modulus: BigInt) -> BigInt { - a.modpow(&b, &modulus) -} - -fn mod_normalize(a: BigInt, modulus: BigInt) -> BigInt { - if a.is_negative() { - a.clone() + modulus.clone() * (1 + abs(a) / modulus) - } else { - a % modulus - } -} - -// NB: This may give nonsense if modulus isn't coprime with a -fn mod_inverse(a: BigInt, modulus: BigInt) -> BigInt { - mod_normalize(euclid_gcd_coefficients(a, modulus.clone()).0, modulus) -} - -fn euclid_gcd_coefficients(a: BigInt, b: BigInt) -> (BigInt, BigInt) { - fn euclid_gcd_coefficients_inner( - r: BigInt, - old_r: BigInt, - s: BigInt, - old_s: BigInt, - t: BigInt, - old_t: BigInt, - ) -> (BigInt, BigInt) { - if r.is_zero() { - (old_s, old_t) - } else { - euclid_gcd_coefficients_inner( - old_r.clone() - (old_r.clone() / r.clone()) * r.clone(), - r.clone(), - old_s - (old_r.clone() / r.clone()) * s.clone(), - s, - old_t - (old_r.clone() / r) * t.clone(), - t, - ) - } - } - - assert!(a < b); - - euclid_gcd_coefficients_inner(b, a, 0.into(), 1.into(), 1.into(), 0.into()) -} - -#[derive(Debug, Clone)] -enum Instruction { - DealIntoNewStack, - Cut(BigInt), - ReverseCut(BigInt), - DealWithIncrement(BigInt), -} - -impl FromStr for Instruction { - type Err = ParseErr; - fn from_str(s: &str) -> Result { - if s.starts_with("deal into new stack") { - Ok(Instruction::DealIntoNewStack) - } else if s.starts_with("cut -") { - s.split(' ') - .nth(1) - .map(|val| { - val.parse::() - .map_err(|_| ParseErr) - .map(|parsed| Instruction::ReverseCut(abs(parsed))) - }) - .unwrap_or(Err(ParseErr)) - } else if s.starts_with("cut") { - s.split(' ') - .nth(1) - .map(|val| { - val.parse::() - .map_err(|_| ParseErr) - .map(|parsed| Instruction::Cut(parsed)) - }) - .unwrap_or(Err(ParseErr)) - } else if s.starts_with("deal with increment") { - s.split(' ') - .nth(3) - .map(|val| { - val.parse::() - .map_err(|_| ParseErr) - .map(|parsed| Instruction::DealWithIncrement(parsed)) - }) - .unwrap_or(Err(ParseErr)) - } else { - Err(ParseErr) - } - } -} - -// f(x) = ax + b mod c -#[derive(Display, Clone)] -#[display(fmt = "f(x) = {} x + {} % {}", a, b, modulus)] -struct StandardisedInstruction { - a: BigInt, - b: BigInt, - modulus: BigInt, -} - -impl From<(Instruction, BigInt, bool)> for StandardisedInstruction { - fn from((instruction, modulus, forward): (Instruction, BigInt, bool)) -> Self { - match (instruction, forward) { - (Instruction::DealIntoNewStack, _) => StandardisedInstruction { - a: BigInt::from(-1), - b: BigInt::from(-1), - modulus: modulus, - }, - (Instruction::Cut(n), true) => StandardisedInstruction { - a: BigInt::from(1), - b: BigInt::from(-n), - modulus: modulus, - }, - (Instruction::Cut(n), false) => StandardisedInstruction { - a: BigInt::from(1), - b: BigInt::from(n), - modulus: modulus, - }, - (Instruction::ReverseCut(n), true) => StandardisedInstruction { - a: BigInt::from(1), - b: BigInt::from(n), - modulus: modulus, - }, - (Instruction::ReverseCut(n), false) => StandardisedInstruction { - a: BigInt::from(1), - b: BigInt::from(-n), - modulus: modulus, - }, - (Instruction::DealWithIncrement(n), true) => StandardisedInstruction { - a: BigInt::from(n), - b: BigInt::from(0), - modulus: modulus, - }, - (Instruction::DealWithIncrement(n), false) => StandardisedInstruction { - a: BigInt::from(mod_inverse(n, modulus.clone())), - b: BigInt::from(0), - modulus: modulus, - }, - } - .normalise() - } -} - -impl StandardisedInstruction { - fn identity(modulus: BigInt) -> StandardisedInstruction { - StandardisedInstruction { - a: BigInt::from(1), - b: BigInt::from(0), - modulus, - } - } - fn normalise(&self) -> StandardisedInstruction { - StandardisedInstruction { - a: mod_normalize(self.a.clone(), self.modulus.clone()), - b: mod_normalize(self.b.clone(), self.modulus.clone()), - modulus: self.modulus.clone(), - } - } - fn then(&self, other: &StandardisedInstruction) -> StandardisedInstruction { - // g(f(x)) = ga (fa x + fb) + gb = - StandardisedInstruction { - a: mod_times(self.a.clone(), other.a.clone(), self.modulus.clone()), - b: mod_plus( - mod_times(self.b.clone(), other.a.clone(), self.modulus.clone()), - other.b.clone(), - self.modulus.clone(), - ), - modulus: self.modulus.clone(), - } - } - fn repeat(&self, repetitions: BigInt) -> StandardisedInstruction { - StandardisedInstruction { - a: mod_pow(self.a.clone(), repetitions.clone(), self.modulus.clone()), - b: mod_divide( - mod_times( - self.b.clone(), - mod_sub( - BigInt::from(1), - mod_pow(self.a.clone(), repetitions.clone(), self.modulus.clone()), - self.modulus.clone(), - ), - self.modulus.clone(), - ), - mod_sub(BigInt::from(1), self.a.clone(), self.modulus.clone()), - self.modulus.clone(), - ), - modulus: self.modulus.clone(), - } - } - - fn apply(&self, x: BigInt) -> BigInt { - mod_plus( - mod_times(self.a.clone(), x, self.modulus.clone()), - self.b.clone(), - self.modulus.clone(), - ) - } -} - -#[derive(Debug, Clone, Copy)] -struct ParseErr; - -impl fmt::Display for ParseErr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Error parsing input") - } -} - -impl std::error::Error for ParseErr {} - -#[test] -fn mod_inverse_of_13() { - assert_eq!(mod_inverse(1.into(), 13.into()), 1.into()); - assert_eq!(mod_inverse(2.into(), 13.into()), 7.into()); - assert_eq!(mod_inverse(3.into(), 13.into()), 9.into()); - assert_eq!(mod_inverse(4.into(), 13.into()), 10.into()); - assert_eq!(mod_inverse(5.into(), 13.into()), 8.into()); - assert_eq!(mod_inverse(6.into(), 13.into()), 11.into()); - assert_eq!(mod_inverse(7.into(), 13.into()), 2.into()); - assert_eq!(mod_inverse(8.into(), 13.into()), 5.into()); - assert_eq!(mod_inverse(9.into(), 13.into()), 3.into()); - assert_eq!(mod_inverse(10.into(), 13.into()), 4.into()); - assert_eq!(mod_inverse(11.into(), 13.into()), 6.into()); - assert_eq!(mod_inverse(12.into(), 13.into()), 12.into()); -} diff --git a/src/bin/day_23.rs b/src/bin/day_23.rs deleted file mode 100644 index e074cf4..0000000 --- a/src/bin/day_23.rs +++ /dev/null @@ -1,211 +0,0 @@ -use aoc2019::*; -use rpds::list; -use rpds::list::List; -use rpds::vector::Vector; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 23: Category Six")] -/// Executes an Intcode program on a network of computers -/// -/// See https://adventofcode.com/2019/day/23 for details. -struct Opt { - #[structopt(short = "n", long = "network-size")] - network_size: usize, - #[structopt(long = "nat")] - send_nat: 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::(), "Invalid number")) - .collect::(); - - let network = Network::new(program, opt.network_size); - - if opt.send_nat { - println!("{}", network.first_repeated_nat_packet().y); - } else { - println!("{}", network.first_nat_packet().y); - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -#[derive(Debug, Clone)] -struct Network { - computers: Vector, - nat: Option, - is_potentially_idle: bool, - is_idle: bool, -} - -impl Network { - fn new(program: IntcodeProgram, network_size: usize) -> Network { - Network { - computers: (0..network_size) - .map(|ip| program.with_input(list![ip.into(), Intcode::from(-1)])) - .collect(), - nat: None, - is_potentially_idle: false, - is_idle: false, - } - } - - fn first_nat_packet(&self) -> Packet { - iter::successors(Some(self.clone()), |network| Some(network.next())) - .filter_map(|network| network.nat) - .next() - .unwrap() - } - - fn first_repeated_nat_packet(&self) -> Packet { - self.sent_nat_packets() - .zip(self.sent_nat_packets().skip(1)) - // .inspect(|(nat, _p2)| eprintln!("{}", nat.y)) - .find(|(p1, p2)| p1.y == p2.y) - .unwrap() - .0 - } - - fn sent_nat_packets<'a>(&'a self) -> impl Iterator + 'a { - iter::successors(Some(self.clone()), |network| { - Some(network.with_nat_packet_sent().run_to_network_idle()) - }) - .filter_map(|network| network.nat) - } - - fn run_to_network_idle(&self) -> Network { - iter::successors(Some(self.clone()), |network| Some(network.next())) - .find(|network| network.is_idle) - .unwrap() - } - - fn with_nat_packet_sent(&self) -> Network { - if self.nat.is_some() { - Network { - computers: self - .computers - .iter() - .enumerate() - .map(|(ip, computer)| { - computer - .with_additional_input( - self.nat - .iter() - .filter(|packet| packet.dest == Intcode::from(ip)) - .flat_map(|packet| vec![packet.x.clone(), packet.y.clone()]) - .collect(), - ) - .run_to_termination_or_input() - }) - .collect(), - nat: self.nat.clone(), - is_potentially_idle: false, - is_idle: false, - } - } else { - self.clone() - } - } - - fn next(&self) -> Network { - Network { - computers: self - .computers - .iter() - .enumerate() - .map(|(ip, computer)| { - computer - .with_cleared_output() - .with_additional_input(if self.empty_queues() { - list![Intcode::from(-1)] - } else { - list![] - }) - .with_additional_input( - self.pending_packets() - .filter(|packet| packet.dest == Intcode::from(ip)) - .flat_map(|packet| vec![packet.x, packet.y]) - .collect(), - ) - .run_to_termination_or_input() - }) - .collect(), - nat: self - .pending_packets() - .filter(|packet| packet.is_nat()) - .map(|packet| packet.with_dest(0.into())) - .last() - .or_else(|| self.nat.clone()), - is_potentially_idle: self.empty_queues(), - is_idle: self.is_potentially_idle && self.empty_queues(), - } - } - - fn pending_packets<'a>(&'a self) -> impl Iterator + 'a { - self.computers.iter().flat_map(|computer| { - computer - .output - .iter() - .cloned() - .collect::>() - .chunks_exact(3) - .map(|packet| Packet { - dest: packet[0].clone(), - x: packet[1].clone(), - y: packet[2].clone(), - }) - .collect::>() - }) - } - - fn pending_input<'a>(&'a self) -> impl Iterator + 'a { - self.computers - .iter() - .flat_map(|computer| computer.input.iter().cloned().collect::>()) - } - - fn empty_queues(&self) -> bool { - self.pending_packets().count() == 0 && self.pending_input().count() == 0 - } -} - -#[derive(Debug, Clone)] -struct Packet { - dest: Intcode, - x: Intcode, - y: Intcode, -} - -impl Packet { - fn is_nat(&self) -> bool { - self.dest == 255.into() - } - - fn with_dest(&self, dest: Intcode) -> Packet { - Packet { - dest, - ..self.clone() - } - } -} diff --git a/src/bin/day_24.rs b/src/bin/day_24.rs deleted file mode 100644 index ebc6a1b..0000000 --- a/src/bin/day_24.rs +++ /dev/null @@ -1,239 +0,0 @@ -use rpds::RedBlackTreeSet; -use std::io; -use std::io::prelude::*; -use std::iter; -use std::iter::FromIterator; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 24: Planet of Discord")] -/// Simulates the life and death of Eris bugs -/// -/// See https://adventofcode.com/2019/day/24 for details. -struct Opt { - /// How many iterations of the game of life should be run - /// If not provided, runs until a state appears twice. - #[structopt(short = "n")] - depth: Option, - /// Interprets the map as being one part of an infinite fractal map - #[structopt(short = "f")] - fractal: bool, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let initial_state: State = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .collect::() - .with_fractal_mode(opt.fractal); - - let final_state = match opt.depth { - Some(depth) => initial_state.n_steps_forward(depth), - None => initial_state.first_repeated_state(), - }; - - println!("Bugs: {}", final_state.alive.size()); - println!("Biodiversity: {}", final_state.biodiversity_rating()); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -struct State { - alive: RedBlackTreeSet, - fractal_mode: bool, -} - -impl FromIterator for State { - fn from_iter>(iter: T) -> Self { - State { - alive: iter - .into_iter() - .enumerate() - .flat_map(move |(y, line)| { - line.chars() - .enumerate() - .filter(move |(_x, c)| *c == '#') - .map(move |(x, _c)| Coordinate { - x: x as isize, - y: y as isize, - depth: 0, - }) - .collect::>() - }) - .collect(), - fractal_mode: false, - } - } -} - -impl State { - fn with_fractal_mode(&self, fractal_mode: bool) -> State { - State { - fractal_mode, - ..self.clone() - } - } - - fn n_steps_forward(&self, n: usize) -> Self { - iter::successors(Some(self.clone()), |state| Some(state.next())) - .nth(n) - .unwrap() - } - - fn first_repeated_state(&self) -> State { - iter::successors( - Some((RedBlackTreeSet::new(), self.clone())), - |(seen, state)| Some((seen.insert(state.clone()), state.next())), - ) - .find(|(seen, state)| seen.contains(state)) - .unwrap() - .1 - } - - fn next(&self) -> State { - State { - alive: self - .still_alive_next_round() - .chain(self.comes_alive_next_round()) - .collect(), - ..self.clone() - } - } - - fn biodiversity_rating(&self) -> usize { - self.alive - .iter() - .map(|coord| 2_usize.pow((coord.y * 5 + coord.x) as u32)) - .sum() - } - - fn still_alive_next_round<'a>(&'a self) -> impl Iterator + 'a { - self.alive - .iter() - .filter(move |coord| self.count_alive_neighbours(**coord) == 1) - .cloned() - } - - fn comes_alive_next_round<'a>(&'a self) -> impl Iterator + 'a { - self.alive - .iter() - .flat_map(move |coord| self.neighbours(*coord)) - .filter(move |coord| !self.alive.contains(coord)) - .filter(move |coord| { - self.count_alive_neighbours(*coord) == 1 || self.count_alive_neighbours(*coord) == 2 - }) - } - - fn count_alive_neighbours(&self, coordinate: Coordinate) -> usize { - self.neighbours(coordinate) - .into_iter() - .filter(|coord| self.alive.contains(coord)) - .count() - } - - fn neighbours(&self, coordinate: Coordinate) -> Vec { - if self.fractal_mode { - [(-1, 0), (1, 0), (0, -1), (0, 1)] - .into_iter() - .map(|(dx, dy)| Coordinate { - x: coordinate.x + dx, - y: coordinate.y + dy, - depth: coordinate.depth, - }) - .flat_map(move |coord| match (coord.x, coord.y) { - (x, _y) if x < 0 => vec![Coordinate { - x: 1, - y: 2, - depth: coord.depth - 1, - }] - .into_iter(), - (_x, y) if y < 0 => vec![Coordinate { - x: 2, - y: 1, - depth: coord.depth - 1, - }] - .into_iter(), - (x, _y) if x >= 5 => vec![Coordinate { - x: 3, - y: 2, - depth: coord.depth - 1, - }] - .into_iter(), - (_x, y) if y >= 5 => vec![Coordinate { - x: 2, - y: 3, - depth: coord.depth - 1, - }] - .into_iter(), - (2, 2) => match (coordinate.x, coordinate.y) { - (1, 2) => (0..5) - .map(|y| Coordinate { - x: 0, - y, - depth: coord.depth + 1, - }) - .collect::>() - .into_iter(), - (2, 1) => (0..5) - .map(|x| Coordinate { - x, - y: 0, - depth: coord.depth + 1, - }) - .collect::>() - .into_iter(), - (3, 2) => (0..5) - .map(|y| Coordinate { - x: 4, - y, - depth: coord.depth + 1, - }) - .collect::>() - .into_iter(), - (2, 3) => (0..5) - .map(|x| Coordinate { - x, - y: 4, - depth: coord.depth + 1, - }) - .collect::>() - .into_iter(), - (_, _) => vec![].into_iter(), - }, - _ => vec![coord.clone()].into_iter(), - }) - .collect() - } else { - [(-1, 0), (1, 0), (0, -1), (0, 1)] - .into_iter() - .map(|(dx, dy)| Coordinate { - x: coordinate.x + dx, - y: coordinate.y + dy, - depth: coordinate.depth, - }) - .filter(|coord| coord.x >= 0 && coord.x < 5 && coord.y >= 0 && coord.y < 5) - .collect() - } - } -} - -#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)] -struct Coordinate { - x: isize, - y: isize, - depth: isize, -} diff --git a/src/bin/day_25.dot b/src/bin/day_25.dot deleted file mode 100644 index 58dc131..0000000 --- a/src/bin/day_25.dot +++ /dev/null @@ -1,43 +0,0 @@ -digraph { - Breach [label="Hull Breach"] - Crew [label="Crew Quarters (antenna)"] - Hallway [label="Hallway (weather machine)"] - Storage [label="Storage (klein bottle)"] - Stables [label="Stables (spool of cat6)"] - Warp [label="Warp Drive Maintenance"] - Security [label="Security Checkpoint"] - Pressure [label="Pressure-Sensitive Floor"] - Gift [label="Gift Wrapping Center"] - Sick [label="Sick Bay (infinite loop X)"] - Chocolate [label="Hot Chocolate Fountain (giant electromagnet X)"] - Observatory [label="Observatory (cake)"] - Navigation [label="Navigation (escape pod XX)"] - Corridor [label="Corridor"] - Holodeck [label="Holodeck (molten lava X)"] - Science [label="Science Lab (tambourine)"] - Passages [label="Passages (shell)"] - Engineering [label="Engineering"] - Arcade [label="Arcade (photons X)"] - Kitchen [label="Kitchen (mug)"] - - - Breach -> Crew [label=East] - Breach -> Hallway [label=North] - Hallway -> Storage [label=North] - Storage -> Stables [label=East] - Stables -> Warp [label=South] - Warp -> Security [label=South] - Security -> Pressure [label=East] - Stables -> Gift [label=East] - Gift -> Sick [label=North] - Sick -> Chocolate [label=West] - Chocolate -> Observatory [label=North] - Chocolate -> Navigation [label=West] - Corridor -> Holodeck [label=North] - Holodeck -> Science [label=North] - Sick -> Corridor [label=East] - Corridor -> Passages [label=South] - Passages -> Engineering [label=East] - Engineering -> Arcade [label=South] - Gift -> Kitchen [label=South] -} diff --git a/src/bin/day_25.rs b/src/bin/day_25.rs deleted file mode 100644 index 522789e..0000000 --- a/src/bin/day_25.rs +++ /dev/null @@ -1,110 +0,0 @@ -use aoc2019::*; -use std::io; -use std::io::prelude::*; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 25: Cryostasis")] -/// Pilots a robot to save Santa! -/// -/// See https://adventofcode.com/2019/day/25 for details. -struct Opt {} - -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::(); - - let input = vec![ - "east", - "take antenna", - "west", - "north", - "take weather machine", - "north", - "take klein bottle", - "east", - "take spool of cat6", - "east", - "south", - "take mug", - "north", - "north", - "west", - "north", - "take cake", - "south", - "east", - "east", - "north", - "north", - "take tambourine", - "south", - "south", - "south", - "take shell", - "north", - "west", - "south", - "west", - "south", - "south", - "inv", - //"drop mug", - //"drop weather machine", - "drop cake", - "drop shell", - "drop klein bottle", - "drop tambourine", - //"drop antenna", - //"drop spool of cat6", - "east", - ]; - - let result = exit_on_failed_assertion( - program - .with_input( - input - .iter() - .flat_map(|line| { - line.chars() - .map(|c| Intcode::from(c as u8)) - .chain(vec![Intcode::from(10)].into_iter()) - }) - .collect(), - ) - .run_to_termination_or_input() - .output_into_result(), - "Program failed", - ); - - println!( - "{}", - result - .drop_last() - .unwrap() - .iter() - .flat_map(|c| c.to_signed_bytes_be()) - .map(|c| c as char) - .collect::() - ); - println!("{}", result.last().unwrap()); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} diff --git a/src/bin/day_3.rs b/src/bin/day_3.rs deleted file mode 100644 index f4163bd..0000000 --- a/src/bin/day_3.rs +++ /dev/null @@ -1,333 +0,0 @@ -use rpds::vector::Vector; -use std::fmt; -use std::io; -use std::io::prelude::*; -use std::process; -use std::str::FromStr; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 3: Crossed Wires")] -/// Finds the closest intersection between two wires. By default, -/// 'closest' is defined as closest in terms of Manhattan distance. If -/// --signal-distance is set, distance is defined in terms of the -/// total distance along the wire. -/// -/// See https://adventofcode.com/2019/day/3 for details. -struct Opt { - #[structopt(short = "s", long = "signal-distance")] - /// returns the closest intersection by signal distance. - signal_distance: bool, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let mut input = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid wire")); - - let (wire1, wire2) = match (input.next(), input.next()) { - (Some(w1), Some(w2)) => (w1, w2), - _ => { - eprintln!("Input must have two wires"); - process::exit(1); - } - }; - - match wire1.closest_collision(&wire2, opt.signal_distance) { - Some(c) => println!( - "{}", - if opt.signal_distance { - c.signal_distance - } else { - c.manhattan_distance() - } - ), - None => { - eprintln!("No collisions"); - 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); - } - } -} - -#[derive(Debug, Clone)] -struct Wire { - segments: Vector, -} - -impl FromStr for Wire { - type Err = UnknownError; - - fn from_str(s: &str) -> Result { - s.split(',') - .fold( - Ok(Vector::new()), - |acc: Result, UnknownError>, next_str| { - acc.and_then(|previous_segments| { - WireSegment::from_str( - previous_segments.last().map(|l| l.end()).unwrap_or((0, 0)), - previous_segments - .last() - .map(|l| l.end_signal_distance()) - .unwrap_or(0), - next_str, - ) - .map(|seg| previous_segments.push_back(seg)) - }) - }, - ) - .map(|segments| Wire { segments }) - } -} - -impl Wire { - fn closest_collision(&self, other: &Wire, use_signal_distance: bool) -> Option { - self.collisions(other).min_by_key(|c| { - if use_signal_distance { - c.signal_distance - } else { - c.manhattan_distance() - } - }) - } - - fn collisions<'a>(&'a self, other: &'a Wire) -> impl Iterator + 'a { - self.segments - .iter() - .flat_map(move |seg1| other.segments.iter().map(move |seg2| (seg1, seg2))) - .flat_map(|(seg1, seg2)| seg1.collisions(seg2)) - .filter(|c| !(c.x == 0 && c.y == 0)) - } -} - -#[derive(Debug, Clone)] -struct WireSegment { - start: (i32, i32), - start_signal_distance: i32, - direction: Direction, - length: i32, -} - -impl WireSegment { - fn from_str( - start: (i32, i32), - start_signal_distance: i32, - s: &str, - ) -> Result { - s.parse::().and_then(|direction| { - WireSegment::length_from_str(s).map(|length| WireSegment { - start, - start_signal_distance, - direction, - length, - }) - }) - } - - fn length_from_str(s: &str) -> Result { - s.chars() - .skip(1) - .collect::() - .parse() - .map_err(|_| UnknownError) - } - - fn end(&self) -> (i32, i32) { - ( - self.start.0 + self.direction.as_vec().0 * self.length, - self.start.1 + self.direction.as_vec().1 * self.length, - ) - } - - fn end_signal_distance(&self) -> i32 { - self.start_signal_distance + self.length - } - - fn collisions(&self, other: &WireSegment) -> Option { - use Direction::*; - - match (self.direction, other.direction) { - (Left, Left) | (Right, Right) | (Up, Up) | (Down, Down) => None, - (Left, Right) | (Right, Left) | (Up, Down) | (Down, Up) => None, - (Left, Up) => collisions( - self.end(), - self.end_signal_distance(), - self.length, - -1, - other.start, - other.start_signal_distance, - other.length, - 1, - ), - (Left, Down) => collisions( - self.end(), - self.end_signal_distance(), - self.length, - -1, - other.end(), - other.end_signal_distance(), - other.length, - -1, - ), - (Right, Up) => collisions( - self.start, - self.start_signal_distance, - self.length, - 1, - other.start, - other.start_signal_distance, - other.length, - 1, - ), - (Right, Down) => collisions( - self.start, - self.start_signal_distance, - self.length, - 1, - other.end(), - other.end_signal_distance(), - other.length, - -1, - ), - (Down, Right) => collisions( - other.start, - other.start_signal_distance, - other.length, - 1, - self.end(), - self.end_signal_distance(), - self.length, - -1, - ), - (Down, Left) => collisions( - other.end(), - other.end_signal_distance(), - other.length, - -1, - self.end(), - self.end_signal_distance(), - self.length, - -1, - ), - (Up, Right) => collisions( - other.start, - other.start_signal_distance, - other.length, - 1, - self.start, - self.start_signal_distance, - self.length, - 1, - ), - (Up, Left) => collisions( - other.end(), - other.end_signal_distance(), - other.length, - -1, - self.start, - self.start_signal_distance, - self.length, - 1, - ), - } - } -} - -fn collisions( - horizontal_start: (i32, i32), - horizontal_start_signal_distance: i32, - horizontal_length: i32, - horizontal_signal_distance_multiplier: i32, - vertical_start: (i32, i32), - vertical_start_signal_distance: i32, - vertical_length: i32, - vertical_signal_distance_multiplier: i32, -) -> Option { - if horizontal_start.1 >= vertical_start.1 - && horizontal_start.1 <= vertical_start.1 + vertical_length - && vertical_start.0 >= horizontal_start.0 - && vertical_start.0 <= horizontal_start.0 + horizontal_length - { - Some(Collision { - x: vertical_start.0, - y: horizontal_start.1, - signal_distance: horizontal_start_signal_distance - + (vertical_start.0 - horizontal_start.0) * horizontal_signal_distance_multiplier - + vertical_start_signal_distance - + (horizontal_start.1 - vertical_start.1) * vertical_signal_distance_multiplier, - }) - } else { - None - } -} - -#[derive(Debug, Clone, Copy)] -enum Direction { - Up, - Down, - Left, - Right, -} - -impl FromStr for Direction { - type Err = UnknownError; - - fn from_str(s: &str) -> Result { - use Direction::*; - match s.chars().next() { - Some('L') => Ok(Left), - Some('R') => Ok(Right), - Some('U') => Ok(Up), - Some('D') => Ok(Down), - Some(_) => Err(UnknownError), - None => Err(UnknownError), - } - } -} -impl Direction { - fn as_vec(&self) -> (i32, i32) { - use Direction::*; - match self { - Up => (0, 1), - Down => (0, -1), - Left => (-1, 0), - Right => (1, 0), - } - } -} - -struct Collision { - x: i32, - y: i32, - signal_distance: i32, -} - -impl Collision { - fn manhattan_distance(&self) -> i32 { - self.x.abs() + self.y.abs() - } -} - -#[derive(Debug, PartialEq)] -struct UnknownError; - -impl fmt::Display for UnknownError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Unknown error") - } -} -impl std::error::Error for UnknownError {} diff --git a/src/bin/day_4.rs b/src/bin/day_4.rs deleted file mode 100644 index d7d6b69..0000000 --- a/src/bin/day_4.rs +++ /dev/null @@ -1,55 +0,0 @@ -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 4: Secure Container")] -/// Calculates how many possible lock values there are -/// -/// See https://adventofcode.com/2019/day/4 for details. -struct Opt { - /// Repeated digits must be exactly 2 long - #[structopt(long = "larger-range-rule")] - larger_range_rule: bool, - min: u32, - max: u32, -} - -fn main() { - let opt = Opt::from_args(); - - println!( - "{}", - valid_combinations(opt.min, opt.max, opt.larger_range_rule) - ) -} - -fn valid_combinations(min: u32, max: u32, larger_range_rule: bool) -> u32 { - (min..max) - .filter(|x| { - two_adjacent_identical_digits(*x, larger_range_rule) && digits_never_decrease(*x) - }) - .count() as u32 -} - -fn two_adjacent_identical_digits(x: u32, larger_range_rule: bool) -> bool { - if larger_range_rule { - (0..5).any(|d| { - digit(x, d) == digit(x, d + 1) - && digit(x, d) != digit(x, d + 2) - && digit(x, d) != digit(x, d - 1) - }) - } else { - (0..5).any(|d| digit(x, d) == digit(x, d + 1)) - } -} - -fn digits_never_decrease(x: u32) -> bool { - (0..5).all(|d| digit(x, d) >= digit(x, d + 1)) -} - -fn digit(x: u32, digit: i32) -> u32 { - if digit < 0 { - 0 - } else { - (x / 10u32.pow(digit as u32)) % 10 - } -} diff --git a/src/bin/day_5.rs b/src/bin/day_5.rs deleted file mode 100644 index 07f7af8..0000000 --- a/src/bin/day_5.rs +++ /dev/null @@ -1,45 +0,0 @@ -use aoc2019::*; -use std::io; -use std::io::prelude::*; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 5: Sunny with a Chance of Asteroids")] -/// Executes an Intcode program -/// -/// The program is read from stdin as a series of comma-separated -/// values. Newlines are ignored. -/// -/// See https://adventofcode.com/2019/day/5 for details. -struct Opt { - #[structopt(short = "i", long = "input")] - input: Vec, -} - -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::() - .with_input(opt.input.into_iter().collect()); - - let result = exit_on_failed_assertion(program.execute(), "Program errored"); - println!("{}", result); -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} diff --git a/src/bin/day_6.rs b/src/bin/day_6.rs deleted file mode 100644 index 2af272c..0000000 --- a/src/bin/day_6.rs +++ /dev/null @@ -1,251 +0,0 @@ -use rpds::vector::Vector; -use std::fmt; -use std::io; -use std::io::prelude::*; -use std::iter::FromIterator; -use std::process; -use std::str::FromStr; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 6: Universal Orbit Map")] -/// Finds the minumum number of orbital transfers between two points. -/// -/// Input is read from stdin, one direct orbit per line, in the format -/// `A)B` (B is orbiting A). -/// -/// See https://adventofcode.com/2019/day/6 for details. -struct Opt { - /// Debug checksum: Counts the total orbits - #[structopt(short = "d", long = "debug")] - debug: bool, -} - -fn main() { - let stdin = io::stdin(); - let opt = Opt::from_args(); - - let orbits: OrbitalMap = stdin - .lock() - .lines() - .map(|x| exit_on_failed_assertion(x, "Error reading input")) - .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid orbit")) - .collect(); - - // eprintln!("{:#?}", orbits); - - if opt.debug { - println!("{}", orbits.total_orbits()); - } else { - println!("{}", orbits.orbital_transfers("YOU", "SAN")); - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -#[derive(Debug)] -struct StrError { - str: String, -} - -impl fmt::Display for StrError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.str) - } -} -impl std::error::Error for StrError {} - -#[derive(Debug, Clone)] -struct Orbit { - a: String, - b: String, -} - -impl FromStr for Orbit { - type Err = StrError; - - fn from_str(s: &str) -> Result { - match s.split(')').collect::>()[..] { - [a, b] => Ok(Orbit { - a: a.to_string(), - b: b.to_string(), - }), - _ => Err(StrError { - str: format!("{} is not a valid orbit description", s), - }), - } - } -} - -#[derive(Clone, Debug)] -struct OrbitalMap { - id: String, - depth: usize, - orbiters: Vector, -} - -struct OrbitalMapBuilder { - orbiters: Vector, - inserted_orbits: Vector, - pending_orbits: Vector, -} - -impl FromIterator for OrbitalMap { - fn from_iter>(iter: T) -> Self { - iter.into_iter().collect::().build() - } -} - -impl FromIterator for OrbitalMapBuilder { - fn from_iter>(iter: T) -> Self { - OrbitalMapBuilder { - orbiters: Vector::new(), - inserted_orbits: Vector::new(), - pending_orbits: iter.into_iter().collect(), - } - } -} - -impl OrbitalMapBuilder { - fn build(self) -> OrbitalMap { - if self.pending_orbits.is_empty() { - OrbitalMap { - id: ROOT.into(), - depth: 0, - orbiters: self.orbiters, - } - } else { - self.pending_orbits - .into_iter() - .fold( - OrbitalMapBuilder { - pending_orbits: Vector::new(), - ..self - }, - |acc, next| acc.insert(&next), - ) - .build() - } - } - - fn insert(self, orbit: &Orbit) -> OrbitalMapBuilder { - if orbit.a == ROOT { - OrbitalMapBuilder { - orbiters: self.orbiters.push_back(OrbitalMap::new(orbit.b.clone(), 1)), - inserted_orbits: self.inserted_orbits.push_back(orbit.b.clone()), - ..self - } - } else if self.inserted_orbits.iter().any(|o| *o == orbit.a) { - OrbitalMapBuilder { - orbiters: self - .orbiters - .into_iter() - .map(|map| OrbitalMap::insert(map.clone(), orbit)) - .collect(), - inserted_orbits: self.inserted_orbits.push_back(orbit.b.clone()), - ..self - } - } else { - OrbitalMapBuilder { - pending_orbits: self.pending_orbits.push_back(orbit.clone()), - ..self - } - } - } -} - -const ROOT: &str = "COM"; - -impl OrbitalMap { - fn new(id: String, depth: usize) -> OrbitalMap { - OrbitalMap { - id, - depth, - orbiters: Vector::new(), - } - } - - fn insert(self, orbit: &Orbit) -> OrbitalMap { - if orbit.a == self.id { - if self.orbiters.iter().any(|o| o.id == orbit.b) { - self - } else { - OrbitalMap { - orbiters: self - .orbiters - .push_back(OrbitalMap::new(orbit.b.clone(), self.depth + 1)), - ..self - } - } - } else { - OrbitalMap { - orbiters: self - .orbiters - .into_iter() - .map(|map| OrbitalMap::insert(map.clone(), orbit)) - .collect(), - ..self - } - } - } - - fn count_orbits(&self) -> usize { - self.orbiters.len() - + self - .orbiters - .iter() - .map(|o| o.count_orbits()) - .sum::() - } - - fn total_orbits(&self) -> usize { - self.count_orbits() - + self - .orbiters - .iter() - .map(|o| o.total_orbits()) - .sum::() - } - - fn find_depth(&self, id: &str) -> usize { - if self.id == id { - self.depth - } else { - // only the actual one will return non-zero from this - self.orbiters.iter().map(|o| o.find_depth(id)).sum() - } - } - - fn contains(&self, id: &str) -> bool { - self.id == id || self.orbiters.iter().any(|o| o.contains(id)) - } - - fn find_common_ancestor(&self, a: &str, b: &str) -> Option { - if !self.contains(a) || !self.contains(b) { - None - } else { - self.orbiters - .iter() - .flat_map(|o| o.find_common_ancestor(a, b)) - .next() - .or(Some(self.clone())) - } - } - - fn orbital_transfers(&self, from: &str, to: &str) -> usize { - self.find_depth(from) + self.find_depth(to) - - 2 * self - .find_common_ancestor(from, to) - .map(|o| o.depth) - .unwrap_or(0) - - 2 - } -} diff --git a/src/bin/day_7.rs b/src/bin/day_7.rs deleted file mode 100644 index 9b9177a..0000000 --- a/src/bin/day_7.rs +++ /dev/null @@ -1,175 +0,0 @@ -use aoc2019::*; -use rpds::list; -use rpds::list::List; -use rpds::vector::Vector; -use std::io; -use std::io::prelude::*; -use std::iter; -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::(), "Invalid number")) - .collect::(); - - let result = exit_on_failed_assertion( - find_max_power(&program, opt.feedback_loop_mode), - "Program errored", - ); - println!("{}", result); -} - -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_max_power( - program: &IntcodeProgram, - feedback_loop_mode: bool, -) -> Result { - PhaseSetting::all(feedback_loop_mode) - .map(|phase| AmplifierArray::new(program, &phase).execute()) - .collect::, _>>() - .map(|powers| powers.into_iter().max().unwrap_or(Intcode::from(0))) -} - -#[derive(Debug, Clone)] -struct PhaseSetting([Intcode; 5]); - -impl PhaseSetting { - fn all(feedback_loop_mode: bool) -> impl Iterator { - if feedback_loop_mode { - PhaseSetting::permute(5, 10) - } else { - PhaseSetting::permute(0, 5) - } - } - - fn permute(min: i32, max: i32) -> impl Iterator { - // This is an absolutely atrocious way to do the permutation, - // but luckily it's only 5 elements long. - (min..max) - .flat_map(move |a| { - (min..max).flat_map(move |b| { - (min..max).flat_map(move |c| { - (min..max).flat_map(move |d| { - (min..max).map(move |e| { - PhaseSetting([a.into(), b.into(), c.into(), d.into(), e.into()]) - }) - }) - }) - }) - }) - .filter(move |phase| (min..max).all(|x| phase.0.contains(&x.into()))) - } -} - -#[derive(Debug, Clone)] -struct AmplifierArray { - amplifiers: Vector, -} - -impl AmplifierArray { - fn new(program: &IntcodeProgram, phase: &PhaseSetting) -> AmplifierArray { - AmplifierArray { - amplifiers: (0..5) - .map(|n| AmplifierArray::new_amp(program, phase, n)) - .collect(), - } - } - - fn new_amp(program: &IntcodeProgram, phase: &PhaseSetting, n: usize) -> IntcodeProgram { - if n == 0 { - program.with_input(list![phase.0[n].clone(), Intcode::from(0)]) - } else { - program.with_input(list![phase.0[n].clone()]) - } - } - - fn execute(&self) -> Result { - self.run_to_termination().output_into_result() - } - - fn run_to_termination(&self) -> AmplifierArray { - iter::successors(Some(self.clone()), |p| Some(p.next())) - .find(|p| p.is_terminated()) - .unwrap() // successors doesn't terminate, so this will never be none. - } - - fn output_into_result(&self) -> Result { - self.amplifiers - .first() - .and_then(|amp| amp.input.first().cloned()) - .ok_or(IntcodeProgramError::Unknown) - } - - fn is_terminated(&self) -> bool { - self.amplifiers.last().map(|amp| amp.halted).unwrap_or(true) - } - - fn next(&self) -> AmplifierArray { - self.run_amplifiers().update_inputs() - } - - fn run_amplifiers(&self) -> AmplifierArray { - AmplifierArray { - amplifiers: self - .amplifiers - .iter() - .map(|amp| amp.run_to_termination_or_input()) - .collect(), - } - } - - fn update_inputs(&self) -> AmplifierArray { - AmplifierArray { - amplifiers: self - .amplifiers - .iter() - .fold( - ( - Vector::new(), - self.amplifiers - .last() - .map(|a| a.output.iter().cloned().collect::>()) - .unwrap_or(List::new()), - ), - |(amps, piped_input), next_amp| { - ( - amps.push_back( - next_amp - .with_additional_input(piped_input) - .with_cleared_output(), - ), - next_amp.output.iter().cloned().collect::>(), - ) - }, - ) - .0, - } - } -} diff --git a/src/bin/day_8.rs b/src/bin/day_8.rs deleted file mode 100644 index 0508e7c..0000000 --- a/src/bin/day_8.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::fmt; -use std::io; -use std::io::prelude::*; -use std::process; -use structopt::StructOpt; - -#[derive(Debug, StructOpt)] -#[structopt(name = "Day 8: Space Image Format")] -/// Executes an Intcode program on 5 amplifiers, and finds the input that gives the max output -/// -/// See https://adventofcode.com/2019/day/8 for details. -struct Opt { - /// Rather than rendering the image, calculate and print its checksum - #[structopt(short = "c", long = "checksum")] - checksum_mode: bool, - #[structopt(short = "w", long = "width")] - width: u32, - #[structopt(short = "h", long = "height")] - height: u32, -} - -fn main() { - let opt = Opt::from_args(); - - let image: Image = { - let mut buffer = String::new(); - exit_on_failed_assertion( - io::stdin().read_to_string(&mut buffer), - "Error reading input", - ); - - Image::from_str(&buffer.trim(), opt.width, opt.height) - }; - - if opt.checksum_mode { - println!("{}", image.checksum()); - } else { - println!("{}", image); - } -} - -fn exit_on_failed_assertion(data: Result, message: &str) -> A { - match data { - Ok(data) => data, - Err(e) => { - eprintln!("{}: {}", message, e); - process::exit(1); - } - } -} - -#[derive(Debug)] -struct Image { - width: u32, - height: u32, - layers: Vec, -} - -impl fmt::Display for Image { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.flatten() - .pixels - .chunks(self.width as usize) - .map(|line| { - line.iter() - .map(|c| write!(f, "{}", if *c == 0 { ' ' } else { '1' })) - .collect::() - .and_then(|_| writeln!(f)) - }) - .collect() - } -} - -impl Image { - fn from_str(s: &str, width: u32, height: u32) -> Image { - Image { - width, - height, - layers: s - .as_bytes() - .chunks((width * height) as usize) - .map(|chunk| ImageLayer::new(chunk)) - .collect(), - } - } - - fn checksum(&self) -> usize { - self.layers - .iter() - .min_by_key(|layer| layer.pixel_count(0)) - .map(|layer| layer.pixel_count(1) * layer.pixel_count(2)) - .unwrap_or(0) - } - - fn flatten(&self) -> ImageLayer { - self.layers - .iter() - .fold(ImageLayer::empty(self.width, self.height), |acc, next| { - ImageLayer { - pixels: acc - .pixels - .iter() - .zip(next.pixels.iter()) - .map(|(a, b)| if *a == 2 { *b } else { *a }) - .collect(), - } - }) - } -} - -#[derive(Debug)] -struct ImageLayer { - pixels: Vec, -} - -impl ImageLayer { - fn new(char_pixels: &[u8]) -> ImageLayer { - ImageLayer { - pixels: char_pixels - .iter() - .map(|c| c.overflowing_sub(b'0').0) - .collect(), - } - } - - fn empty(width: u32, height: u32) -> ImageLayer { - ImageLayer { - pixels: vec![2; (width * height) as usize], - } - } - - fn pixel_count(&self, value: u8) -> usize { - self.pixels.iter().filter(|p| **p == value).count() - } -} diff --git a/src/bin/day_9.rs b/src/bin/day_9.rs deleted file mode 100644 index 7f9b4aa..0000000 --- a/src/bin/day_9.rs +++ /dev/null @@ -1 +0,0 @@ -// Run the day 5 binary for this diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index a7dfc02..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,438 +0,0 @@ -use derivative::Derivative; -use num::bigint::BigInt; -use num::traits::identities::Zero; -use rpds::RedBlackTreeMap; -use rpds::{list::List, vector::Vector}; -use std::fmt; -use std::iter; -use std::iter::FromIterator; -use std::iter::IntoIterator; -use std::iter::Iterator; - -pub type Intcode = BigInt; - -#[derive(Clone, Derivative)] -#[derivative(Debug)] -pub struct IntcodeProgram { - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] - instruction_pointer: Intcode, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] - relative_base: Intcode, - pub error: Option, - pub halted: bool, - pub awaiting_input: bool, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] - memory: RedBlackTreeMap, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] - pub input: List, - #[derivative(Debug(format_with = "std::fmt::Display::fmt"))] - pub output: Vector, -} - -impl FromIterator for IntcodeProgram { - fn from_iter>(iter: I) -> Self { - IntcodeProgram { - instruction_pointer: Intcode::from(0), - relative_base: Intcode::from(0), - error: None, - halted: false, - awaiting_input: false, - memory: iter - .into_iter() - .enumerate() - .map(|(addr, val)| (Intcode::from(addr), val)) - .collect(), - input: List::new(), - output: Vector::new(), - } - } -} - -pub fn intcode_to_bool(i: &Intcode) -> bool { - *i != Intcode::from(0) -} - -pub fn bool_to_intcode(i: bool) -> Intcode { - if i { - Intcode::from(1) - } else { - Intcode::from(0) - } -} - -impl IntcodeProgram { - pub fn with_mem_0(&self, val: Intcode) -> IntcodeProgram { - self.with_memory_set(0.into(), val) - } - - pub fn with_noun_verb_input(&self, noun: Intcode, verb: Intcode) -> IntcodeProgram { - self.with_memory_set(1.into(), noun) - .with_memory_set(2.into(), verb) - } - - pub fn with_input(&self, input: List) -> IntcodeProgram { - IntcodeProgram { - input, - ..self.clone() - } - } - - pub fn with_additional_input(&self, input: List) -> IntcodeProgram { - IntcodeProgram { - input: self.input.iter().chain(input.iter()).cloned().collect(), - ..self.clone() - } - } - - pub fn with_cleared_output(&self) -> IntcodeProgram { - IntcodeProgram { - output: Vector::new(), - ..self.clone() - } - } - - pub fn execute(&self) -> Result, IntcodeProgramError> { - self.run_to_termination().output_into_result() - } - - pub fn execute_returning_memory_0(&self) -> Result { - self.run_to_termination().memory_0_into_result() - } - - pub fn run_to_termination(&self) -> IntcodeProgram { - iter::successors(Some(self.clear_await_input()), |p| { - Some(IntcodeProgram::next(&p)) - }) - .find(|p| p.halted) - .unwrap() // successors doesn't terminate, so this will never be none. - } - - pub fn run_to_termination_or_input(&self) -> IntcodeProgram { - iter::successors(Some(self.clear_await_input()), |p| { - Some(IntcodeProgram::next(&p)) - }) - .find(|p| p.halted || p.awaiting_input) - .unwrap() - } - - pub fn output_into_result(&self) -> Result, IntcodeProgramError> { - match self.error { - Some(ref error) => Err(error.clone()), - None => Ok(self.output.clone()), - } - } - - fn with_instruction_pointer(&self, instruction_pointer: Intcode) -> IntcodeProgram { - IntcodeProgram { - instruction_pointer, - ..self.clone() - } - } - - fn with_instruction_pointer_offset(&self, offset: usize) -> IntcodeProgram { - IntcodeProgram { - instruction_pointer: self.instruction_pointer.clone() + offset, - ..self.clone() - } - } - - fn with_relative_base(&self, relative_base: Intcode) -> IntcodeProgram { - IntcodeProgram { - relative_base, - ..self.clone() - } - } - - fn with_memory_set(&self, address: Intcode, value: Intcode) -> IntcodeProgram { - IntcodeProgram { - memory: self.memory.insert(address, value), - ..self.clone() - } - } - - fn with_input_consumed(&self) -> IntcodeProgram { - self.input - .drop_first() - .map(|input| IntcodeProgram { - input, - ..self.clone() - }) - .unwrap_or(self.error(IntcodeProgramError::Unknown)) - } - - fn with_output(&self, print: Intcode) -> IntcodeProgram { - IntcodeProgram { - output: self.output.push_back(print), - ..self.clone() - } - } - - fn memory_0_into_result(&self) -> Result { - match self.error { - Some(ref error) => Err(error.clone()), - None => Ok(self - .memory - .get(&Intcode::from(0)) - .cloned() - .unwrap_or(Intcode::from(0))), - } - } - fn next(&self) -> IntcodeProgram { - //dbg!(self); - self.memory - .get(&self.instruction_pointer) - .map(|opcode| match opcode.to_radix_le(100).1[0] { - 1 => self.add(opcode), - 2 => self.multiply(opcode), - 3 => self.input(opcode), - 4 => self.output(opcode), - 5 => self.jump_if_true(opcode), - 6 => self.jump_if_false(opcode), - 7 => self.less_than(opcode), - 8 => self.equals(opcode), - 9 => self.set_relative_base(opcode), - 99 => self.halt(), - unknown => self.error(IntcodeProgramError::InvalidOpcode(unknown.clone())), - }) - .unwrap_or(self.error(IntcodeProgramError::Unknown)) - } - - fn add(&self, mode: &Intcode) -> IntcodeProgram { - self.with_instruction_pointer_offset(4).with_memory_set( - self.get_literal(3, mode), - self.get(1, mode) + self.get(2, mode), - ) - } - - fn multiply(&self, mode: &Intcode) -> IntcodeProgram { - self.with_instruction_pointer_offset(4).with_memory_set( - self.get_literal(3, mode), - self.get(1, mode) * self.get(2, mode), - ) - } - - fn input(&self, mode: &Intcode) -> IntcodeProgram { - match self.input.first().cloned() { - Some(input) => self - .with_instruction_pointer_offset(2) - .with_memory_set(self.get_literal(1, mode), input) - .with_input_consumed(), - None => self.await_input(), - } - } - - fn output(&self, mode: &Intcode) -> IntcodeProgram { - self.with_instruction_pointer_offset(2) - .with_output(self.get(1, mode)) - } - - fn jump_if_true(&self, mode: &Intcode) -> IntcodeProgram { - if !self.get(1, mode).is_zero() { - self.with_instruction_pointer(self.get(2, mode)) - } else { - self.with_instruction_pointer_offset(3) - } - } - fn jump_if_false(&self, mode: &Intcode) -> IntcodeProgram { - if self.get(1, mode).is_zero() { - self.with_instruction_pointer(self.get(2, mode)) - } else { - self.with_instruction_pointer_offset(3) - } - } - - fn less_than(&self, mode: &Intcode) -> IntcodeProgram { - self.with_instruction_pointer_offset(4).with_memory_set( - self.get_literal(3, mode), - if self.get(1, mode) < self.get(2, mode) { - Intcode::from(1) - } else { - Intcode::from(0) - }, - ) - } - - fn equals(&self, mode: &Intcode) -> IntcodeProgram { - self.with_instruction_pointer_offset(4).with_memory_set( - self.get_literal(3, mode), - if self.get(1, mode) == self.get(2, mode) { - Intcode::from(1) - } else { - Intcode::from(0) - }, - ) - } - - fn set_relative_base(&self, mode: &Intcode) -> IntcodeProgram { - self.with_instruction_pointer_offset(2) - .with_relative_base(self.relative_base.clone() + self.get(1, mode)) - } - - fn halt(&self) -> IntcodeProgram { - IntcodeProgram { - halted: true, - ..self.clone() - } - } - - fn await_input(&self) -> IntcodeProgram { - IntcodeProgram { - awaiting_input: true, - ..self.clone() - } - } - - fn clear_await_input(&self) -> IntcodeProgram { - IntcodeProgram { - awaiting_input: false, - ..self.clone() - } - } - - fn error(&self, error: IntcodeProgramError) -> IntcodeProgram { - IntcodeProgram { - halted: true, - error: Some(error), - ..self.clone() - } - } - - fn get(&self, pointer_offset: usize, mode: &Intcode) -> Intcode { - match mode - .to_radix_le(10) - .1 - .get(pointer_offset + 1) - .cloned() - .unwrap_or(0) - { - 0 => self.get_position(pointer_offset), - 1 => self.get_immediate(pointer_offset), - 2 => self.get_relative(pointer_offset), - _ => Intcode::from(0), - } - } - - fn get_literal(&self, pointer_offset: usize, mode: &Intcode) -> Intcode { - match mode - .to_radix_le(10) - .1 - .get(pointer_offset + 1) - .cloned() - .unwrap_or(0) - { - 0 => self.get_immediate(pointer_offset), - 1 => self.get_immediate(pointer_offset), - 2 => self.get_immediate_relative(pointer_offset), - _ => Intcode::from(0), - } - } - - fn get_immediate(&self, pointer_offset: usize) -> Intcode { - self.memory - .get(&(self.instruction_pointer.clone() + pointer_offset)) - .cloned() - .unwrap_or(Intcode::from(0)) - } - - fn get_position(&self, pointer_offset: usize) -> Intcode { - self.memory - .get(&self.get_immediate(pointer_offset)) - .cloned() - .unwrap_or(Intcode::from(0)) - } - - fn get_relative(&self, pointer_offset: usize) -> Intcode { - self.memory - .get(&(self.get_immediate(pointer_offset) + self.relative_base.clone())) - .cloned() - .unwrap_or(Intcode::from(0)) - } - - fn get_immediate_relative(&self, pointer_offset: usize) -> Intcode { - self.get_immediate(pointer_offset) + self.relative_base.clone() - } -} - -#[derive(Debug, PartialEq, Clone)] -pub enum IntcodeProgramError { - InvalidOpcode(u8), - Unknown, -} - -impl fmt::Display for IntcodeProgramError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use IntcodeProgramError::*; - - match self { - InvalidOpcode(i) => write!(f, "{} is not a valid opcode", i), - Unknown => write!(f, "Unknown error"), - } - } -} -impl std::error::Error for IntcodeProgramError {} - -#[cfg(test)] -mod tests { - use super::*; - - fn i32_vec_to_intcode_program(input: Vec) -> IntcodeProgram { - input.into_iter().map(Intcode::from).collect() - } - - fn i32_vec_to_intcode_memory(input: Vec) -> RedBlackTreeMap { - input - .into_iter() - .enumerate() - .map(|(i, val)| (Intcode::from(i), Intcode::from(val))) - .collect() - } - - fn i32_vec_to_intcode_vec(input: Vec) -> Vector { - input.into_iter().map(Intcode::from).collect() - } - - fn test_example_program( - before_execution: Vec, - after_execution: Vec, - ) -> IntcodeProgram { - let program = i32_vec_to_intcode_program(before_execution).run_to_termination(); - - assert_eq!(program.error, None); - assert_eq!(program.memory, i32_vec_to_intcode_memory(after_execution)); - program - } - - #[test] - fn day_2_example_1() { - test_example_program(vec![1, 0, 0, 0, 99], vec![2, 0, 0, 0, 99]); - } - - #[test] - fn day_2_example_2() { - test_example_program(vec![2, 3, 0, 3, 99], vec![2, 3, 0, 6, 99]); - } - - #[test] - fn day_5_example_1() { - test_example_program(vec![1002, 4, 3, 4, 33], vec![1002, 4, 3, 4, 99]); - } - - #[test] - fn day_9_example_1() { - let quine = vec![ - 109, 1, 204, -1, 1001, 100, 1, 100, 1008, 100, 16, 101, 1006, 101, 0, 99, - ]; - let program = i32_vec_to_intcode_program(quine.clone()).run_to_termination(); - assert_eq!(program.error, None); - assert_eq!(program.output, i32_vec_to_intcode_vec(quine)); - } -} - -pub fn sort_by_key( - iter: impl IntoIterator, - f: impl FnMut(&T) -> K, -) -> impl Iterator { - let mut tmp: Vec = iter.into_iter().collect(); - tmp.sort_by_key(f); - tmp.into_iter() -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 0c24a73..0000000 --- a/src/main.rs +++ /dev/null @@ -1,12 +0,0 @@ -use std::io; -use std::io::prelude::*; - -fn main() { - let stdin = io::stdin(); - let answer = string_length_sum(stdin.lock().lines().map(|l| l.unwrap())); - dbg!(answer); -} - -fn string_length_sum(it: impl Iterator) -> usize { - it.map(|l| l.len()).sum() -} -- cgit v1.2.3