122 lines
No EOL
3.4 KiB
Rust
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
|
|
} |