Constant cheating
This commit is contained in:
		
							parent
							
								
									962e7749f6
								
							
						
					
					
						commit
						e215cd7472
					
				| @ -1,135 +1,5 @@ | ||||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| struct Path { | ||||
|     path: [Option<DirButton>; 6], | ||||
| } | ||||
| 
 | ||||
| impl Path { | ||||
|     const fn from(buttons: &[DirButton]) -> Option<Self> { | ||||
|         let steps = buttons.len(); | ||||
|         let mut path = [None, None, None, None, None, None]; | ||||
|         let mut i = 0; | ||||
|         while i < steps { | ||||
|             path[i] = Some(buttons[i]); | ||||
|             i += 1; | ||||
|         } | ||||
|         path[i] = Some(DirButton::A); | ||||
|         Some(Self { path }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||||
| enum DirButton { | ||||
|     Up, | ||||
|     Down, | ||||
|     Left, | ||||
|     Right, | ||||
|     A, | ||||
| } | ||||
| 
 | ||||
| const DIRBUTTON_PATHS: [[[Option<Path>; 2]; 5]; 5] = [ | ||||
|     // Up
 | ||||
|     [ | ||||
|         // Up
 | ||||
|         [Path::from(&[]), None], | ||||
|         // Down
 | ||||
|         [Path::from(&[DirButton::Down]), None], | ||||
|         // Left
 | ||||
|         [Path::from(&[DirButton::Down, DirButton::Left]), None], | ||||
|         // Right
 | ||||
|         [ | ||||
|             Path::from(&[DirButton::Down, DirButton::Right]), | ||||
|             Path::from(&[DirButton::Right, DirButton::Down]), | ||||
|         ], | ||||
|         // A
 | ||||
|         [Path::from(&[DirButton::Right]), None], | ||||
|     ], | ||||
|     // Down
 | ||||
|     [ | ||||
|         // Up
 | ||||
|         [Path::from(&[DirButton::Up]), None], | ||||
|         // Down
 | ||||
|         [Path::from(&[]), None], | ||||
|         // Left
 | ||||
|         [Path::from(&[DirButton::Left]), None], | ||||
|         // Right
 | ||||
|         [Path::from(&[DirButton::Right]), None], | ||||
|         // A
 | ||||
|         [ | ||||
|             Path::from(&[DirButton::Up, DirButton::Right]), | ||||
|             Path::from(&[DirButton::Right, DirButton::Up]), | ||||
|         ], | ||||
|     ], | ||||
|     // Left
 | ||||
|     [ | ||||
|         // Up
 | ||||
|         [Path::from(&[DirButton::Right, DirButton::Up]), None], | ||||
|         // Down
 | ||||
|         [Path::from(&[DirButton::Right]), None], | ||||
|         // Left
 | ||||
|         [Path::from(&[]), None], | ||||
|         // Right
 | ||||
|         [Path::from(&[DirButton::Right, DirButton::Right]), None], | ||||
|         // A
 | ||||
|         [ | ||||
|             Path::from(&[DirButton::Right, DirButton::Right, DirButton::Up]), | ||||
|             None, | ||||
|         ], | ||||
|     ], | ||||
|     // Right
 | ||||
|     [ | ||||
|         // Up
 | ||||
|         [ | ||||
|             Path::from(&[DirButton::Up, DirButton::Left]), | ||||
|             Path::from(&[DirButton::Left, DirButton::Up]), | ||||
|         ], | ||||
|         // Down
 | ||||
|         [Path::from(&[DirButton::Left]), None], | ||||
|         // Left
 | ||||
|         [Path::from(&[DirButton::Left, DirButton::Left]), None], | ||||
|         // Right
 | ||||
|         [Path::from(&[]), None], | ||||
|         // A
 | ||||
|         [Path::from(&[DirButton::Up]), None], | ||||
|     ], | ||||
|     // A
 | ||||
|     [ | ||||
|         // Up
 | ||||
|         [Path::from(&[DirButton::Left]), None], | ||||
|         // Down
 | ||||
|         [ | ||||
|             Path::from(&[DirButton::Down, DirButton::Left]), | ||||
|             Path::from(&[DirButton::Left, DirButton::Down]), | ||||
|         ], | ||||
|         // Left
 | ||||
|         [ | ||||
|             Path::from(&[DirButton::Down, DirButton::Left, DirButton::Left]), | ||||
|             None, | ||||
|         ], | ||||
|         // Right
 | ||||
|         [Path::from(&[DirButton::Down]), None], | ||||
|         // A
 | ||||
|         [Path::from(&[]), None], | ||||
|     ], | ||||
| ]; | ||||
| 
 | ||||
| impl DirButton { | ||||
|     const fn index(&self) -> usize { | ||||
|         match self { | ||||
|             DirButton::Up => 0, | ||||
|             DirButton::Down => 1, | ||||
|             DirButton::Left => 2, | ||||
|             DirButton::Right => 3, | ||||
|             DirButton::A => 4, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     const fn paths_to(&self, other: &DirButton) -> &[Option<Path>; 2] { | ||||
|         &DIRBUTTON_PATHS[self.index()][other.index()] | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Eq)] | ||||
| enum NumButton { | ||||
|     One, | ||||
| @ -162,179 +32,350 @@ impl NumButton { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn paths_to(&self, other: &NumButton) -> [Option<Path>; 2] { | ||||
|     const fn index(&self) -> usize { | ||||
|         self.pos().1 * 3 + self.pos().0 | ||||
|     } | ||||
| 
 | ||||
|     const fn value(&self) -> usize { | ||||
|         match self { | ||||
|             NumButton::One => 1, | ||||
|             NumButton::Two => 2, | ||||
|             NumButton::Three => 3, | ||||
|             NumButton::Four => 4, | ||||
|             NumButton::Five => 5, | ||||
|             NumButton::Six => 6, | ||||
|             NumButton::Seven => 7, | ||||
|             NumButton::Eight => 8, | ||||
|             NumButton::Nine => 9, | ||||
|             NumButton::Zero => 0, | ||||
|             NumButton::A => unimplemented!(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     const fn from_index(idx: usize) -> Self { | ||||
|         match idx { | ||||
|             0 => NumButton::Seven, | ||||
|             1 => NumButton::Eight, | ||||
|             2 => NumButton::Nine, | ||||
|             3 => NumButton::Four, | ||||
|             4 => NumButton::Five, | ||||
|             5 => NumButton::Six, | ||||
|             6 => NumButton::One, | ||||
|             7 => NumButton::Two, | ||||
|             8 => NumButton::Three, | ||||
|             10 => NumButton::Zero, | ||||
|             11 => NumButton::A, | ||||
|             _ => unreachable!(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     const fn paths_to(&self, other: &NumButton) -> [Path; 2] { | ||||
|         let start = self.pos(); | ||||
|         let end = other.pos(); | ||||
| 
 | ||||
|         let bx = if start.0 < end.0 { | ||||
|             DirButton::Right | ||||
|         } else { | ||||
|             DirButton::Left | ||||
|         }; | ||||
|         let bx = if start.0 < end.0 { RIGHT } else { LEFT }; | ||||
|         let dx = start.0.abs_diff(end.0); | ||||
| 
 | ||||
|         let by = if start.1 < end.1 { | ||||
|             DirButton::Down | ||||
|         } else { | ||||
|             DirButton::Up | ||||
|         }; | ||||
|         let by = if start.1 < end.1 { DOWN } else { UP }; | ||||
|         let dy = start.1.abs_diff(end.1); | ||||
| 
 | ||||
|         if start.0 == 0 && end.1 == 3 { | ||||
|             let mut x = [None, None, None, None, None, None]; | ||||
|             (0..dx).for_each(|i| { | ||||
|                 x[i] = Some(bx); | ||||
|             }); | ||||
|             (0..dy).for_each(|i| { | ||||
|                 x[i + dx] = Some(by); | ||||
|             }); | ||||
|             x[dx + dy] = Some(DirButton::A); | ||||
|             [Some(Path { path: x }), None] | ||||
|         } else if end.0 == 0 && start.1 == 3 { | ||||
|             let mut y = [None, None, None, None, None, None]; | ||||
|             (0..dx).for_each(|i| { | ||||
|                 y[i + dy] = Some(bx); | ||||
|             }); | ||||
|             (0..dy).for_each(|i| { | ||||
|                 y[i] = Some(by); | ||||
|             }); | ||||
|             y[dx + dy] = Some(DirButton::A); | ||||
|             [Some(Path { path: y }), None] | ||||
|         if (start.0 == 0 && end.1 == 3) || start.1 == end.1 { | ||||
|             let mut x = [DistanceSize::MAX; 6]; | ||||
|             let y = [DistanceSize::MAX; 6]; | ||||
|             let mut i = dx; | ||||
|             while i > 0 { | ||||
|                 x[i - 1] = bx; | ||||
|                 i -= 1; | ||||
|             } | ||||
|             let mut i = dy; | ||||
|             while i > 0 { | ||||
|                 x[i - 1 + dx] = by; | ||||
|                 i -= 1; | ||||
|             } | ||||
|             x[dx + dy] = A; | ||||
|             [x, y] | ||||
|         } else if (end.0 == 0 && start.1 == 3) || start.0 == end.0 { | ||||
|             let x = [DistanceSize::MAX; 6]; | ||||
|             let mut y = [DistanceSize::MAX; 6]; | ||||
|             let mut i = dx; | ||||
|             while i > 0 { | ||||
|                 y[i - 1 + dy] = bx; | ||||
|                 i -= 1; | ||||
|             } | ||||
|             let mut i = dy; | ||||
|             while i > 0 { | ||||
|                 y[i - 1] = by; | ||||
|                 i -= 1; | ||||
|             } | ||||
|             y[dx + dy] = A; | ||||
|             [y, x] | ||||
|         } else { | ||||
|             let mut x = [None, None, None, None, None, None]; | ||||
|             let mut y = [None, None, None, None, None, None]; | ||||
|             (0..dx).for_each(|i| { | ||||
|                 x[i] = Some(bx); | ||||
|                 y[i + dy] = Some(bx); | ||||
|             }); | ||||
|             (0..dy).for_each(|i| { | ||||
|                 x[i + dx] = Some(by); | ||||
|                 y[i] = Some(by); | ||||
|             }); | ||||
|             x[dx + dy] = Some(DirButton::A); | ||||
|             y[dx + dy] = Some(DirButton::A); | ||||
|             [Some(Path { path: x }), Some(Path { path: y })] | ||||
|             let mut x = [DistanceSize::MAX; 6]; | ||||
|             let mut y = [DistanceSize::MAX; 6]; | ||||
|             let mut i = dx; | ||||
|             while i > 0 { | ||||
|                 x[i - 1] = bx; | ||||
|                 y[i - 1 + dy] = bx; | ||||
|                 i -= 1; | ||||
|             } | ||||
|             let mut i = dy; | ||||
|             while i > 0 { | ||||
|                 x[i - 1 + dx] = by; | ||||
|                 y[i - 1] = by; | ||||
|                 i -= 1; | ||||
|             } | ||||
|             x[dx + dy] = A; | ||||
|             y[dx + dy] = A; | ||||
|             [x, y] | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| type Input = Vec<(DistanceSize, Vec<NumButton>)>; | ||||
| type Input = String; | ||||
| 
 | ||||
| #[aoc_generator(day21)] | ||||
| fn parse(input: &str) -> Input { | ||||
|     input | ||||
|         .lines() | ||||
|         .map(|line| { | ||||
|             ( | ||||
|                 line[0..3].parse().unwrap(), | ||||
|                 line.chars() | ||||
|                     .map(|c| match c { | ||||
|                         '1' => NumButton::One, | ||||
|                         '2' => NumButton::Two, | ||||
|                         '3' => NumButton::Three, | ||||
|                         '4' => NumButton::Four, | ||||
|                         '5' => NumButton::Five, | ||||
|                         '6' => NumButton::Six, | ||||
|                         '7' => NumButton::Seven, | ||||
|                         '8' => NumButton::Eight, | ||||
|                         '9' => NumButton::Nine, | ||||
|                         '0' => NumButton::Zero, | ||||
|                         'A' => NumButton::A, | ||||
|                         _ => unreachable!(), | ||||
|                     }) | ||||
|                     .collect(), | ||||
|             ) | ||||
|         }) | ||||
|         .collect() | ||||
|     input.to_string() | ||||
| } | ||||
| 
 | ||||
| type DistanceSize = u64; | ||||
| type Path = [DistanceSize; 6]; | ||||
| 
 | ||||
| type DistanceSize = usize; | ||||
| type DistanceMatrix = [[DistanceSize; 5]; 5]; | ||||
| 
 | ||||
| fn precompute_steps(steps: &mut [DistanceMatrix]) { | ||||
|     if steps.len() == 1 { | ||||
|         return; | ||||
| const fn shortest_dir_path(path: &Path, steps: &DistanceMatrix) -> DistanceSize { | ||||
|     let mut sum = 0; | ||||
|     let mut pos = A; | ||||
|     let mut i = 0; | ||||
| 
 | ||||
|     while i < 6 && path[i] != DistanceSize::MAX { | ||||
|         sum += steps[pos][path[i]]; | ||||
|         pos = path[i]; | ||||
|         i += 1; | ||||
|     } | ||||
| 
 | ||||
|     precompute_steps(&mut steps[1..]); | ||||
| 
 | ||||
|     let buttons = [ | ||||
|         DirButton::Up, | ||||
|         DirButton::Down, | ||||
|         DirButton::Left, | ||||
|         DirButton::Right, | ||||
|         DirButton::A, | ||||
|     ]; | ||||
| 
 | ||||
|     buttons.iter().for_each(|start| { | ||||
|         buttons.iter().for_each(|end| { | ||||
|             steps[0][start.index()][end.index()] = start | ||||
|                 .paths_to(end) | ||||
|                 .iter() | ||||
|                 .flatten() | ||||
|                 .map(|path| { | ||||
|                     path.path | ||||
|                         .iter() | ||||
|                         .flatten() | ||||
|                         .fold((0, &DirButton::A), |acc, next| { | ||||
|                             (acc.0 + steps[1][acc.1.index()][next.index()], next) | ||||
|                         }) | ||||
|                         .0 | ||||
|                 }) | ||||
|                 .fold(DistanceSize::MAX, |acc, next| acc.min(next)); | ||||
|         }); | ||||
|     }); | ||||
|     sum | ||||
| } | ||||
| 
 | ||||
| fn shortest_dir_path(path: &Path, steps: &mut [DistanceMatrix]) -> DistanceSize { | ||||
|     path.path | ||||
|         .iter() | ||||
|         .flatten() | ||||
|         .fold((0, &DirButton::A), |acc, next| { | ||||
|             (acc.0 + steps[0][acc.1.index()][next.index()], next) | ||||
|         }) | ||||
|         .0 | ||||
| } | ||||
| 
 | ||||
| fn shortest_path(path: &[NumButton], steps: &mut [DistanceMatrix]) -> DistanceSize { | ||||
|     path.iter() | ||||
|         .fold((0, &NumButton::A), |acc, end| { | ||||
|             ( | ||||
|                 acc.0 | ||||
|                     + acc | ||||
|                         .1 | ||||
|                         .paths_to(end) | ||||
|                         .iter() | ||||
|                         .flatten() | ||||
|                         .map(|path| shortest_dir_path(path, steps)) | ||||
|                         .fold(DistanceSize::MAX, |acc, next| acc.min(next)), | ||||
|                 end, | ||||
| const fn shortest_path( | ||||
|     path: &[usize], | ||||
|     paths: &[[[Path; 2]; 12]; 12], | ||||
|     steps: &DistanceMatrix, | ||||
| ) -> DistanceSize { | ||||
|     let mut sum = 0; | ||||
|     let mut pos = NumButton::A.index(); | ||||
|     let mut i = 0; | ||||
|     while i < path.len() { | ||||
|         let step_paths = paths[pos][path[i]]; | ||||
|         sum += if step_paths[1][0] != DistanceSize::MAX { | ||||
|             min( | ||||
|                 shortest_dir_path(&step_paths[0], steps), | ||||
|                 shortest_dir_path(&step_paths[1], steps), | ||||
|             ) | ||||
|         }) | ||||
|         .0 | ||||
|         } else { | ||||
|             shortest_dir_path(&step_paths[0], steps) | ||||
|         }; | ||||
|         pos = path[i]; | ||||
|         i += 1; | ||||
|     } | ||||
|     sum | ||||
| } | ||||
| 
 | ||||
| const UP: usize = 0; | ||||
| const DOWN: usize = 1; | ||||
| const LEFT: usize = 2; | ||||
| const RIGHT: usize = 3; | ||||
| const A: usize = 4; | ||||
| 
 | ||||
| const fn min(a: usize, b: usize) -> usize { | ||||
|     if a < b { | ||||
|         a | ||||
|     } else { | ||||
|         b | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| const fn precompute_steps_new<const N: usize>(matrix: DistanceMatrix) -> DistanceMatrix { | ||||
|     let mut steps = 0; | ||||
|     let mut matrix = matrix; | ||||
| 
 | ||||
|     while steps < N { | ||||
|         let up = matrix[A][UP] + matrix[UP][A]; | ||||
|         let down = matrix[A][DOWN] + matrix[DOWN][A]; | ||||
|         let left = matrix[A][LEFT] + matrix[LEFT][A]; | ||||
|         let right = matrix[A][RIGHT] + matrix[RIGHT][A]; | ||||
|         let left_left = matrix[A][LEFT] + matrix[LEFT][LEFT] + matrix[LEFT][A]; | ||||
|         let right_right = matrix[A][RIGHT] + matrix[RIGHT][RIGHT] + matrix[RIGHT][A]; | ||||
|         let left_down = matrix[A][LEFT] + matrix[LEFT][DOWN] + matrix[DOWN][A]; | ||||
|         let down_left = matrix[A][DOWN] + matrix[DOWN][LEFT] + matrix[LEFT][A]; | ||||
|         let left_up = matrix[A][LEFT] + matrix[LEFT][UP] + matrix[UP][A]; | ||||
|         let up_left = matrix[A][UP] + matrix[UP][LEFT] + matrix[LEFT][A]; | ||||
|         let right_down = matrix[A][RIGHT] + matrix[RIGHT][DOWN] + matrix[DOWN][A]; | ||||
|         let down_right = matrix[A][DOWN] + matrix[DOWN][RIGHT] + matrix[RIGHT][A]; | ||||
|         let right_up = matrix[A][RIGHT] + matrix[RIGHT][UP] + matrix[UP][A]; | ||||
|         let up_right = matrix[A][UP] + matrix[UP][RIGHT] + matrix[RIGHT][A]; | ||||
|         let down_left_left = | ||||
|             matrix[A][DOWN] + matrix[DOWN][LEFT] + matrix[LEFT][LEFT] + matrix[LEFT][A]; | ||||
|         let right_right_up = | ||||
|             matrix[A][RIGHT] + matrix[RIGHT][RIGHT] + matrix[RIGHT][UP] + matrix[UP][A]; | ||||
| 
 | ||||
|         matrix[UP][UP] = 1; | ||||
|         matrix[UP][DOWN] = down; | ||||
|         matrix[UP][LEFT] = down_left; | ||||
|         matrix[UP][RIGHT] = min(down_right, right_down); | ||||
|         matrix[UP][A] = right; | ||||
| 
 | ||||
|         matrix[DOWN][UP] = up; | ||||
|         matrix[DOWN][DOWN] = 1; | ||||
|         matrix[DOWN][LEFT] = left; | ||||
|         matrix[DOWN][RIGHT] = right; | ||||
|         matrix[DOWN][A] = min(up_right, right_up); | ||||
| 
 | ||||
|         matrix[LEFT][UP] = right_up; | ||||
|         matrix[LEFT][DOWN] = right; | ||||
|         matrix[LEFT][LEFT] = 1; | ||||
|         matrix[LEFT][RIGHT] = right_right; | ||||
|         matrix[LEFT][A] = right_right_up; | ||||
| 
 | ||||
|         matrix[RIGHT][UP] = min(up_left, left_up); | ||||
|         matrix[RIGHT][DOWN] = left; | ||||
|         matrix[RIGHT][LEFT] = left_left; | ||||
|         matrix[RIGHT][RIGHT] = 1; | ||||
|         matrix[RIGHT][A] = up; | ||||
| 
 | ||||
|         matrix[A][UP] = left; | ||||
|         matrix[A][DOWN] = min(left_down, down_left); | ||||
|         matrix[A][LEFT] = down_left_left; | ||||
|         matrix[A][RIGHT] = down; | ||||
|         matrix[A][A] = 1; | ||||
| 
 | ||||
|         steps += 1; | ||||
|     } | ||||
| 
 | ||||
|     matrix | ||||
| } | ||||
| 
 | ||||
| const fn precompute_paths() -> [[[Path; 2]; 12]; 12] { | ||||
|     let mut paths = [[[[DistanceSize::MAX; 6], [DistanceSize::MAX; 6]]; 12]; 12]; | ||||
| 
 | ||||
|     let mut start = 0usize; | ||||
|     while start < 12 { | ||||
|         let mut end = 0usize; | ||||
|         if start == 9 { | ||||
|             start += 1; | ||||
|             continue; | ||||
|         } | ||||
|         while end < 12 { | ||||
|             if end == 9 { | ||||
|                 end += 1; | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             paths[start][end] = NumButton::from_index(start).paths_to(&NumButton::from_index(end)); | ||||
| 
 | ||||
|             end += 1; | ||||
|         } | ||||
|         start += 1; | ||||
|     } | ||||
| 
 | ||||
|     paths | ||||
| } | ||||
| 
 | ||||
| const fn precompute_num_paths( | ||||
|     steps: &[[usize; 5]; 5], | ||||
|     paths: &[[[[usize; 6]; 2]; 12]; 12], | ||||
| ) -> [[[usize; 12]; 12]; 12] { | ||||
|     let mut matrix = [[[0; 12]; 12]; 12]; | ||||
| 
 | ||||
|     let mut one = 0usize; | ||||
|     while one < 12 { | ||||
|         if one == 9 || one == 11 { | ||||
|             one += 1; | ||||
|             continue; | ||||
|         } | ||||
|         let mut two = 0usize; | ||||
|         while two < 12 { | ||||
|             if two == 9 || two == 11 { | ||||
|                 two += 1; | ||||
|                 continue; | ||||
|             } | ||||
|             let mut three = 0usize; | ||||
|             while three < 12 { | ||||
|                 if three == 9 || three == 11 { | ||||
|                     three += 1; | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 let num = NumButton::from_index(one).value() * 100 | ||||
|                     + NumButton::from_index(two).value() * 10 | ||||
|                     + NumButton::from_index(three).value(); | ||||
|                 matrix[one][two][three] = | ||||
|                     num * shortest_path(&[one, two, three, NumButton::A.index()], paths, steps); | ||||
| 
 | ||||
|                 three += 1; | ||||
|             } | ||||
|             two += 1; | ||||
|         } | ||||
|         one += 1; | ||||
|     } | ||||
| 
 | ||||
|     matrix | ||||
| } | ||||
| 
 | ||||
| const CHAR_IDX: [usize; 10] = [ | ||||
|     NumButton::Zero.index(), | ||||
|     NumButton::One.index(), | ||||
|     NumButton::Two.index(), | ||||
|     NumButton::Three.index(), | ||||
|     NumButton::Four.index(), | ||||
|     NumButton::Five.index(), | ||||
|     NumButton::Six.index(), | ||||
|     NumButton::Seven.index(), | ||||
|     NumButton::Eight.index(), | ||||
|     NumButton::Nine.index(), | ||||
| ]; | ||||
| 
 | ||||
| #[aoc(day21, part1)] | ||||
| fn part1(input: &Input) -> DistanceSize { | ||||
|     let mut steps = vec![[[1; 5]; 5]; 3]; | ||||
| 
 | ||||
|     precompute_steps(&mut steps); | ||||
|     let num_paths = const { | ||||
|         let steps = precompute_steps_new::<2>([[1; 5]; 5]); | ||||
|         let paths = precompute_paths(); | ||||
|         precompute_num_paths(&steps, &paths) | ||||
|     }; | ||||
| 
 | ||||
|     input | ||||
|         .iter() | ||||
|         .map(|(num, path)| num * shortest_path(path, &mut steps)) | ||||
|         .as_bytes() | ||||
|         .chunks(5) | ||||
|         .map(|chunk| { | ||||
|             let num = [ | ||||
|                 CHAR_IDX[chunk[0] as usize - 48], | ||||
|                 CHAR_IDX[chunk[1] as usize - 48], | ||||
|                 CHAR_IDX[chunk[2] as usize - 48], | ||||
|             ]; | ||||
|             num_paths[num[0]][num[1]][num[2]] | ||||
|         }) | ||||
|         .sum() | ||||
| } | ||||
| 
 | ||||
| #[aoc(day21, part2)] | ||||
| fn part2(input: &Input) -> DistanceSize { | ||||
|     let mut steps = vec![[[1; 5]; 5]; 26]; | ||||
| 
 | ||||
|     precompute_steps(&mut steps); | ||||
|     let num_paths = const { | ||||
|         let steps = precompute_steps_new::<25>([[1; 5]; 5]); | ||||
|         let paths = precompute_paths(); | ||||
|         precompute_num_paths(&steps, &paths) | ||||
|     }; | ||||
| 
 | ||||
|     input | ||||
|         .iter() | ||||
|         .map(|(num, path)| num * shortest_path(path, &mut steps)) | ||||
|         .as_bytes() | ||||
|         .chunks(5) | ||||
|         .map(|chunk| { | ||||
|             let num = [ | ||||
|                 CHAR_IDX[chunk[0] as usize - 48], | ||||
|                 CHAR_IDX[chunk[1] as usize - 48], | ||||
|                 CHAR_IDX[chunk[2] as usize - 48], | ||||
|             ]; | ||||
|             num_paths[num[0]][num[1]][num[2]] | ||||
|         }) | ||||
|         .sum() | ||||
| } | ||||
| 
 | ||||
| @ -344,8 +385,8 @@ mod tests { | ||||
| 
 | ||||
|     #[test] | ||||
|     fn part1_example() { | ||||
|         assert_eq!(part1(&parse("179A")), 68 * 179); | ||||
|         assert_eq!(part1(&parse("379A")), 64 * 379); | ||||
|         assert_eq!(part1(&parse("179A")), 68 * 179); | ||||
|         assert_eq!(part1(&parse("456A")), 64 * 456); | ||||
|         assert_eq!(part1(&parse("980A")), 60 * 980); | ||||
|         assert_eq!(part1(&parse("029A")), 68 * 29); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jan-Bulthuis
						Jan-Bulthuis