Day 13, puzzle 1

This commit is contained in:
jazzpi 2022-12-16 00:58:34 +01:00
parent 36ceda33db
commit 57f4bc2732
3 changed files with 131 additions and 0 deletions

14
src/bin/d13p1.rs Normal file
View File

@ -0,0 +1,14 @@
use aoc22::{day13, util};
pub fn main() {
let pairs = day13::parse_pairs(&util::parse_input());
let mut sum = 0;
for (i, pair) in pairs.iter().enumerate() {
if pair.0 < pair.1 {
sum += i + 1;
}
}
println!("Sum of indices of pairs in right order: {}", sum);
}

116
src/day13.rs Normal file
View File

@ -0,0 +1,116 @@
use std::cmp::Ordering;
use itertools::{EitherOrBoth, Itertools};
#[derive(Debug)]
pub enum Node {
List(Vec<Node>),
Num(usize),
}
impl PartialOrd for Node {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self {
Node::List(l1) => match other {
Node::Num(n2) => self.partial_cmp(&Node::List(vec![Node::Num(*n2)])),
Node::List(l2) => {
for pair in l1.iter().zip_longest(l2.iter()) {
match pair {
EitherOrBoth::Both(n1, n2) => {
if n1 < n2 {
return Some(Ordering::Less);
} else if n2 < n1 {
return Some(Ordering::Greater);
}
}
EitherOrBoth::Left(_) => return Some(Ordering::Greater),
EitherOrBoth::Right(_) => return Some(Ordering::Less),
}
}
Some(Ordering::Equal)
}
},
Node::Num(n1) => match other {
Node::Num(n2) => n1.partial_cmp(n2),
Node::List(_) => Node::List(vec![Node::Num(*n1)]).partial_cmp(other),
},
}
}
}
impl PartialEq for Node {
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(Ordering::Equal)
}
fn ne(&self, other: &Self) -> bool {
!self.eq(other)
}
}
pub fn parse_pairs(input: &String) -> Vec<(Node, Node)> {
let mut result = Vec::new();
for mut p in &input.lines().chunks(3) {
let first = parse_list(p.next().unwrap()).0;
let second = parse_list(p.next().unwrap()).0;
assert!(p.next().unwrap_or("").is_empty());
result.push((first, second));
}
result
}
enum ParseState {
Idle,
InNumber,
}
fn parse_list(line: &str) -> (Node, usize) {
assert_eq!(line.chars().next(), Some('['));
let mut state = ParseState::Idle;
let mut i = 1;
let mut result = Vec::new();
let mut num_start = 0;
while i < line.len() {
let c = line.chars().nth(i).unwrap();
match state {
ParseState::Idle => {
if c == '[' {
let (n, inc) = parse_list(&line[i..]);
result.push(n);
i += inc;
} else if c == ']' {
// End of list reached
break;
} else if c.is_numeric() {
num_start = i;
state = ParseState::InNumber;
} else if c != ',' {
panic!("Unknown char: {}", c);
}
}
ParseState::InNumber => {
if c == ',' {
let slice = &line[num_start..i];
result.push(Node::Num(slice.parse().unwrap()));
state = ParseState::Idle;
} else if c == ']' {
// End of list reached
let slice = &line[num_start..i];
result.push(Node::Num(slice.parse().unwrap()));
break;
} else if !c.is_numeric() {
panic!("Unknown digit {}", c);
}
}
}
i += 1;
}
(Node::List(result), i)
}

View File

@ -2,6 +2,7 @@ pub mod day1;
pub mod day10;
pub mod day11;
pub mod day12;
pub mod day13;
pub mod day2;
pub mod day3;
pub mod day4;