day20
This commit is contained in:
		
							parent
							
								
									0ecea97752
								
							
						
					
					
						commit
						e857602932
					
				
							
								
								
									
										262
									
								
								aoc_2024/src/day20.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								aoc_2024/src/day20.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,262 @@ | ||||
| use std::usize; | ||||
| 
 | ||||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||||
| enum Cell { | ||||
|     Empty, | ||||
|     Wall, | ||||
| } | ||||
| 
 | ||||
| type Input = ((usize, usize), (usize, usize), Vec<Vec<Cell>>); | ||||
| 
 | ||||
| #[aoc_generator(day20)] | ||||
| fn parse(input: &str) -> Input { | ||||
|     let mut start = (0, 0); | ||||
|     let mut end = (0, 0); | ||||
|     let map = input | ||||
|         .lines() | ||||
|         .enumerate() | ||||
|         .map(|(y, line)| { | ||||
|             line.chars() | ||||
|                 .enumerate() | ||||
|                 .map(|(x, c)| match c { | ||||
|                     '.' => Cell::Empty, | ||||
|                     '#' => Cell::Wall, | ||||
|                     'S' => { | ||||
|                         start = (x, y); | ||||
|                         Cell::Empty | ||||
|                     } | ||||
|                     'E' => { | ||||
|                         end = (x, y); | ||||
|                         Cell::Empty | ||||
|                     } | ||||
|                     _ => panic!("unexpected character: {}", c), | ||||
|                 }) | ||||
|                 .collect() | ||||
|         }) | ||||
|         .collect(); | ||||
|     (start, end, map) | ||||
| } | ||||
| 
 | ||||
