From c96ffb03a8a3327cb7fe0e5061a8d8e43663bf9b Mon Sep 17 00:00:00 2001 From: mat ess Date: Mon, 5 Dec 2022 22:24:05 -0500 Subject: [PATCH] Day 5 --- inputs/5.small.txt | 9 + inputs/5.txt | 512 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 180 +++++++++++++--- 3 files changed, 668 insertions(+), 33 deletions(-) create mode 100644 inputs/5.small.txt create mode 100644 inputs/5.txt diff --git a/inputs/5.small.txt b/inputs/5.small.txt new file mode 100644 index 0000000..84933bb --- /dev/null +++ b/inputs/5.small.txt @@ -0,0 +1,9 @@ + [D] +[N] [C] +[Z] [M] [P] + 1 2 3 + +move 1 from 2 to 1 +move 3 from 1 to 3 +move 2 from 2 to 1 +move 1 from 1 to 2 diff --git a/inputs/5.txt b/inputs/5.txt new file mode 100644 index 0000000..7f69557 --- /dev/null +++ b/inputs/5.txt @@ -0,0 +1,512 @@ + [M] [Z] [V] + [Z] [P] [L] [Z] [J] +[S] [D] [W] [W] [H] [Q] +[P] [V] [N] [D] [P] [C] [V] +[H] [B] [J] [V] [B] [M] [N] [P] +[V] [F] [L] [Z] [C] [S] [P] [S] [G] +[F] [J] [M] [G] [R] [R] [H] [R] [L] +[G] [G] [G] [N] [V] [V] [T] [Q] [F] + 1 2 3 4 5 6 7 8 9 + +move 6 from 9 to 3 +move 2 from 2 to 1 +move 1 from 8 to 2 +move 3 from 7 to 2 +move 7 from 6 to 9 +move 1 from 9 to 5 +move 3 from 5 to 7 +move 6 from 8 to 6 +move 1 from 7 to 8 +move 6 from 6 to 5 +move 4 from 5 to 8 +move 9 from 2 to 9 +move 1 from 2 to 3 +move 3 from 1 to 3 +move 3 from 5 to 1 +move 10 from 3 to 5 +move 4 from 4 to 6 +move 2 from 7 to 6 +move 2 from 6 to 9 +move 6 from 8 to 6 +move 1 from 4 to 3 +move 1 from 4 to 5 +move 1 from 4 to 1 +move 2 from 3 to 1 +move 1 from 3 to 7 +move 8 from 1 to 9 +move 1 from 1 to 2 +move 1 from 2 to 7 +move 6 from 6 to 3 +move 7 from 3 to 5 +move 14 from 5 to 6 +move 2 from 1 to 3 +move 5 from 5 to 8 +move 5 from 8 to 1 +move 2 from 7 to 1 +move 5 from 6 to 9 +move 8 from 9 to 3 +move 13 from 9 to 3 +move 7 from 1 to 4 +move 6 from 4 to 1 +move 22 from 3 to 1 +move 1 from 9 to 3 +move 2 from 6 to 1 +move 1 from 3 to 4 +move 7 from 9 to 8 +move 2 from 1 to 7 +move 2 from 3 to 2 +move 2 from 6 to 9 +move 2 from 7 to 8 +move 1 from 3 to 6 +move 9 from 8 to 6 +move 1 from 2 to 4 +move 8 from 1 to 2 +move 1 from 9 to 4 +move 3 from 4 to 1 +move 1 from 4 to 6 +move 10 from 6 to 5 +move 5 from 2 to 9 +move 6 from 9 to 3 +move 2 from 5 to 3 +move 2 from 9 to 7 +move 7 from 5 to 8 +move 5 from 6 to 2 +move 3 from 3 to 7 +move 3 from 3 to 5 +move 4 from 5 to 8 +move 1 from 3 to 5 +move 6 from 6 to 8 +move 1 from 5 to 7 +move 9 from 8 to 9 +move 1 from 3 to 1 +move 7 from 2 to 7 +move 9 from 7 to 6 +move 2 from 2 to 3 +move 7 from 9 to 3 +move 9 from 6 to 8 +move 7 from 3 to 4 +move 2 from 7 to 6 +move 4 from 4 to 5 +move 3 from 5 to 6 +move 2 from 7 to 4 +move 5 from 4 to 7 +move 13 from 8 to 4 +move 2 from 9 to 4 +move 2 from 8 to 7 +move 6 from 7 to 5 +move 6 from 4 to 2 +move 1 from 7 to 5 +move 3 from 2 to 7 +move 1 from 7 to 8 +move 3 from 2 to 4 +move 2 from 3 to 9 +move 2 from 7 to 2 +move 6 from 5 to 4 +move 3 from 6 to 2 +move 2 from 6 to 9 +move 5 from 2 to 9 +move 12 from 4 to 8 +move 3 from 9 to 2 +move 12 from 1 to 5 +move 4 from 4 to 6 +move 12 from 8 to 9 +move 2 from 6 to 5 +move 1 from 4 to 8 +move 1 from 4 to 1 +move 3 from 2 to 1 +move 2 from 6 to 7 +move 1 from 5 to 9 +move 2 from 1 to 4 +move 10 from 5 to 1 +move 2 from 7 to 3 +move 18 from 9 to 7 +move 8 from 7 to 2 +move 1 from 9 to 6 +move 1 from 6 to 7 +move 10 from 7 to 9 +move 1 from 4 to 2 +move 19 from 1 to 5 +move 8 from 5 to 9 +move 3 from 8 to 4 +move 2 from 5 to 2 +move 2 from 3 to 6 +move 10 from 5 to 2 +move 4 from 1 to 2 +move 2 from 9 to 2 +move 1 from 1 to 6 +move 2 from 5 to 6 +move 1 from 8 to 7 +move 1 from 5 to 8 +move 1 from 5 to 6 +move 18 from 2 to 5 +move 5 from 2 to 1 +move 6 from 5 to 8 +move 1 from 8 to 9 +move 2 from 2 to 4 +move 1 from 2 to 6 +move 2 from 7 to 6 +move 1 from 4 to 1 +move 4 from 8 to 5 +move 1 from 2 to 9 +move 2 from 8 to 3 +move 1 from 3 to 6 +move 1 from 4 to 8 +move 1 from 8 to 9 +move 10 from 5 to 7 +move 5 from 5 to 1 +move 2 from 4 to 1 +move 3 from 7 to 6 +move 12 from 1 to 4 +move 8 from 9 to 5 +move 6 from 7 to 4 +move 1 from 7 to 9 +move 4 from 4 to 3 +move 1 from 1 to 7 +move 3 from 9 to 5 +move 2 from 3 to 1 +move 1 from 7 to 6 +move 8 from 4 to 7 +move 1 from 7 to 6 +move 7 from 6 to 4 +move 2 from 1 to 3 +move 1 from 7 to 1 +move 1 from 3 to 7 +move 1 from 1 to 6 +move 4 from 9 to 3 +move 5 from 4 to 6 +move 12 from 6 to 2 +move 3 from 9 to 4 +move 8 from 2 to 6 +move 2 from 9 to 6 +move 8 from 5 to 6 +move 4 from 5 to 8 +move 14 from 6 to 3 +move 11 from 4 to 9 +move 2 from 2 to 7 +move 8 from 3 to 9 +move 11 from 3 to 6 +move 14 from 9 to 1 +move 7 from 1 to 3 +move 2 from 9 to 5 +move 2 from 2 to 8 +move 6 from 7 to 5 +move 1 from 9 to 8 +move 13 from 6 to 3 +move 4 from 6 to 8 +move 3 from 1 to 6 +move 5 from 5 to 8 +move 7 from 8 to 7 +move 2 from 1 to 8 +move 1 from 4 to 1 +move 4 from 8 to 9 +move 8 from 7 to 5 +move 1 from 8 to 1 +move 4 from 9 to 3 +move 1 from 4 to 5 +move 5 from 5 to 2 +move 1 from 8 to 9 +move 1 from 8 to 6 +move 2 from 6 to 2 +move 4 from 8 to 6 +move 4 from 1 to 8 +move 4 from 8 to 5 +move 1 from 9 to 8 +move 1 from 2 to 3 +move 4 from 6 to 1 +move 1 from 8 to 2 +move 3 from 5 to 4 +move 4 from 2 to 5 +move 1 from 7 to 9 +move 1 from 2 to 6 +move 3 from 1 to 8 +move 2 from 4 to 5 +move 2 from 6 to 1 +move 3 from 8 to 9 +move 4 from 9 to 2 +move 1 from 7 to 1 +move 1 from 6 to 7 +move 4 from 1 to 6 +move 1 from 7 to 4 +move 6 from 2 to 8 +move 2 from 4 to 8 +move 1 from 9 to 5 +move 3 from 6 to 2 +move 1 from 6 to 4 +move 7 from 3 to 5 +move 2 from 8 to 1 +move 3 from 2 to 8 +move 6 from 8 to 5 +move 17 from 5 to 3 +move 2 from 1 to 6 +move 3 from 8 to 3 +move 1 from 9 to 5 +move 11 from 5 to 2 +move 40 from 3 to 5 +move 11 from 2 to 7 +move 4 from 7 to 8 +move 1 from 8 to 9 +move 1 from 3 to 5 +move 1 from 4 to 8 +move 19 from 5 to 8 +move 7 from 7 to 8 +move 16 from 5 to 2 +move 6 from 5 to 8 +move 1 from 5 to 8 +move 1 from 9 to 4 +move 1 from 6 to 1 +move 1 from 4 to 7 +move 1 from 6 to 9 +move 1 from 1 to 7 +move 1 from 7 to 3 +move 1 from 7 to 2 +move 1 from 9 to 8 +move 1 from 3 to 4 +move 1 from 4 to 6 +move 14 from 2 to 9 +move 24 from 8 to 4 +move 8 from 8 to 3 +move 1 from 6 to 3 +move 16 from 4 to 1 +move 3 from 8 to 4 +move 3 from 3 to 8 +move 4 from 3 to 4 +move 1 from 3 to 9 +move 13 from 9 to 4 +move 16 from 1 to 8 +move 8 from 8 to 1 +move 3 from 1 to 7 +move 1 from 8 to 6 +move 1 from 3 to 8 +move 10 from 8 to 5 +move 5 from 5 to 2 +move 3 from 8 to 9 +move 1 from 8 to 9 +move 1 from 4 to 5 +move 5 from 2 to 6 +move 3 from 5 to 2 +move 1 from 6 to 1 +move 5 from 1 to 5 +move 1 from 1 to 5 +move 2 from 7 to 3 +move 2 from 3 to 2 +move 1 from 5 to 7 +move 7 from 5 to 3 +move 5 from 9 to 5 +move 2 from 7 to 9 +move 4 from 5 to 6 +move 2 from 9 to 8 +move 2 from 2 to 4 +move 5 from 3 to 5 +move 1 from 3 to 2 +move 7 from 4 to 9 +move 1 from 8 to 1 +move 1 from 2 to 1 +move 9 from 4 to 6 +move 2 from 1 to 8 +move 1 from 3 to 9 +move 2 from 8 to 6 +move 13 from 4 to 6 +move 1 from 8 to 7 +move 2 from 9 to 6 +move 3 from 5 to 7 +move 3 from 2 to 5 +move 3 from 2 to 6 +move 5 from 6 to 2 +move 4 from 2 to 5 +move 4 from 5 to 7 +move 5 from 5 to 7 +move 7 from 9 to 6 +move 6 from 7 to 2 +move 22 from 6 to 5 +move 10 from 5 to 8 +move 7 from 5 to 4 +move 8 from 8 to 5 +move 18 from 6 to 2 +move 5 from 7 to 5 +move 1 from 8 to 2 +move 6 from 5 to 1 +move 7 from 4 to 2 +move 4 from 1 to 5 +move 1 from 7 to 9 +move 1 from 8 to 6 +move 1 from 7 to 8 +move 10 from 5 to 9 +move 12 from 2 to 1 +move 8 from 5 to 2 +move 19 from 2 to 9 +move 1 from 6 to 8 +move 13 from 9 to 3 +move 8 from 1 to 2 +move 5 from 1 to 3 +move 10 from 2 to 1 +move 7 from 2 to 5 +move 3 from 5 to 7 +move 4 from 1 to 3 +move 1 from 2 to 3 +move 3 from 1 to 2 +move 1 from 8 to 6 +move 2 from 7 to 5 +move 4 from 1 to 3 +move 6 from 5 to 4 +move 2 from 2 to 1 +move 1 from 2 to 9 +move 6 from 4 to 5 +move 5 from 5 to 9 +move 1 from 6 to 8 +move 1 from 5 to 1 +move 6 from 9 to 2 +move 5 from 2 to 4 +move 3 from 1 to 6 +move 2 from 4 to 7 +move 22 from 3 to 9 +move 1 from 8 to 4 +move 2 from 4 to 3 +move 2 from 6 to 1 +move 2 from 1 to 5 +move 1 from 6 to 7 +move 1 from 7 to 4 +move 6 from 3 to 7 +move 1 from 2 to 4 +move 8 from 7 to 3 +move 1 from 4 to 5 +move 1 from 7 to 9 +move 5 from 3 to 6 +move 1 from 8 to 4 +move 4 from 3 to 2 +move 32 from 9 to 3 +move 3 from 6 to 7 +move 5 from 9 to 3 +move 1 from 9 to 7 +move 2 from 9 to 2 +move 2 from 4 to 3 +move 2 from 5 to 4 +move 5 from 3 to 2 +move 3 from 7 to 8 +move 1 from 7 to 2 +move 1 from 8 to 5 +move 1 from 3 to 4 +move 5 from 4 to 5 +move 4 from 5 to 2 +move 3 from 5 to 7 +move 1 from 7 to 5 +move 1 from 6 to 5 +move 2 from 8 to 5 +move 15 from 2 to 4 +move 3 from 5 to 6 +move 4 from 6 to 5 +move 2 from 5 to 2 +move 1 from 2 to 4 +move 25 from 3 to 9 +move 2 from 5 to 2 +move 11 from 9 to 2 +move 13 from 2 to 1 +move 4 from 4 to 7 +move 12 from 9 to 8 +move 6 from 7 to 8 +move 7 from 4 to 7 +move 7 from 7 to 8 +move 1 from 5 to 1 +move 5 from 4 to 3 +move 2 from 2 to 1 +move 2 from 9 to 5 +move 7 from 1 to 7 +move 1 from 1 to 4 +move 12 from 3 to 2 +move 1 from 3 to 9 +move 1 from 1 to 3 +move 1 from 9 to 1 +move 7 from 7 to 2 +move 1 from 4 to 7 +move 2 from 8 to 7 +move 7 from 1 to 2 +move 1 from 3 to 4 +move 26 from 2 to 1 +move 4 from 8 to 1 +move 3 from 1 to 6 +move 1 from 6 to 3 +move 1 from 6 to 9 +move 1 from 3 to 8 +move 20 from 1 to 3 +move 1 from 9 to 7 +move 4 from 7 to 1 +move 1 from 5 to 3 +move 4 from 3 to 5 +move 1 from 6 to 2 +move 6 from 3 to 2 +move 8 from 1 to 4 +move 1 from 1 to 5 +move 3 from 1 to 4 +move 7 from 2 to 4 +move 10 from 3 to 8 +move 4 from 4 to 3 +move 12 from 4 to 7 +move 3 from 3 to 1 +move 2 from 4 to 3 +move 2 from 8 to 1 +move 6 from 8 to 9 +move 5 from 9 to 6 +move 1 from 9 to 3 +move 3 from 8 to 7 +move 10 from 8 to 5 +move 4 from 8 to 7 +move 9 from 7 to 9 +move 4 from 8 to 4 +move 2 from 4 to 3 +move 3 from 1 to 7 +move 11 from 7 to 4 +move 6 from 4 to 8 +move 1 from 7 to 3 +move 4 from 5 to 1 +move 5 from 3 to 6 +move 5 from 9 to 4 +move 1 from 9 to 8 +move 10 from 4 to 8 +move 5 from 1 to 2 +move 1 from 7 to 6 +move 9 from 6 to 3 +move 7 from 8 to 7 +move 3 from 4 to 1 +move 2 from 2 to 1 +move 9 from 8 to 3 +move 10 from 5 to 8 +move 18 from 3 to 9 +move 1 from 7 to 8 +move 1 from 5 to 3 +move 4 from 8 to 3 +move 2 from 6 to 3 +move 6 from 7 to 2 +move 1 from 5 to 3 +move 1 from 1 to 9 +move 10 from 3 to 9 +move 4 from 1 to 8 +move 13 from 8 to 1 +move 3 from 1 to 8 +move 3 from 2 to 4 +move 5 from 2 to 6 +move 5 from 6 to 4 +move 28 from 9 to 2 +move 2 from 9 to 5 +move 2 from 5 to 2 +move 1 from 3 to 7 +move 2 from 1 to 4 +move 3 from 8 to 3 +move 1 from 9 to 4 +move 3 from 4 to 6 +move 2 from 3 to 7 +move 8 from 1 to 5 +move 3 from 7 to 6 +move 14 from 2 to 8 +move 1 from 9 to 1 +move 6 from 5 to 6 +move 4 from 2 to 5 +move 9 from 8 to 2 +move 4 from 8 to 4 +move 7 from 2 to 4 +move 12 from 4 to 3 +move 5 from 4 to 7 +move 5 from 7 to 4 +move 1 from 8 to 7 +move 1 from 4 to 5 +move 2 from 5 to 4 +move 1 from 5 to 8 +move 1 from 5 to 9 diff --git a/src/main.rs b/src/main.rs index 3f072e5..e14ce36 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,30 @@ use std::collections::HashSet; use std::fs; -use std::{cmp::Ordering, ops::RangeInclusive as Range}; +use std::ops::RangeInclusive as Range; +use std::{cmp::Ordering, fmt::Display}; use anyhow::Error; use chrono::{Datelike, Local}; use pico_args::Arguments; +fn main() -> Result<(), Error> { + let mut args = Arguments::from_env(); + let small = args.contains("--small"); + let part = args.opt_free_from_str()?.unwrap_or(1); + let day = args + .opt_free_from_str()? + .unwrap_or_else(|| Local::now().day()); + let small = if small { ".small" } else { "" }; + let path = format!("inputs/{day}{small}.txt"); + let input = fs::read_to_string(path)?; + println!("running day {day} part {part}"); + let result = SOLUTIONS[day as usize - 1][part as usize - 1](input); + println!("{result}"); + Ok(()) +} + macro_rules! solutions { - ($($all:tt),*) => { + ($($all:expr),*) => { const DAYS: usize = 0 $( + solutions!(@expand $all 1) )*; const SOLUTIONS: [Day; DAYS] = [ $($all),* @@ -16,7 +33,33 @@ macro_rules! solutions { (@expand $ignore:tt $e:expr) => {$e}; } -type Part = fn(String) -> u64; +enum Output { + Num(u64), + Str(String), +} + +impl Display for Output { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Output::Num(n) => write!(f, "{n}"), + Output::Str(s) => write!(f, "{s}"), + } + } +} + +impl From for Output { + fn from(n: u64) -> Self { + Self::Num(n) + } +} + +impl From for Output { + fn from(s: String) -> Self { + Self::Str(s) + } +} + +type Part = fn(String) -> Output; type Day = [Part; 2]; solutions! { [ @@ -31,7 +74,7 @@ solutions! { (max, sum + cal) } }); - max + max.into() }, // day 1 part 2 |input| { @@ -52,7 +95,7 @@ solutions! { (a, b, c, sum + cal) } }); - a + b + c + (a + b + c).into() }, ], [ @@ -65,7 +108,7 @@ solutions! { let (you, me) = (RPS::from_str(you), RPS::from_str(me)); RPS::score(you, me) }) - .sum() + .sum::().into() }, // day 2 part 2 |input| { @@ -77,7 +120,7 @@ solutions! { let me = out.requires(you); RPS::score(you, me) }) - .sum() + .sum::().into() }, ], [ @@ -90,7 +133,7 @@ solutions! { let rs = Rucksack::new(line); rs.score() }) - .sum() + .sum::().into() }, // day 3 part 2 |input| { @@ -105,47 +148,118 @@ solutions! { } _ => unreachable!("fooey"), }) - .sum() + .sum::().into() }, ], [ // day 4 part 1 |input| { - make_ranges(input) + (make_ranges(input) .iter() - .map(|(first, second)| { + .filter(|(first, second)| { range_contains(first, second) || range_contains(second, first) }) - .map(|b| if b { 1 } else { 0 }) - .sum() + .count() as u64).into() }, // day 4 part 2 |input| { - make_ranges(input) + (make_ranges(input) .iter() - .map(|(first, second)| { - range_overlaps(first, second) || range_overlaps(second, first) - }) - .map(|b| if b { 1 } else { 0 }) - .sum() + .filter(|(first, second)| range_overlaps(first, second) || range_overlaps(second, first)) + .count() as u64).into() + }, + ], + [ + // day 5 part 1 + |input| { + let midpt = input.find("\n\n").unwrap(); + let stacks = make_stacks(&input[..=midpt]); + let rules = make_rules(&input[midpt + 2..]); + run_rules(stacks, rules).into() + }, + // day 5 part 2 + |input| { + let midpt = input.find("\n\n").unwrap(); + let stacks = make_stacks(&input[..=midpt]); + let rules = make_rules(&input[midpt + 2..]); + run_rules_9001(stacks, rules).into() }, ] } -fn main() -> Result<(), Error> { - let mut args = Arguments::from_env(); - let small = args.contains("--small"); - let part = args.opt_free_from_str()?.unwrap_or(1); - let day = args - .opt_free_from_str()? - .unwrap_or_else(|| Local::now().day()); - let small = if small { ".small" } else { "" }; - let path = format!("inputs/{day}{small}.txt"); - let input = fs::read_to_string(path)?; - println!("running day {day} part {part}"); - let result = SOLUTIONS[day as usize - 1][part as usize - 1](input); - println!("{result}"); - Ok(()) +fn run_rules_9001(mut stacks: Vec>, rules: Vec) -> String { + for rule in rules { + let total = stacks[rule.from - 1].len(); + let mut moved = stacks[rule.from - 1].drain((total - rule.n)..).collect(); + stacks[rule.to - 1].append(&mut moved); + } + let mut s = String::new(); + for stack in stacks { + s.push(*stack.last().unwrap()) + } + s +} + +fn run_rules(mut stacks: Vec>, rules: Vec) -> String { + for rule in rules { + for _ in 0..rule.n { + let c = stacks[rule.from - 1].pop().unwrap(); + stacks[rule.to - 1].push(c); + } + } + let mut s = String::new(); + for stack in stacks { + s.push(*stack.last().unwrap()) + } + s +} + +fn make_stacks(input: &str) -> Vec> { + let n = (input.find('\n').unwrap()) / 4 + 1; + let mut stacks = vec![vec![]; n]; + input + .lines() + .rev() + .filter(|line| line.trim().starts_with('[')) + .for_each(|line| { + for (idx, cr8) in line.chars().skip(1).step_by(4).enumerate() { + if cr8 != ' ' { + stacks[idx].push(cr8); + } + } + }); + stacks +} + +#[derive(Debug)] +struct Rule { + n: usize, + from: usize, + to: usize, +} + +impl Rule { + fn new(raw: Vec) -> Self { + Self { + n: raw[0], + from: raw[1], + to: raw[2], + } + } +} + +fn make_rules(input: &str) -> Vec { + input + .lines() + .map(|line| { + line.split_whitespace() + .skip(1) + .step_by(2) + .map(|num| num.parse::().unwrap()) + .collect() + }) + .map(Rule::new) + .collect() } fn make_ranges(input: String) -> Vec<(Range, Range)> {