generated from janezicmatej/aoc-template
	solution: day 21
This commit is contained in:
		
							
								
								
									
										11
									
								
								data/examples/21.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								data/examples/21.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| ........... | ||||
| .....###.#. | ||||
| .###.##..#. | ||||
| ..#.#...#.. | ||||
| ....#.#.... | ||||
| .##..S####. | ||||
| .##..#...#. | ||||
| .......##.. | ||||
| .##.#.####. | ||||
| .##..##.##. | ||||
| ........... | ||||
							
								
								
									
										106
									
								
								src/bin/21.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/bin/21.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| use std::{collections::HashSet, usize}; | ||||
|  | ||||
| fn parse_input(input: &str) -> (Vec<Vec<u8>>, (isize, isize)) { | ||||
|     let mut grid: Vec<_> = input.lines().map(|x| x.as_bytes().to_vec()).collect(); | ||||
|  | ||||
|     let start = grid | ||||
|         .iter() | ||||
|         .enumerate() | ||||
|         .flat_map(|(y, item)| item.iter().enumerate().map(move |(x, item)| (x, y, *item))) | ||||
|         .find_map(|(x, y, s)| if s == b'S' { Some((y, x)) } else { None }) | ||||
|         .unwrap(); | ||||
|  | ||||
|     grid[start.0][start.1] = b'.'; | ||||
|  | ||||
|     (grid, (start.0 as isize, start.1 as isize)) | ||||
| } | ||||
|  | ||||
| fn walk_return_at( | ||||
|     grid: &[Vec<u8>], | ||||
|     start: (isize, isize), | ||||
|     mut returns: Vec<usize>, | ||||
|     can_cycle: bool, | ||||
| ) -> Vec<usize> { | ||||
|     returns.sort_by(|a, b| b.cmp(a)); | ||||
|  | ||||
|     let h = grid.len() as isize; | ||||
|     let w = grid[0].len() as isize; | ||||
|  | ||||
|     let invalid_indexing = |y, x| y < 0 || y >= h || x < 0 || x >= w; | ||||
|  | ||||
|     let mut results = Vec::new(); | ||||
|     let length = returns[0]; | ||||
|     let mut next = returns.pop().unwrap(); | ||||
|  | ||||
|     let mut visited = HashSet::new(); | ||||
|     visited.insert(start); | ||||
|  | ||||
|     for i in 1..=length { | ||||
|         let mut new_visited = HashSet::new(); | ||||
|  | ||||
|         for (y, x) in visited.iter() { | ||||
|             for (dy, dx) in [(1, 0), (0, 1), (-1, 0), (0, -1)] { | ||||
|                 let (ny, nx) = (y + dy, x + dx); | ||||
|  | ||||
|                 if !can_cycle && invalid_indexing(ny, nx) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 let (cy, cx) = (ny.rem_euclid(h) as usize, nx.rem_euclid(w) as usize); | ||||
|  | ||||
|                 if grid[cy][cx] == b'.' { | ||||
|                     new_visited.insert((ny, nx)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         visited = new_visited; | ||||
|  | ||||
|         if i == next { | ||||
|             results.push(visited.len()); | ||||
|             if !returns.is_empty() { | ||||
|                 next = returns.pop().unwrap(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     results | ||||
| } | ||||
|  | ||||
| pub fn part_one(input: &str) -> Option<usize> { | ||||
|     let (grid, start) = parse_input(input); | ||||
|     let result = walk_return_at(&grid, start, vec![64], false); | ||||
|  | ||||
|     Some(result[0]) | ||||
| } | ||||
|  | ||||
| pub fn part_two(input: &str) -> Option<usize> { | ||||
|     let (grid, start) = parse_input(input); | ||||
|  | ||||
|     let h = grid.len(); | ||||
|     let s = start.0 as usize; | ||||
|  | ||||
|     let result = walk_return_at(&grid, start, vec![s, s + h, s + 2 * h], true); | ||||
|  | ||||
|     let a = (result[2] - 2 * result[1] + result[0]) / 2; | ||||
|     let b = (result[1] - result[0]) - a; | ||||
|     let c = result[0]; | ||||
|  | ||||
|     let x = 26501365 / h; | ||||
|  | ||||
|     Some(a * x * x + b * x + c) | ||||
| } | ||||
|  | ||||
| aoc::solution!(21); | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
|     #[test] | ||||
|     fn test_part_one() { | ||||
|         assert_eq!( | ||||
|             part_one(&aoc::template::read_file("examples", 21)), | ||||
|             Some(42) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user