| #[aoc(day20, part1)] | ||||
| fn part1(input: &Input) -> usize { | ||||
|     let start = input.0; | ||||
|     let end = input.1; | ||||
|     let map = &input.2; | ||||
| 
 | ||||
|     #[cfg(not(test))] | ||||
|     let min_saving = 100; | ||||
|     #[cfg(test)] | ||||
|     let min_saving = 2; | ||||
| 
 | ||||
|     let w = map[0].len(); | ||||
|     let h = map.len(); | ||||
| 
 | ||||
|     let mut dist = vec![vec![usize::MAX; w]; h]; | ||||
|     dist[start.1][start.0] = 0; | ||||
| 
 | ||||
|     let mut deque = std::collections::VecDeque::new(); | ||||
|     deque.push_back((0, start)); | ||||
| 
 | ||||
|     while let Some((d, pos)) = deque.pop_front() { | ||||
|         if dist[pos.1][pos.0] < d { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         dist[pos.1][pos.0] = d; | ||||
| 
 | ||||
|         [(1, 0), (-1, 0), (0, -1), (0, 1)] | ||||
|             .iter() | ||||
|             .for_each(|(dx, dy)| { | ||||
|                 let x = (pos.0 as isize + dx) as usize; | ||||
|                 let y = (pos.1 as isize + dy) as usize; | ||||
| 
 | ||||
|                 if x < w && y < h && map[y][x] == Cell::Empty { | ||||
|                     let new_d = d + 1; | ||||
|                     if new_d < dist[y][x] { | ||||
|                         deque.push_back((new_d, (x, y))); | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     map.iter() | ||||
|         .enumerate() | ||||
|         .map(|(y, line)| { | ||||
|             line.iter() | ||||
|                 .enumerate() | ||||
|                 .map(|(x, cell)| { | ||||
|                     let y = y as isize; | ||||
|                     if *cell == Cell::Empty { | ||||
|                         [ | ||||
|                             (0, 2), | ||||
|                             (0, -2), | ||||
|                             (2, 0), | ||||
|                             (-2, 0), | ||||
|                             (1, 1), | ||||
|                             (1, -1), | ||||
|                             (-1, 1), | ||||
|                             (-1, -1), | ||||
|                         ] | ||||
|                         .iter() | ||||
|                         .filter(|(dx, dy)| { | ||||
|                             let nx = x as isize + dx; | ||||
|                             let ny = y + dy; | ||||
|                             nx >= 0 | ||||
|                                 && nx < w as isize | ||||
|                                 && ny >= 0 | ||||
|                                 && ny < h as isize | ||||
|                                 && map[ny as usize][nx as usize] == Cell::Empty | ||||
|                                 && dist[ny as usize][nx as usize] | ||||
|                                     >= dist[y as usize][x] + min_saving + 2 | ||||
|                         }) | ||||
|                         // .inspect(|v| {
 | ||||
|                         //     println!("{:?} {:?}", (x, y), v);
 | ||||
|                         // })
 | ||||
|                         .count() | ||||
|                     } else { | ||||
|                         0 | ||||
|                     } | ||||
|                 }) | ||||
|                 .sum::<usize>() | ||||
|         }) | ||||
|         .sum() | ||||
| } | ||||
| 
 | ||||
| #[aoc(day20, part2)] | ||||
| fn part2(input: &Input) -> usize { | ||||
|     let start = input.0; | ||||
|     let end = input.1; | ||||
|     let map = &input.2; | ||||
| 
 | ||||
|     #[cfg(not(test))] | ||||
|     let min_saving = 100; | ||||
|     #[cfg(test)] | ||||
|     let min_saving = 60; | ||||
| 
 | ||||
|     let max_skip = 20; | ||||
| 
 | ||||
|     let w = map[0].len(); | ||||
|     let h = map.len(); | ||||
| 
 | ||||
|     let mut dist = vec![vec![usize::MAX; w]; h]; | ||||
|     dist[start.1][start.0] = 0; | ||||
| 
 | ||||
|     let mut deque = std::collections::VecDeque::new(); | ||||
|     deque.push_back((0, start)); | ||||
| 
 | ||||
|     while let Some((d, pos)) = deque.pop_front() { | ||||
|         if dist[pos.1][pos.0] < d { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         dist[pos.1][pos.0] = d; | ||||
| 
 | ||||
|         [(1, 0), (-1, 0), (0, -1), (0, 1)] | ||||
|             .iter() | ||||
|             .for_each(|(dx, dy)| { | ||||
|                 let x = (pos.0 as isize + dx) as usize; | ||||
|                 let y = (pos.1 as isize + dy) as usize; | ||||
| 
 | ||||
|                 if x < w && y < h && map[y][x] == Cell::Empty { | ||||
|                     let new_d = d + 1; | ||||
|                     if new_d < dist[y][x] { | ||||
|                         deque.push_back((new_d, (x, y))); | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     map.iter() | ||||
|         .enumerate() | ||||
|         .map(|(y, line)| { | ||||
|             line.iter() | ||||
|                 .enumerate() | ||||
|                 .map(|(x, cell)| { | ||||
|                     let y = y as isize; | ||||
|                     if *cell == Cell::Empty { | ||||
|                         (-max_skip..=max_skip) | ||||
|                             .flat_map(|dx: isize| { | ||||
|                                 let skip = max_skip - dx.abs(); | ||||
|                                 (-skip..=skip).map(move |dy| (dx, dy)) | ||||
|                             }) | ||||
|                             .filter(|(dx, dy)| { | ||||
|                                 let nx = x as isize + dx; | ||||
|                                 let ny = y + dy; | ||||
|                                 nx >= 0 | ||||
|                                     && nx < w as isize | ||||
|                                     && ny >= 0 | ||||
|                                     && ny < h as isize | ||||
|                                     && map[ny as usize][nx as usize] == Cell::Empty | ||||
|                                     && dist[ny as usize][nx as usize] | ||||
|                                         >= dist[y as usize][x] | ||||
|                                             + min_saving | ||||
|                                             + dx.unsigned_abs() | ||||
|                                             + dy.unsigned_abs() | ||||
|                             }) | ||||
|                             // .inspect(|v| {
 | ||||
|                             //     println!("{:?} {:?}", (x, y), v);
 | ||||
|                             // })
 | ||||
|                             .count() | ||||
|                     } else { | ||||
|                         0 | ||||
|                     } | ||||
|                 }) | ||||
|                 .sum::<usize>() | ||||
|         }) | ||||
|         .sum() | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn part1_example() { | ||||
|         assert_eq!( | ||||
|             part1(&parse( | ||||
|                 "###############
 | ||||
| #...#...#.....# | ||||
| #.#.#.#.#.###.# | ||||
| #S#...#.#.#...# | ||||
| #######.#.#.### | ||||
| #######.#.#...# | ||||
| #######.#.###.# | ||||
| ###..E#...#...# | ||||
| ###.#######.### | ||||
| #...###...#...# | ||||
| #.#####.#.###.# | ||||
| #.#...#.#.#...# | ||||
| #.#.#.#.#.#.### | ||||
| #...#...#...### | ||||
| ###############" | ||||
|             )), | ||||
|             44 | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn part2_example() { | ||||
|         assert_eq!( | ||||
|             part2(&parse( | ||||
|                 "###############
 | ||||
| #...#...#.....# | ||||
| #.#.#.#.#.###.# | ||||
| #S#...#.#.#...# | ||||
| #######.#.#.### | ||||
| #######.#.#...# | ||||
| #######.#.###.# | ||||
| ###..E#...#...# | ||||
| ###.#######.### | ||||
| #...###...#...# | ||||
| #.#####.#.###.# | ||||
| #.#...#.#.#...# | ||||
| #.#.#.#.#.#.### | ||||
| #...#...#...### | ||||
| ###############" | ||||
|             )), | ||||
|             129 | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,3 @@ | ||||
| mod day19; | ||||
| mod day18; | ||||
| mod day17; | ||||
| mod day1; | ||||
| mod day10; | ||||
| mod day11; | ||||
| @ -9,7 +6,11 @@ mod day13; | ||||
| mod day14; | ||||
| mod day15; | ||||
| mod day16; | ||||
| mod day17; | ||||
| mod day18; | ||||
| mod day19; | ||||
| mod day2; | ||||
| mod day20; | ||||
| mod day3; | ||||
| mod day4; | ||||
| mod day5; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jan-Bulthuis
						Jan-Bulthuis