From 2896afdb8c92019a446fb2175fd14c52a19c96f5 Mon Sep 17 00:00:00 2001 From: Patrick Auernig Date: Wed, 14 Dec 2022 23:31:00 +0100 Subject: [PATCH] Add solution for 2022 day 13 part 2 --- 2022/README.md | 2 +- 2022/day-13/src/bin/part_one.rs | 54 ++---------------------------- 2022/day-13/src/bin/part_two.rs | 58 +++++++++++++++++++++++++++++++++ 2022/day-13/src/lib.rs | 41 ++++++++++++++++++++++- README.md | 2 +- 5 files changed, 102 insertions(+), 55 deletions(-) create mode 100644 2022/day-13/src/bin/part_two.rs diff --git a/2022/README.md b/2022/README.md index 5ff430b..61e8255 100644 --- a/2022/README.md +++ b/2022/README.md @@ -16,7 +16,7 @@ | [10] | ✓ | ✓ | [Rust] | | [11] | ✓ | | [Rust] | | [12] | ✓ | ✓ | [Rust] | -| [13] | ✓ | | [Rust] | +| [13] | ✓ | ✓ | [Rust] | | [14] | | | | | [15] | | | | | [16] | | | | diff --git a/2022/day-13/src/bin/part_one.rs b/2022/day-13/src/bin/part_one.rs index d632849..9b89f71 100644 --- a/2022/day-13/src/bin/part_one.rs +++ b/2022/day-13/src/bin/part_one.rs @@ -1,6 +1,6 @@ use std::{env, io}; -use aoc_2022_13::{parse_input, Pair, Segment}; +use aoc_2022_13::parse_input; fn main() -> io::Result<()> { let infile_path = env::args().nth(1).expect("input file"); @@ -17,62 +17,12 @@ fn solve(path: &str) -> io::Result { let result = pairs .iter() .enumerate() - .filter_map(|(i, pair)| match is_in_right_order(&pair) { - Ordered::Yes => Some(i + 1), - _ => None, - }) + .filter_map(|(i, (a, b))| if a < b { Some(i + 1) } else { None }) .sum::(); Ok(result as u32) } -#[derive(Debug)] -enum Ordered { - Undecided, - Yes, - No, -} - -fn is_in_right_order((left, right): &Pair) -> Ordered { - test_segment(left, right) -} - -fn test_segment(left: &Segment, right: &Segment) -> Ordered { - match (left, right) { - (Segment::Num(lval), Segment::Num(rval)) => test_segment_num(*lval, *rval), - (Segment::List(lval), Segment::List(rval)) => test_segment_list(lval, rval), - (Segment::List(lval), rval @ Segment::Num(_)) => test_segment_list(lval, &[rval.clone()]), - (lval @ Segment::Num(_), Segment::List(rval)) => test_segment_list(&[lval.clone()], rval), - } -} - -fn test_segment_list(left: &[Segment], right: &[Segment]) -> Ordered { - let mut left = left.iter(); - let mut right = right.iter(); - - loop { - match (left.next(), right.next()) { - (Some(lval), Some(rval)) => match test_segment(lval, rval) { - Ordered::Undecided => (), - ord => return ord, - }, - (None, Some(_)) => return Ordered::Yes, - (Some(_), None) => return Ordered::No, - (None, None) => return Ordered::Undecided, - } - } -} - -fn test_segment_num(left: u32, right: u32) -> Ordered { - if left < right { - Ordered::Yes - } else if left == right { - Ordered::Undecided - } else { - Ordered::No - } -} - #[cfg(test)] mod test { use super::*; diff --git a/2022/day-13/src/bin/part_two.rs b/2022/day-13/src/bin/part_two.rs new file mode 100644 index 0000000..1e665da --- /dev/null +++ b/2022/day-13/src/bin/part_two.rs @@ -0,0 +1,58 @@ +use std::{env, io}; + +use aoc_2022_13::{parse_input, Segment}; + +fn main() -> io::Result<()> { + let infile_path = env::args().nth(1).expect("input file"); + + let result = solve(&infile_path)?; + + println!("{result}"); + + Ok(()) +} + +fn solve(path: &str) -> io::Result { + let pairs = parse_input(path)?; + let mut packets = pairs.iter().fold(vec![], |mut acc, (a, b)| { + acc.extend([a, b]); + acc + }); + let divider_a = Segment::List(vec![Segment::List(vec![Segment::Num(2)])]); + let divider_b = Segment::List(vec![Segment::List(vec![Segment::Num(6)])]); + packets.push(÷r_a); + packets.push(÷r_b); + + packets.sort(); + + let result = packets + .iter() + .enumerate() + .filter_map(|(idx, &val)| { + if val == ÷r_a || val == ÷r_b { + Some(idx + 1) + } else { + None + } + }) + .product::(); + + Ok(result as u32) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn sample() { + let result = solve("inputs/test.txt").unwrap(); + assert_eq!(140, result); + } + + #[test] + fn puzzle() { + let result = solve("inputs/puzzle.txt").unwrap(); + assert_eq!(29025, result); + } +} diff --git a/2022/day-13/src/lib.rs b/2022/day-13/src/lib.rs index 04023d9..ba77faf 100644 --- a/2022/day-13/src/lib.rs +++ b/2022/day-13/src/lib.rs @@ -1,4 +1,5 @@ use std::{ + cmp::Ordering, fmt, fs::File, io::{self, Read}, @@ -7,12 +8,33 @@ use std::{ pub type Pair = (Segment, Segment); -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq)] pub enum Segment { Num(u32), List(Vec), } +impl Ord for Segment { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (Segment::Num(lval), Segment::Num(rval)) => lval.cmp(rval), + (Segment::List(lval), Segment::List(rval)) => test_segment_list(lval, rval), + (Segment::List(lval), rval @ Segment::Num(_)) => { + test_segment_list(lval, &[rval.clone()]) + } + (lval @ Segment::Num(_), Segment::List(rval)) => { + test_segment_list(&[lval.clone()], rval) + } + } + } +} + +impl PartialOrd for Segment { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} + impl fmt::Debug for Segment { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -22,6 +44,23 @@ impl fmt::Debug for Segment { } } +fn test_segment_list(left: &[Segment], right: &[Segment]) -> Ordering { + let mut left = left.iter(); + let mut right = right.iter(); + + loop { + match (left.next(), right.next()) { + (Some(lval), Some(rval)) => match lval.cmp(rval) { + Ordering::Equal => (), + ord => return ord, + }, + (None, Some(_)) => return Ordering::Less, + (Some(_), None) => return Ordering::Greater, + (None, None) => return Ordering::Equal, + } + } +} + pub fn parse_input

(path: P) -> io::Result> where P: AsRef, diff --git a/README.md b/README.md index 1952ea5..9084cda 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,4 @@ - [2019](2019/README.md) (0% completed) - [2020](2020/README.md) (20% completed) - [2021](2021/README.md) (68% completed) -- [2022](2022/README.md) (48% completed) +- [2022](2022/README.md) (50% completed)