83 lines
2.2 KiB
Rust
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(())
|
|
}
|