From: alex Date: Sun, 10 Dec 2023 10:08:35 +0000 (+0100) Subject: Day10 - part 1 X-Git-Url: https://aoc.elinar.fr/?a=commitdiff_plain;h=2c4d443a3b5397953dd818595e7fb060dc4443f2;p=aoc_2023 Day10 - part 1 --- diff --git a/src/day10.rs b/src/day10.rs new file mode 100644 index 0000000..9b30225 --- /dev/null +++ b/src/day10.rs @@ -0,0 +1,276 @@ +use std::io::Read; +use std::error::Error; +use std::fs::File; + +pub fn run(input_file: &str) -> Result<(), Box> { + let mut f = File::open(input_file)?; + let mut input = String::new(); + f.read_to_string(&mut input)?; + + let res = run_part1(&input)?; + println!("{res}"); + + let res = run_part2(&input)?; + println!("{res}"); + + Ok(()) +} + +#[derive(Debug)] +struct Puzzle { + start: (usize, usize), + map: Vec>, +} + +impl Puzzle { + pub fn new(input: &str) -> Self { + // astuce : on ajoute une ligne de symbole neutre en haut et en bas + // et à gauche et à droite de la carte + // cela permet de s'affranchir des tests de limites de tableau + // + // ....... + // -L|F7 .-L|F7. + // 7S-7| .7S-7|. + // L|7|| -> .L|7||. + // -L-J| .-L-J|. + // L|-JF .L|-JF. + // ....... + + let mut map: Vec> = Vec::new(); + + // coordonnées du S de départ + let mut start = (0, 0); + + input.lines() + .filter(|l| !l.is_empty()) + .enumerate() + .for_each(|(i,l)| { + let mut row: Vec = Vec::new(); + + row.push('.'); + l.chars().for_each(|c| { row.push(c); }); + row.push('.'); + + // ajout d'une première ligne de '.' + if i == 0 { + map.push( (0..row.len()).map(|_| '.').collect::>() ); + } + map.push(row); + + // recherche du S de départ + if start == (0, 0) { + start = match l.chars().position(|c| c == 'S') { + Some(p) => (i + 1, p + 1), + None => (0, 0), + }; + } + }); + + // ajout d'une dernière ligne + map.push( (0..map[0].len()).map(|_| '.').collect::>() ); + + Self { + start, + map + } + } + + pub fn get_char(self: &Self, pos: (usize, usize)) -> char { + self.map[pos.0][pos.1] + } +} + +// a -> b +// (row, col) +fn is_connected(c: char, a: (usize, usize), b: (usize, usize)) -> bool { + match c { + '|' => a.1 == b.1 && (a.0 as i32 - b.0 as i32).abs() == 1, + '-' => a.0 == b.0 && (a.1 as i32 - b.1 as i32).abs() == 1, + 'L' => (a.1 == b.1 && (a.0 + 1) == b.0) || (a.0 == b.0 && a.1 == (b.1 + 1)), + 'J' => (a.1 == b.1 && (a.0 + 1) == b.0) || (a.0 == b.0 && (a.1 + 1) == b.1), + '7' => (a.1 == b.1 && a.0 == (b.0 + 1)) || (a.0 == b.0 && (a.1 + 1) == b.1), + 'F' => (a.1 == b.1 && a.0 == (b.0 + 1)) || (a.0 == b.0 && a.1 == (b.1 + 1)), + '.' => false, + _ => unreachable!(), + } +} + +// besoin de connaitre le sens +// c le char du tuyau de connexion +// current: la position actuelle +// pipe: le tuyau de connexion +// retourne: (row, col) de la sortie après le tuyau de connexion +fn get_next_next(c: char, current: (usize, usize), pipe: (usize, usize) ) -> (usize, usize) { + let (row, col) = current; + //println!("get_next: c: {}, current: {:?}, pipe: {:?}", c, current, pipe); + // vérifier que le "pipe" est connecté au "current" + match c { + // | x + // x | + '|' => { + if pipe.0 < row { + (row - 2, col) + } else { + (row + 2, col) + } + }, + + // x- + // -x + '-' => { + if pipe.1 < col { + (row, col - 2) + } else { + (row, col + 2) + } + }, + + // x Lx + // L + 'L' => { + if pipe.1 < col { + (row - 1, col - 1) + } else { + (row + 1, col + 1) + } + }, + + // x xJ + // J + 'J' => { + if pipe.1 > col { + (row - 1, col + 1) + } else { + (row + 1, col - 1) + } + }, + + // 7 x7 + // x + '7' => { + if pipe.1 > col { + (row + 1, col + 1) + } else { + (row - 1, col - 1) + } + }, + + // F Fx + // x + 'F' => { + if pipe.1 < col { + (row + 1, col - 1) + } else { + (row - 1, col + 1) + } + }, + + '.' | 'S' => (0, 0), + _ => unreachable!(), + } +} + +fn run_part1(input: &str) -> Result> { + println!("Running day10 - part 1"); + + let puzzle = Puzzle::new(input); + + let mut current = puzzle.start; + let (row, col) = current; + // on recherche dans les 4 directions + let start = [ + (row - 1, col), + (row + 1, col), + (row, col - 1), + (row, col + 1), + ]; + let mut count: u32 = 0; + for mut next in start { + count = 1; + while puzzle.get_char(next) != 'S' && is_connected(puzzle.get_char(next), current, next) { + count += 1; + let next_next = get_next_next(puzzle.get_char(next), current, next); + current = next; + next = next_next; + } + if puzzle.get_char(next) == 'S' { + break; + } + } + + let res = count.div_ceil(2); + Ok(res) +} + +fn run_part2(input: &str) -> Result> { + println!("Running day10 - part 2"); + let res = 0; + Ok(res) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn day10_part1_example1() { + let input = "\ +-L|F7 +7S-7| +L|7|| +-L-J| +L|-JF"; + let res = run_part1(&input); + assert_eq!(4, res.unwrap()); + } + + #[test] + fn day10_part1_example2() { + let input = "\ +7-F7- +.FJ|7 +SJLL7 +|F--J +LJ.LJ"; + let res = run_part1(&input); + assert_eq!(8, res.unwrap()); + } + + #[test] + fn test_is_connected() { + // (row, col) + assert_eq!( is_connected('|', (0,0), (1,0)), true); + assert_eq!( is_connected('|', (1,0), (0,0)), true); + assert_eq!( is_connected('|', (0,0), (0,1)), false); + assert_eq!( is_connected('|', (0,0), (2,0)), false); + + assert_eq!( is_connected('-', (0,0), (0,1)), true); + assert_eq!( is_connected('-', (0,1), (0,0)), true); + assert_eq!( is_connected('-', (0,0), (1,0)), false); + + assert_eq!( is_connected('L', (0,0), (1,0)), true); + assert_eq!( is_connected('L', (0,1), (0,0)), true); + assert_eq!( is_connected('L', (0,0), (0,1)), false); + + assert_eq!( is_connected('J', (0,0), (1,0)), true); + assert_eq!( is_connected('J', (0,0), (0,1)), true); + assert_eq!( is_connected('J', (0,1), (0,0)), false); + + assert_eq!( is_connected('7', (0,0), (0,1)), true); + assert_eq!( is_connected('7', (1,0), (0,0)), true); + assert_eq!( is_connected('7', (0,0), (1,0)), false); + + assert_eq!( is_connected('F', (0,1), (0,0)), true); + assert_eq!( is_connected('F', (1,0), (0,0)), true); + assert_eq!( is_connected('F', (0,0), (0,1)), false); + + assert_eq!( is_connected('.', (0,0), (0,1)), false); + } + + #[test] + fn day10_part2() { + let input = ""; + let res = run_part2(&input); + assert_eq!(0, res.unwrap()); + } +} diff --git a/src/main.rs b/src/main.rs index 5dc80cc..fe39a4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ pub mod day06; pub mod day07; pub mod day08; pub mod day09; +pub mod day10; fn main() { let args: Vec = env::args().collect(); @@ -39,6 +40,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box> { "day07" => day07::run(input_file)?, "day08" => day08::run(input_file)?, "day09" => day09::run(input_file)?, + "day10" => day10::run(input_file)?, _ => return Err(format!("unknown day \"{day}\"").into()), } Ok(())