From 3da797b10ba25164134ac1828eb81c8aa139b6d7 Mon Sep 17 00:00:00 2001 From: H-Rusch Date: Sun, 10 Dec 2023 15:14:41 +0100 Subject: [PATCH] 2023 day 10 part 1 --- aoc23/examples/day10_1_1.txt | 5 ++ aoc23/examples/day10_1_2.txt | 5 ++ aoc23/src/main.rs | 1 + aoc23/src/solutions.rs | 3 +- aoc23/src/solutions/day10.rs | 130 +++++++++++++++++++++++++++++++++++ 5 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 aoc23/examples/day10_1_1.txt create mode 100644 aoc23/examples/day10_1_2.txt create mode 100644 aoc23/src/solutions/day10.rs diff --git a/aoc23/examples/day10_1_1.txt b/aoc23/examples/day10_1_1.txt new file mode 100644 index 0000000..73b3d66 --- /dev/null +++ b/aoc23/examples/day10_1_1.txt @@ -0,0 +1,5 @@ +..... +.S-7. +.|.|. +.L-J. +..... \ No newline at end of file diff --git a/aoc23/examples/day10_1_2.txt b/aoc23/examples/day10_1_2.txt new file mode 100644 index 0000000..3c00cf2 --- /dev/null +++ b/aoc23/examples/day10_1_2.txt @@ -0,0 +1,5 @@ +..F7. +.FJ|. +SJ.L7 +|F--J +LJ... \ No newline at end of file diff --git a/aoc23/src/main.rs b/aoc23/src/main.rs index c998913..47c212b 100644 --- a/aoc23/src/main.rs +++ b/aoc23/src/main.rs @@ -45,6 +45,7 @@ fn main() { 7 => solve_day!(day07, &input), 8 => solve_day!(day08, &input), 9 => solve_day!(day09, &input), + 10 => solve_day!(day10, &input), _ => println!("day not solved: {}", day), } } diff --git a/aoc23/src/solutions.rs b/aoc23/src/solutions.rs index 1de1945..705ab79 100644 --- a/aoc23/src/solutions.rs +++ b/aoc23/src/solutions.rs @@ -6,4 +6,5 @@ pub mod day05; pub mod day06; pub mod day07; pub mod day08; -pub mod day09; \ No newline at end of file +pub mod day09; +pub mod day10; \ No newline at end of file diff --git a/aoc23/src/solutions/day10.rs b/aoc23/src/solutions/day10.rs new file mode 100644 index 0000000..c8271ab --- /dev/null +++ b/aoc23/src/solutions/day10.rs @@ -0,0 +1,130 @@ +use std::collections::{HashMap, VecDeque}; + +use util::grid::{Coordinate, Direction}; + +pub fn part1(input: &str) -> usize { + let (coordinates, start) = parse(input); + let circle = find_circle(start, &coordinates); + + circle.len() / 2 +} + +pub fn part2(input: &str) -> usize { + 0 +} + +fn find_circle(start: Coordinate, coordinates: &HashMap) -> String { + let mut queue = init_queue(&start, coordinates); + + while let Some((coordinate, direction, path)) = queue.pop_front() { + if coordinate == start { + return path; + } + + let pipe = coordinates.get(&coordinate).unwrap(); + let next_direction = next_direction(*pipe, direction); + let next_coordinate = coordinate.step(&next_direction, 1); + let mut next_path = path.clone(); + next_path.push(*pipe); + + queue.push_back((next_coordinate, next_direction, next_path)); + } + + unreachable!() +} + +fn init_queue( + start: &Coordinate, + coordinates: &HashMap, +) -> VecDeque<(Coordinate, Direction, String)> { + [ + Direction::Up, + Direction::Left, + Direction::Down, + Direction::Right, + ] + .into_iter() + .map(|direction| (start.step(&direction, 1), direction)) + .filter(|(coordinate, direction)| { + coordinates.contains_key(coordinate) + && valid_directions(*coordinates.get(coordinate).unwrap(), direction) + }) + .map(|(coordinate, direction)| (coordinate, direction, String::from("S"))) + .collect() +} + +fn next_direction(pipe: char, direction: Direction) -> Direction { + match (pipe, direction) { + ('|', Direction::Up) => Direction::Up, + ('|', Direction::Down) => Direction::Down, + ('-', Direction::Left) => Direction::Left, + ('-', Direction::Right) => Direction::Right, + ('L', Direction::Down) => Direction::Right, + ('L', Direction::Left) => Direction::Up, + ('J', Direction::Down) => Direction::Left, + ('J', Direction::Right) => Direction::Up, + ('7', Direction::Up) => Direction::Left, + ('7', Direction::Right) => Direction::Down, + ('F', Direction::Up) => Direction::Right, + ('F', Direction::Left) => Direction::Down, + _ => unreachable!(), + } +} + +fn valid_directions(pipe: char, direction: &Direction) -> bool { + match (pipe, direction) { + ('|', Direction::Up | Direction::Down) => true, + ('-', Direction::Left | Direction::Right) => true, + ('L', Direction::Left | Direction::Down) => true, + ('J', Direction::Right | Direction::Down) => true, + ('7', Direction::Right | Direction::Up) => true, + ('F', Direction::Left | Direction::Up) => true, + ('S', _) => true, + _ => false, + } +} + +fn parse(input: &str) -> (HashMap, Coordinate) { + let mut coordinates = HashMap::new(); + for (y, row) in input.lines().enumerate() { + for (x, cell) in row.chars().enumerate() { + if cell != '.' { + coordinates.insert(Coordinate::from(x as i32, y as i32), cell); + } + } + } + + let start_position = find_start(input); + + (coordinates, start_position) +} + +fn find_start(input: &str) -> Coordinate { + for (y, row) in input.lines().enumerate() { + for (x, cell) in row.chars().enumerate() { + if cell == 'S' { + return Coordinate::from(x as i32, y as i32); + } + } + } + unreachable!() +} + +#[cfg(test)] +mod tests { + use super::*; + + const EXAMPLE_1: &str = include_str!("../../examples/day10_1_1.txt"); + const EXAMPLE_2: &str = include_str!("../../examples/day10_1_2.txt"); + + #[test] + fn part1_ex() { + assert_eq!(4, part1(EXAMPLE_1)); + assert_eq!(8, part1(EXAMPLE_2)); + } + + #[test] + fn part2_ex() { + assert_eq!(0, part2(INPUT)); + } +}