advent-of-code-2022/src/days/d13.rs
2022-12-13 12:18:34 +01:00

122 lines
No EOL
3.4 KiB
Rust

use std::fs;
use serde_json::Value;
pub fn solve() {
let path = "res/13/input.txt";
let contents = fs::read_to_string(path).expect("I/O error, wrong path?");
let pairs: Vec<(&str, &str)> = contents
.split("\n\n")
.map(|pair| pair.split_at(pair.find("\n").unwrap()))
.collect();
let mut right_order_indices = Vec::<u32>::new();
pairs.iter().enumerate().for_each(|(i, pair)| {
let json1: Value = serde_json::from_str(pair.0).unwrap();
let json2: Value = serde_json::from_str(pair.1).unwrap();
println!("== Pair {} ==", i+1);
let res = is_right_order((&json1, &json2));
println!("Pair {}: {res:?}\n", i+1);
if res != Ordered::No {
right_order_indices.push((i+1) as u32);
}
});
let res: u32 = right_order_indices.iter().sum();
println!("Result 1: {res}");
}
#[derive(PartialEq, Debug)]
enum Ordered {
Yes,
Maybe,
No
}
fn is_right_order(values: (&Value, &Value)) -> Ordered {
println!("Compare {} vs {}", values.0, values.1);
// both values numbers
if values.0.is_number() && values.1.is_number() {
let v0 = values.0.as_u64().unwrap();
let v1 = values.1.as_u64().unwrap();
// wrong order if right is higher than left
if v0 < v1 {
return Ordered::Yes
} else if v0 == v1 {
return Ordered::Maybe
} else {
return Ordered::No
}
}
// left number, right array
else if values.0.is_number() && values.1.is_array() {
// wrap number into arr, then compare again
let left = Value::Array(vec!(values.0.clone()));
return is_right_order((&left, &values.1));
}
// left array, right number
else if values.0.is_array() && values.1.is_number() {
// wrap number into arr, then compare again
let right = Value::Array(vec!(values.1.clone()));
return is_right_order((&values.0, &right));
}
// both array
else if values.0.is_array() && values.1.is_array() {
let a0 = values.0.as_array().unwrap();
let a1 = values.1.as_array().unwrap();
let mut a0iter = a0.iter();
let mut a1iter = a1.iter();
loop {
let left = a0iter.next();
let right = a1iter.next();
if left.is_none() && right.is_some() {
return Ordered::Yes
}
if left.is_some() && right.is_none() {
return Ordered::No
}
if left.is_none() && right.is_none() {
return Ordered::Maybe
}
let left = left.unwrap();
let right = right.unwrap();
return is_right_order((&left, &right));
}
let mut current_order = Ordered::Maybe;
a0.iter()
.enumerate()
.for_each(|(i, _)| {
if current_order == Ordered::No
|| current_order == Ordered::Yes {
return
}
if a1.len() < i+1 {
current_order = Ordered::No;
println!("2nd arr too short");
return
}
current_order = is_right_order((&a0[i], &a1[i]));
});
if a0.len() > a1.len() && current_order != Ordered::No {
return Ordered::Yes
}
return current_order;
}
Ordered::Yes
}