diff --git a/2022/day13/rust/Cargo.toml b/2022/day13/rust/Cargo.toml new file mode 100644 index 0000000..1f5ecec --- /dev/null +++ b/2022/day13/rust/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rust_2022_13" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../../../common/rust" } +nom = "7.1.1" diff --git a/2022/day13/rust/src/main.rs b/2022/day13/rust/src/main.rs new file mode 100644 index 0000000..5269f05 --- /dev/null +++ b/2022/day13/rust/src/main.rs @@ -0,0 +1,78 @@ +#![warn(clippy::pedantic)] + +use nom::Parser; +use std::io::{stdin, Read}; + +use nom::{ + branch::alt, bytes::complete::tag, character::complete::u32, multi::separated_list0, + sequence::delimited, IResult, +}; + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Data { + List(Vec), + Number(usize), +} + +impl PartialOrd for Data { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Data { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + match (self, other) { + (Data::List(l), Data::List(r)) => l.as_slice().cmp(r), + (Data::List(l), r @ Data::Number(_)) => l.iter().cmp([r]), + (l @ Data::Number(_), Data::List(r)) => [l].into_iter().cmp(r.iter()), + (Data::Number(l), Data::Number(r)) => l.cmp(r), + } + } +} + +fn parse_data(s: &str) -> IResult<&str, Data, ()> { + alt(( + delimited(tag("["), separated_list0(tag(","), parse_data), tag("]")).map(Data::List), + u32.map(|i| Data::Number(usize::try_from(i).unwrap())), + ))(s) +} + +fn main() { + let mut data = String::new(); + stdin().read_to_string(&mut data).unwrap(); + + let pairs: Vec<_> = data + .split("\n\n") + .map(|pair| { + let (left, right) = pair.split_once('\n').unwrap(); + (parse_data(left).unwrap().1, parse_data(right).unwrap().1) + }) + .collect(); + + let sum: usize = pairs + .iter() + .enumerate() + .filter_map(|(i, (left, right))| (left <= right).then_some(i + 1)) + .sum(); + + println!("{}", sum); + + let mut sorted: Vec<_> = pairs + .into_iter() + .flat_map(|(left, right)| [left, right]) + .collect(); + let divider = |divider| Data::List(vec![Data::List(vec![Data::Number(divider)])]); + sorted.push(divider(2)); + sorted.push(divider(6)); + sorted.sort(); + + let index = |divider| { + sorted + .binary_search(&Data::List(vec![Data::List(vec![Data::Number(divider)])])) + .unwrap() + + 1 + }; + + println!("{}", index(2) * index(6)); +} diff --git a/Cargo.lock b/Cargo.lock index 16da635..656a1d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -585,6 +585,14 @@ dependencies = [ "petgraph", ] +[[package]] +name = "rust_2022_13" +version = "0.1.0" +dependencies = [ + "aoc", + "nom", +] + [[package]] name = "ryu" version = "1.0.11" diff --git a/Cargo.toml b/Cargo.toml index 7cae5b0..6c93ccb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,5 @@ members = [ "2022/day10/rust", "2022/day11/rust", "2022/day12/rust", + "2022/day13/rust", ]