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::::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 }