day 13
This commit is contained in:
parent
907593e2e1
commit
c0407504c4
130
src/days/day13.rs
Normal file
130
src/days/day13.rs
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
use std::{cmp::Ordering, fmt::Debug};
|
||||||
|
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
use itertools::{EitherOrBoth, Itertools};
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
|
enum Data {
|
||||||
|
Integer(u32),
|
||||||
|
List(Vec<Data>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Data {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Integer(i) => write!(f, "{i}"),
|
||||||
|
Self::List(l) => f.debug_list().entries(l).finish(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Data {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Data {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(Data::Integer(a), Data::Integer(b)) => a.cmp(b),
|
||||||
|
(a @ Data::Integer(_), b @ Data::List(_)) => b.cmp(a).reverse(),
|
||||||
|
(a @ Data::List(_), Data::Integer(b)) => {
|
||||||
|
a.cmp(&Data::List(Vec::from([Data::Integer(*b)])))
|
||||||
|
}
|
||||||
|
(Data::List(a), Data::List(b)) => a
|
||||||
|
.iter()
|
||||||
|
.zip_longest(b)
|
||||||
|
.find_map(|els| match els {
|
||||||
|
EitherOrBoth::Both(a, b) => {
|
||||||
|
let res = a.cmp(b);
|
||||||
|
(!res.is_eq()).then_some(res)
|
||||||
|
}
|
||||||
|
EitherOrBoth::Left(_) => Some(Ordering::Greater),
|
||||||
|
EitherOrBoth::Right(_) => Some(Ordering::Less),
|
||||||
|
})
|
||||||
|
.unwrap_or(Ordering::Equal),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Data {
|
||||||
|
fn parse(s: &str) -> Option<(Self, &str)> {
|
||||||
|
if let Some(mut rest) = s.strip_prefix('[') {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(rest) = rest.strip_prefix(']') {
|
||||||
|
return Some((Self::List(vec), rest));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (val, rest2) = Self::parse(rest)?;
|
||||||
|
vec.push(val);
|
||||||
|
|
||||||
|
if let Some(rest) = rest2.strip_prefix(']') {
|
||||||
|
return Some((Self::List(vec), rest));
|
||||||
|
}
|
||||||
|
|
||||||
|
let rest2 = rest2.strip_prefix(',')?;
|
||||||
|
rest = rest2;
|
||||||
|
}
|
||||||
|
} else if s.chars().next()?.is_alphanumeric() {
|
||||||
|
let (num_part, rest) = s
|
||||||
|
.char_indices()
|
||||||
|
.find_map(|(i, c)| (!c.is_numeric()).then_some(s.split_at(i)))
|
||||||
|
.unwrap_or((s, ""));
|
||||||
|
|
||||||
|
Some((Self::Integer(num_part.parse().ok()?), rest))
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_generator(day13)]
|
||||||
|
fn generator(input: &str) -> Vec<(Data, Data)> {
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.chunks(3)
|
||||||
|
.into_iter()
|
||||||
|
.map(|mut v| {
|
||||||
|
(
|
||||||
|
Data::parse(v.next().unwrap()).unwrap().0,
|
||||||
|
Data::parse(v.next().unwrap()).unwrap().0,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day13, part1)]
|
||||||
|
fn part1(input: &[(Data, Data)]) -> usize {
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.positions(|(a, b)| a < b)
|
||||||
|
.map(|v| v + 1) // adjust for one-indexing
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day13, part2)]
|
||||||
|
fn part2(input: &[(Data, Data)]) -> usize {
|
||||||
|
let mut vec = input
|
||||||
|
.iter()
|
||||||
|
.flat_map(|(a, b)| [a.clone(), b.clone()])
|
||||||
|
.map(|v| (v, false))
|
||||||
|
.chain([
|
||||||
|
(Data::parse("[[2]]").unwrap().0, true),
|
||||||
|
(Data::parse("[[6]]").unwrap().0, true),
|
||||||
|
])
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
vec.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
|
||||||
|
let (i, j) = vec
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, (_, is_divider))| is_divider.then_some(i + 1))
|
||||||
|
.next_tuple()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
i * j
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ mod days {
|
||||||
mod day10;
|
mod day10;
|
||||||
mod day11;
|
mod day11;
|
||||||
mod day12;
|
mod day12;
|
||||||
|
mod day13;
|
||||||
}
|
}
|
||||||
|
|
||||||
aoc_lib! { year = 2022 }
|
aoc_lib! { year = 2022 }
|
||||||
|
|
Loading…
Reference in a new issue