adventofcode

git clone https://git.ce9e.org/adventofcode.git

commit
30a31e74f232471c33812cbc4bd989fff377aadd
parent
a59a12207c481260b0a184f37ec8fd4077114217
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2023-12-18 14:38
refactor: do not include steps in key space

Diffstat

M 2023/17/solution.rs 67 ++++++++++++++++++++++++++++---------------------------------

1 files changed, 31 insertions, 36 deletions


diff --git a/2023/17/solution.rs b/2023/17/solution.rs

@@ -13,26 +13,20 @@ enum Dir {
   13    13 }
   14    14 
   15    15 impl Dir {
   16    -1     fn inverse(&self) -> Self {
   -1    16     fn apply(&self, x: usize, y: usize, k: usize, n: usize) -> Option<(usize, usize)> {
   17    17         return match self {
   18    -1             Dir::Left => Dir::Right,
   19    -1             Dir::Right => Dir::Left,
   20    -1             Dir::Up => Dir::Down,
   21    -1             Dir::Down => Dir::Up,
   -1    18             Dir::Left => if x >= k { Some((x - k, y)) } else { None }
   -1    19             Dir::Right => if x + k < n { Some((x + k, y)) } else { None }
   -1    20             Dir::Up => if y >= k { Some((x, y - k)) } else { None }
   -1    21             Dir::Down => if y + k < n { Some((x, y + k)) } else { None }
   22    22         };
   23    23     }
   24    24 
   25    -1     fn apply(&self, x: usize, y: usize, n: usize) -> Option<(usize, usize)> {
   -1    25     fn sides(&self) -> [Self; 2] {
   26    26         return match self {
   27    -1             Dir::Left => if x > 0 { Some((x - 1, y)) } else { None }
   28    -1             Dir::Right => if x + 1 < n { Some((x + 1, y)) } else { None }
   29    -1             Dir::Up => if y > 0 { Some((x, y - 1)) } else { None }
   30    -1             Dir::Down => if y + 1 < n { Some((x, y + 1)) } else { None }
   31    -1         };
   32    -1     }
   33    -1 
   34    -1     fn iter() -> [Self; 4] {
   35    -1         return [Dir::Left, Dir::Right, Dir::Up, Dir::Down];
   -1    27             Dir::Left | Dir::Right => [Dir::Up, Dir::Down],
   -1    28             Dir::Up | Dir::Down => [Dir::Left, Dir::Right],
   -1    29         }
   36    30     }
   37    31 }
   38    32 
@@ -52,30 +46,31 @@ fn find_path(map: &Vec<Vec<u32>>, min_steps: usize, max_steps: usize) -> u32 {
   52    46     let mut min = HashMap::new();
   53    47     let mut result = u32::MAX;
   54    48 
   55    -1     min.insert((0, 0, Dir::Right, 1), 0);
   56    -1     queue.push_back((0, 0, Dir::Right, 1));
   -1    49     min.insert((0, 0, Dir::Right), 0);
   -1    50     queue.push_back((0, 0, Dir::Right));
   57    51 
   58    -1     min.insert((0, 0, Dir::Down, 1), 0);
   59    -1     queue.push_back((0, 0, Dir::Down, 1));
   -1    52     min.insert((0, 0, Dir::Down), 0);
   -1    53     queue.push_back((0, 0, Dir::Down));
   60    54 
   61    -1     while let Some((y, x, dir, steps)) = queue.pop_front() {
   62    -1         let v = *min.get(&(y, x, dir, steps)).unwrap_or(&u32::MAX);
   63    -1         if (x, y) == (n - 1, n - 1) && steps >= min_steps {
   64    -1             result = result.min(v);
   -1    55     while let Some((y, x, dir)) = queue.pop_front() {
   -1    56         let value = *min.get(&(y, x, dir)).unwrap_or(&u32::MAX);
   -1    57         if (x, y) == (n - 1, n - 1) {
   -1    58             result = result.min(value);
   65    59         }
   66    -1         for ndir in Dir::iter() {
   67    -1             if (ndir == dir && steps >= max_steps)
   68    -1                 || ndir == dir.inverse()
   69    -1                 || (ndir != dir && steps < min_steps)
   70    -1             {
   71    -1                 continue;
   72    -1             }
   73    -1             if let Some((nx, ny)) = ndir.apply(x, y, n) {
   74    -1                 let s = if ndir == dir { steps + 1 } else { 1 };
   75    -1                 let key = (ny, nx, ndir, s);
   76    -1                 if v + map[ny][nx] < *min.get(&key).unwrap_or(&u32::MAX) {
   77    -1                     min.insert(key, v + map[ny][nx]);
   78    -1                     queue.push_back(key);
   -1    60         for ndir in dir.sides() {
   -1    61             let mut new_value = value;
   -1    62             for k in 1..=max_steps {
   -1    63                 if let Some((nx, ny)) = ndir.apply(x, y, k, n) {
   -1    64                     new_value += map[ny][nx];
   -1    65                     if k >= min_steps {
   -1    66                         let key = (ny, nx, ndir);
   -1    67                         if new_value < *min.get(&key).unwrap_or(&u32::MAX) {
   -1    68                             min.insert(key, new_value);
   -1    69                             queue.push_back(key);
   -1    70                         }
   -1    71                     }
   -1    72                 } else {
   -1    73                     break;
   79    74                 }
   80    75             }
   81    76         }