1
0
Fork 0
advent-of-code/2022/src/days/day13.rs

83 lines
2.2 KiB
Rust

use anyhow::Result;
use std::cmp::Ordering;
use std::fs;
#[derive(Debug, Clone, Eq, PartialEq)]
enum Packet {
Num(i32),
List(Vec<Packet>),
}
fn parse(s: &str) -> Packet {
if &s[0..1] == "[" {
let mut stack: i32 = 0;
Packet::List(
s[1..s.len() - 1]
.split(|c| {
if c == '[' {
stack += 1
} else if c == ']' {
stack -= 1
}
c == ',' && stack == 0
})
.filter_map(|s| (!s.is_empty()).then(|| parse(s)))
.collect(),
)
} else {
Packet::Num(s.parse().unwrap())
}
}
impl Ord for Packet {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Packet::Num(a), Packet::Num(b)) => a.cmp(b),
(Packet::Num(_), _) => Packet::List(vec![self.clone()]).cmp(other),
(_, Packet::Num(_)) => self.cmp(&Packet::List(vec![other.clone()])),
(Packet::List(a), Packet::List(b)) => a.cmp(b),
}
}
}
impl PartialOrd for Packet {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub fn run() -> Result<()> {
#[cfg(not(feature = "test_input"))]
let file_contents = fs::read_to_string("day13.txt")?;
#[cfg(feature = "test_input")]
let file_contents = fs::read_to_string("tests/day13.txt")?;
let mut packets: Vec<Packet> = file_contents
.trim()
.lines()
.filter_map(|s| (!s.is_empty()).then(|| parse(s)))
.collect();
let mut part1 = 0;
for (packet_index, packet_pair) in packets.chunks(2).enumerate() {
let o = packet_pair[0].cmp(&packet_pair[1]);
assert!(o != Ordering::Equal);
if o == Ordering::Less {
part1 += packet_index + 1;
}
}
println!("part one: {}", part1);
let div1 = parse("[[2]]");
let div2 = parse("[[6]]");
packets.push(div1.clone());
packets.push(div2.clone());
packets.sort();
let i1 = packets.binary_search(&div1).unwrap() + 1;
let i2 = packets.binary_search(&div2).unwrap() + 1;
println!("part two: {} * {} = {}", i1, i2, i1 * i2);
Ok(())
}