Add solution for 2022 day 13 part 2

This commit is contained in:
Patrick Auernig 2022-12-14 23:31:00 +01:00
parent 1b28bf1848
commit 2896afdb8c
5 changed files with 102 additions and 55 deletions

View File

@ -16,7 +16,7 @@
| [10] | ✓ | ✓ | [Rust] |
| [11] | ✓ | | [Rust] |
| [12] | ✓ | ✓ | [Rust] |
| [13] | ✓ | | [Rust] |
| [13] | ✓ | | [Rust] |
| [14] | | | |
| [15] | | | |
| [16] | | | |

View File

@ -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<u32> {
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::<usize>();
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::*;

View File

@ -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<u32> {
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(&divider_a);
packets.push(&divider_b);
packets.sort();
let result = packets
.iter()
.enumerate()
.filter_map(|(idx, &val)| {
if val == &divider_a || val == &divider_b {
Some(idx + 1)
} else {
None
}
})
.product::<usize>();
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);
}
}

View File

@ -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<Segment>),
}
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<Ordering> {
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<P>(path: P) -> io::Result<Vec<Pair>>
where
P: AsRef<Path>,

View File

@ -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)