advent_of_code_2022/aoc_13a/src/main.rs

211 lines
6.2 KiB
Rust

use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
#[derive(Debug)]
enum Elem {
Number(u8),
List(Vec<Elem>),
}
use crate::Elem::{Number, List};
// I modified my input because the only 2 digits number was 10
// I replaced all 10s with ':' so that I can parse more easely
fn parse_line(line: &str, mut ind: usize) -> (Elem, usize) {
let mut elems: Vec<Elem> = vec![];
let mut len = 0;
while ind < line.len() {
let a = line[ind..ind+1].chars().next().unwrap();
match a {
'[' => { // Creer une List, la push sur le vecteur en cours
println!("Entering sublist from index {} to {}", ind, ind+1);
let (a, b) = parse_line(line, ind+1);
println!("Sublist len was {}, Left sublist, now at index {}", b, ind+b);
ind += b;
len += b;
elems.push(a);
},
']' => {
println!("Returning list with index {}", ind);
return (List(elems), len + 1);
} // Remonter le vecteur en cours de 1,
'0'..=':' => {
println!("Pushing {}", a as u8 - b'0');
elems.push(Number(a as u8 - b'0')); // Creer un nombre, le push sur le vecteur en cours
},
_ => (),
};
ind += 1;
len += 1;
}
unreachable!("parse_line end of function");
//println!("unreachable !!!! UNREACHABLE");
//(List(elems), len)
}
fn compare(lhs: &Elem, rhs: &Elem) -> u8 {
let mut lhs_v = &vec![];
let mut rhs_v = &vec![];
if let List(a) = lhs {
lhs_v = a;
}
if let List(a) = rhs {
rhs_v = a;
}
println!("[ start list");
for i in 0..lhs_v.len() {
if i >= rhs_v.len() {
println!("Right side ran out of items, so inputs are NOT in the right order");
return 2;
}
match (&lhs_v[i], &rhs_v[i]) {
(List(_), List(_)) => {
let c = compare(&lhs_v[i], &rhs_v[i]);
if c != 0 {
return c;
}
},
(List(_), Number(b)) => {
println!("Mixed types; convert right to [{}] and retry comparison", b);
let c = compare(&lhs_v[i], &List(vec![Number(*b)]));
if c != 0 {
return c;
}
},
(Number(a), List(_)) => {
println!("Mixed types; convert left to [{}] and retry comparison", a);
let c = compare(&List(vec![Number(*a)]), &rhs_v[i]);
if c != 0 {
return c;
}
},
(Number(a), Number(b)) => {
println!("Compare {} vs {}", a, b);
if a < b {
println!("Left side is smaller, so input are in the right order");
return 1;
}
if a > b {
println!("Right side is smaller, so input are NOT in the right order");
return 2;
}
}
}
}
if rhs_v.len() > lhs_v.len() {
println!("Left side ran out of items, so inputs are in the right order");
return 1;
}
println!("end list ]");
0
}
fn main() {
let file_path = String::from("input");
println!("In file {}", file_path);
let mut data: Vec<Elem> = vec![];
if let Ok(lines) = read_lines(file_path) {
// Consumes the iterator, returns an (Optional) String
for (i, line) in lines.enumerate() {
if let Ok(ip) = line {
match i % 3 {
0..=1 => data.push(parse_line(&ip, 1).0),
_ => (),
}
}
}
}
let mut ret = 0;
for i in (0..data.len() - 1).filter(|x| x % 2 == 0) {
println!("\n{}", i / 2 + 1);
if compare(&data[i], &data[i+1]) == 1 {
println!("salut {}", i / 2 + 1);
ret += i / 2 + 1;
}
}
//println!("{:#?}", data);
println!("\n{}", ret);
//println!("{:?}", data);
}
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}
#[cfg(test)]
fn compare_all_test_tool(lhs: &Elem, rhs: &Elem) {
assert_eq!(compare(&lhs, &rhs), 1);
assert_eq!(compare(&rhs, &lhs), 2);
assert_eq!(compare(&rhs, &rhs), 0);
assert_eq!(compare(&lhs, &lhs), 0);
}
#[cfg(test)]
fn parse_all_test_tool(lhs: &Elem, rhs: &Elem, lhs_s: &str, rhs_s: &str) {
println!("LHS {:#?}", lhs);
println!("LHS STRING {:#?}", lhs_s);
let lhs_s = parse_line(lhs_s, 1).0;
println!("LHS STRING PARSED {:#?}", lhs_s);
assert_eq!(compare(&lhs, &lhs_s), 0);
println!("LHS PARSING OK");
println!("RHS {:#?}", rhs);
println!("RHS STRING {:#?}", rhs_s);
let rhs_s = parse_line(rhs_s, 1).0;
println!("RHS STRING PARSED {:#?}", rhs_s);
assert_eq!(compare(&rhs, &rhs_s), 0);
println!("RHS PARSING OK");
}
#[cfg(test)]
fn all_test_tool(lhs: &Elem, rhs: &Elem, lhs_s: &str, rhs_s: &str) {
parse_all_test_tool(&lhs, &rhs, lhs_s, rhs_s);
compare_all_test_tool(&lhs, &rhs);
}
#[test]
fn simple_list() {
let lhs_s = "[1,1,2]";
let rhs_s = "[1,3,1]";
let lhs = List(vec![Number(1), Number(1), Number(2)]);
let rhs = List(vec![Number(1), Number(3), Number(1)]);
all_test_tool(&lhs, &rhs, lhs_s, rhs_s);
}
#[test]
fn simple_list_with_conversion() {
let lhs_s = "[1,1,2]";
let rhs_s = "[1,[3],1]";
let lhs = List(vec![Number(1), Number(1), Number(2)]);
let rhs = List(vec![Number(1), List(vec![Number(3)]), Number(1)]);
all_test_tool(&lhs, &rhs, lhs_s, rhs_s);
}
#[test]
fn recursive_empty_list_simple() {
let lhs_s = "[[]]";
let rhs_s = "[[[]]]";
let lhs = List(vec![List(vec![])]);
let rhs = List(vec![List(vec![List(vec![])])]);
all_test_tool(&lhs, &rhs, lhs_s, rhs_s);
}
#[test]
fn recursive_empty_list() {
let lhs_s = "[[[[]]]]";
let rhs_s = "[[[[[]]]]]";
let lhs = List(vec![List(vec![List(vec![List(vec![])])])]);
let rhs = List(vec![List(vec![List(vec![List(vec![List(vec![])])])])]);
all_test_tool(&lhs, &rhs, lhs_s, rhs_s);
}