use std::time::Instant; #[derive(PartialEq, Clone)] enum Pipe { Vertical, // | Horizontal, // - L, // North with East J, // North with West Pipe7, // South with West F, // South with East Dot, // Nothing S, // Start Point } impl From for Pipe { fn from(value: char) -> Self { match value { '|' => Pipe::Vertical, '-' => Pipe::Horizontal, 'L' => Pipe::L, 'J' => Pipe::J, '7' => Pipe::Pipe7, 'F' => Pipe::F, '.' => Pipe::Dot, 'S' => Pipe::S, _ => Pipe::Dot } } } impl Pipe { fn next(&self, from: (i32, i32), current: (i32, i32)) -> (i32, i32) { let diff_y = current.0 - from.0; let diff_x = current.1 - from.1; if diff_y == 0 { // From East or West if diff_x > 0 { // From West match self { Pipe::Horizontal => (current.0, current.1 + 1), // To East Pipe::J => (current.0 - 1, current.1), // To North Pipe::Pipe7 => (current.0 + 1, current.1), // To South _ => (0,0) } } else { // From East match self { Pipe::Horizontal => (current.0, current.1 - 1), // To West Pipe::L => (current.0 - 1, current.1), // To North Pipe::F => (current.0 + 1, current.1 ), // To South _ => (0,0) } } } else if diff_y > 0{ // From North match self { Pipe::Vertical => (current.0 + 1, current.1), // To South Pipe::J => (current.0, current.1 - 1), // To West Pipe::L => (current.0, current.1 + 1), // To East _ => (0,0) } } else { // From South match self { Pipe::Vertical => (current.0 - 1, current.1), // To North Pipe::Pipe7 => (current.0, current.1 - 1), // To West Pipe::F => (current.0, current.1 + 1), // To East _ => (0,0) } } } } pub fn execute_task01(content: &str) { let start = Instant::now(); let sum_of_b = solve_01(content).unwrap(); let duration = start.elapsed(); //assert_eq!(1953784198, sum_of_b); println!("Day10 - Task01 - Duration: {duration:?} - Farthest Point: {}", sum_of_b) } pub fn execute_task02(content: &str) { let start = Instant::now(); let command_steps = solve_02(content).unwrap(); let duration = start.elapsed(); //assert_eq!(957, command_steps); println!("Day09 - Task02 - Duration: {duration:?} - Sum of B: {}", command_steps) } fn solve_01(content: &str) -> anyhow::Result { let mut map = build_map(content); let (starting, directions) = find_start(&map); map[starting.1.0 as usize][starting.1.1 as usize] = starting.0; let from = (starting.1.0 + directions[0].0, starting.1.1 + directions[1].0); let mut pipe_network = vec![from ,starting.1]; solve_pipeline(&map, &mut pipe_network); Ok(pipe_network.len()/2) } fn solve_02(content: &str) -> anyhow::Result { let mut map = build_map(content); let (starting, directions) = find_start(&map); map[starting.1.0 as usize][starting.1.1 as usize] = starting.0; let from = (starting.1.0 + directions[0].0, starting.1.1 + directions[1].0); let mut pipe_network = vec![from ,starting.1]; solve_pipeline(&map, &mut pipe_network); let mut is_in_pipe = false; let mut last_change = Pipe::Dot; let mut size_of_caged_tiles = 0; map.iter() .enumerate() .for_each(|(y, column)| column.iter() .enumerate() .for_each(|(x, pipe)| { if pipe == &Pipe::Horizontal { return } if pipe_network.contains(&(y as i32, x as i32)) { match pipe { Pipe::Vertical => is_in_pipe = !is_in_pipe, Pipe::L => is_in_pipe = !is_in_pipe, Pipe::F => is_in_pipe = !is_in_pipe, Pipe::Pipe7 => { if last_change != Pipe::F { is_in_pipe = !is_in_pipe } }, Pipe::J => { if last_change != Pipe::L { is_in_pipe = !is_in_pipe } }, _ => panic!("HELP") }; } else { if is_in_pipe { println!("Find Tile: ({y},{x})"); size_of_caged_tiles += 1; } } })); Ok(size_of_caged_tiles) } fn build_map(content: &str) -> Vec> { content .lines() .map(|line| line.chars().map(|c| Pipe::from(c)).collect::>()) .collect::>>() } fn find_start(map: &Vec>) -> ((Pipe, (i32, i32)), Vec<(i32, i32)>) { let mut starting: (Pipe, (i32, i32)) = (Pipe::Dot, (0, 0)); let mut directions: Vec<(i32, i32)> = vec![]; 'outer: for (y, line) in map.iter().enumerate() { for (x, c) in line.iter().enumerate() { if c == &Pipe::S { // Find starting, now replace with correct Pipe // North exists if y > 0 { let north_pipe = &map[y - 1][x]; if north_pipe == &Pipe::Pipe7 || north_pipe == &Pipe::F || north_pipe == &Pipe::Vertical { directions.push((-1, 0)); } } // South exists if map.len() > (y + 1) { let south_pipe = &map[y + 1][x]; if south_pipe == &Pipe::L || south_pipe == &Pipe::J || south_pipe == &Pipe::Vertical { directions.push((1, 0)); } } // West exists if x > 0 { let west_pipe = &map[y][x - 1]; if west_pipe == &Pipe::L || west_pipe == &Pipe::F || west_pipe == &Pipe::Horizontal { directions.push((0, -1)); } } // East exists if map[y].len() > (x + 1) { let east_pipe = &map[y][x + 1]; if east_pipe == &Pipe::J || east_pipe == &Pipe::Pipe7 || east_pipe == &Pipe::Horizontal { directions.push((0, 1)); } } // North (-1, 0) with South (1, 0) => (0,0) Vertical // North (-1, 0) with East (0, 1) => (0,0) // North (-1, 0) with West (0, -1) => (0,0) // North (-1, 0) with South (1, 0) => (0,0) // North (-1, 0) with South (1, 0) => (0,0) // North (-1, 0) with South (1, 0) => (0,0) // North (-1, 0) with South (1, 0) => (0,0) let pipe = match (directions[0], directions[1]) { ((-1, 0), (1, 0)) => Pipe::Vertical, // North to South ((-1, 0), (0, 1)) => Pipe::L, // North to East ((-1, 0), (0, -1)) => Pipe::J, // North to West ((1, 0), (-1, 0)) => Pipe::Vertical, // South to North ((1, 0), (0, 1)) => Pipe::F, // South to East ((1, 0), (0, -1)) => Pipe::Pipe7,// South to West ((0, -1), (1, 0)) => Pipe::Pipe7, // West to South ((0, -1), (0, 1)) => Pipe::Horizontal, // West to East ((0, -1), (-1, 0)) => Pipe::J, // West to North ((0, 1), (1, 0)) => Pipe::F, // East to South ((0, 1), (-1, 0)) => Pipe::L, // East to North ((0, 1), (0, -1)) => Pipe::Horizontal, // East to West (_, _) => Pipe::Dot }; starting = (pipe, (y as i32, x as i32)); break 'outer } } } (starting, directions) } fn solve_pipeline(map: &Vec>, pipe_network: &mut Vec<(i32, i32)>) { loop { let from = pipe_network[pipe_network.len() -2].clone(); let latest = pipe_network.last().unwrap().clone(); let pipe = &map[latest.0 as usize][latest.1 as usize]; let new = pipe.next(from.clone(), latest.clone()); if pipe_network.contains(&new) { break } pipe_network.push(new); } } #[test] fn test_solve_01() { let example = r#"..... .S-7. .|.|. .L-J. ....."#; let result = solve_01(example).unwrap(); assert_eq!(4, result); } #[test] fn test_solve_01_2() { let example = r#"..F7. .FJ|. SJ.L7 |F--J LJ..."#; let result = solve_01(example).unwrap(); assert_eq!(8, result); } #[test] fn test_solve_02() { let example = r#"........... .S-------7. .|F-----7|. .||.....||. .||.....||. .|L-7.F-J|. .|..|.|..|. .L--J.L--J. ..........."#; let result = solve_02(example).unwrap(); assert_eq!(4, result); } #[test] fn test_solve_02_2() { let example = r#".F----7F7F7F7F-7.... .|F--7||||||||FJ.... .||.FJ||||||||L7.... FJL7L7LJLJ||LJ.L-7.. L--J.L7...LJS7F-7L7. ....F-J..F7FJ|L7L7L7 ....L7.F7||L7|.L7L7| .....|FJLJ|FJ|F7|.LJ ....FJL-7.||.||||... ....L---J.LJ.LJLJ..."#; let result = solve_02(example).unwrap(); assert_eq!(8, result); } #[test] fn test_solve_02_3() { let example = r#"FF7FSF7F7F7F7F7F---7 L|LJ||||||||||||F--J FL-7LJLJ||||||LJL-77 F--JF--7||LJLJ7F7FJ- L---JF-JLJ.||-FJLJJ7 |F|F-JF---7F7-L7L|7| |FFJF7L7F-JF7|JL---7 7-L-JL7||F7|L7F-7F7| L.L7LFJ|||||FJL7||LJ L7JLJL-JLJLJL--JLJ.L"#; let result = solve_02(example).unwrap(); assert_eq!(10, result); }