From d11ba120b891df5a26dff066f8297bfc2d5f2885 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 13 Dec 2022 10:43:36 +0200 Subject: Day 13 --- 2022/src/bin/day_13.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 2022/src/bin/day_13.rs (limited to '2022/src/bin') diff --git a/2022/src/bin/day_13.rs b/2022/src/bin/day_13.rs new file mode 100644 index 0000000..b00d790 --- /dev/null +++ b/2022/src/bin/day_13.rs @@ -0,0 +1,146 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{line_ending, u32}, + combinator::map, + multi::{separated_list0, separated_list1}, + sequence::{delimited, pair, preceded}, + IResult, +}; +use std::{cmp::Ordering, fs}; + +fn main() -> Result<(), Box> { + let input = fs::read_to_string("inputs/day_13.txt")?; + let message = EncodedMessage::parser(&input).unwrap().1; + + dbg!(message.ordered_index_sum()); + dbg!(message.decoder_key()); + + Ok(()) +} + +#[derive(Debug)] +struct EncodedMessage { + message_pairs: Vec<(Message, Message)>, + ordered_indices: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Message { + List(Vec), + Value(u32), +} + +impl EncodedMessage { + fn parser(input: &str) -> IResult<&str, Self> { + map( + separated_list1( + pair(line_ending, line_ending), + pair(Message::parser, preceded(line_ending, Message::parser)), + ), + EncodedMessage::new, + )(input) + } + + fn new(message_pairs: Vec<(Message, Message)>) -> EncodedMessage { + let mut ordered_indices = Vec::new(); + + for (i, (left, right)) in message_pairs.iter().enumerate() { + if left <= right { + ordered_indices.push(i + 1); + } + } + EncodedMessage { + message_pairs, + ordered_indices, + } + } + + fn ordered_index_sum(&self) -> usize { + self.ordered_indices.iter().sum() + } + + fn decoder_key(&self) -> usize { + let mut all_packets: Vec = self + .message_pairs + .iter() + .flat_map(|(left, right)| [left.clone(), right.clone()]) + .collect(); + let divider_1 = Message::List(vec![Message::List(vec![Message::Value(2)])]); + let divider_2 = Message::List(vec![Message::List(vec![Message::Value(6)])]); + all_packets.push(divider_1.clone()); + all_packets.push(divider_2.clone()); + + all_packets.sort(); + + let index_1 = all_packets.iter().position(|m| *m == divider_1).unwrap() + 1; + let index_2 = all_packets.iter().position(|m| *m == divider_2).unwrap() + 1; + index_1 * index_2 + } +} + +impl Message { + fn parser(input: &str) -> IResult<&str, Self> { + alt(( + map(u32, Message::Value), + map( + delimited( + tag("["), + separated_list0(tag(","), Message::parser), + tag("]"), + ), + Message::List, + ), + ))(input) + } +} + +impl PartialOrd for Message { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Message { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (Message::Value(left), Message::Value(right)) => left.cmp(right), + (Message::List(left), Message::List(right)) => { + for i in 0..left.len() { + if i == right.len() { + return Ordering::Greater; + } + let inner_ord = left[i].cmp(&right[i]); + if inner_ord != Ordering::Equal { + return inner_ord; + } + } + left.len().cmp(&right.len()) + } + (Message::Value(left), Message::List(right)) => { + if right.len() == 0 { + Ordering::Greater + } else { + let inner_ord = Message::Value(*left).cmp(&right[0]); + if inner_ord != Ordering::Equal { + inner_ord + } else { + 1.cmp(&right.len()) + } + } + } + (Message::List(left), Message::Value(right)) => { + if left.len() == 0 { + Ordering::Less + } else { + let inner_ord = left[0].cmp(&Message::Value(*right)); + if inner_ord != Ordering::Equal { + inner_ord + } else { + left.len().cmp(&1) + } + } + } + } + } +} -- cgit v1.2.3