You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
74 lines
2.3 KiB
Rust
74 lines
2.3 KiB
Rust
use serde_json::{json, Value};
|
|
use std::cmp::Ordering;
|
|
|
|
fn main() {
|
|
let contents = std::fs::read_to_string("data.txt").expect("Failed to read file");
|
|
|
|
// Part 1
|
|
let sum = contents
|
|
.trim()
|
|
.split("\n\n")
|
|
.map(|pair| {
|
|
pair.split("\n")
|
|
.map(|str| serde_json::from_str(str).unwrap())
|
|
.collect::<Vec<Value>>()
|
|
})
|
|
.enumerate()
|
|
.map(|(i, p)| (i + 1, in_order(&p[0], &p[1])))
|
|
.fold(0, |acc, (i, good)| {
|
|
acc + if good.unwrap_or(false) { i } else { 0 }
|
|
});
|
|
|
|
println!("Part 1. Sum: {:?}", sum);
|
|
|
|
// Part 2
|
|
let two = json!([[2]]);
|
|
let six = json!([[6]]);
|
|
let mut packets = contents
|
|
.split("\n")
|
|
.filter(|&l| !l.is_empty())
|
|
.map(|line| serde_json::from_str(line).unwrap())
|
|
.collect::<Vec<Value>>();
|
|
packets.append(&mut vec![two.clone(), six.clone()]);
|
|
packets.sort_by(cmp);
|
|
let idx1 = packets.iter().position(|x| x == &two).unwrap();
|
|
let idx2 = packets.iter().position(|x| x == &six).unwrap();
|
|
println!("Part 2. Decoder Key: {:?}", (idx1 + 1) * (idx2 + 1));
|
|
}
|
|
|
|
fn in_order(left: &Value, right: &Value) -> Option<bool> {
|
|
match left {
|
|
Value::Number(l) => match right {
|
|
Value::Number(r) => match l.as_u64().cmp(&r.as_u64()) {
|
|
Ordering::Less => Some(true),
|
|
Ordering::Greater => Some(false),
|
|
Ordering::Equal => None,
|
|
},
|
|
Value::Array(_) => in_order(&json!([left]), &right),
|
|
_ => panic!("Bad input"),
|
|
},
|
|
Value::Array(l) => match right {
|
|
Value::Number(_) => in_order(&left, &json!([right])),
|
|
Value::Array(r) => match (l.len(), r.len()) {
|
|
(0, 0) => None,
|
|
(0, _) => Some(true),
|
|
(_, 0) => Some(false),
|
|
(_, _) => match in_order(&l[0], &r[0]) {
|
|
None => in_order(&json!(l[1..]), &json!(r[1..])),
|
|
a => a,
|
|
},
|
|
},
|
|
_ => panic!("Bad input"),
|
|
},
|
|
_ => panic!("Bad input"),
|
|
}
|
|
}
|
|
|
|
fn cmp(l: &Value, r: &Value) -> Ordering {
|
|
match in_order(l, r) {
|
|
Some(true) => Ordering::Less,
|
|
Some(false) => Ordering::Greater,
|
|
None => Ordering::Equal,
|
|
}
|
|
}
|