adventofcode

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

commit
10a3f14f9ce5cd83e849c9868fbe88b7a76fad42
parent
d94a3b4129af946d8981c9031efee339de9454c0
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-12-21 10:22
2024-12-21

Diffstat

A 2024/21/input.txt 5 +++++
A 2024/21/solution.rs 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A 2024/21/test.txt 5 +++++

3 files changed, 144 insertions, 0 deletions


diff --git a/2024/21/input.txt b/2024/21/input.txt

@@ -0,0 +1,5 @@
   -1     1 208A
   -1     2 586A
   -1     3 341A
   -1     4 463A
   -1     5 593A

diff --git a/2024/21/solution.rs b/2024/21/solution.rs

@@ -0,0 +1,134 @@
   -1     1 use std::collections::HashMap;
   -1     2 
   -1     3 #[path = "../lib.rs"]
   -1     4 mod lib;
   -1     5 
   -1     6 #[derive(Eq, Hash, PartialEq, Clone, Copy)]
   -1     7 enum Dir {
   -1     8     Left,
   -1     9     Down,
   -1    10     Right,
   -1    11     Up,
   -1    12     A,
   -1    13 }
   -1    14 
   -1    15 fn get_pos_dir(v: Dir) -> (usize, usize) {
   -1    16     return match v {
   -1    17         Dir::Left => (0, 0),
   -1    18         Dir::Down => (1, 0),
   -1    19         Dir::Right => (2, 0),
   -1    20         Dir::Up => (1, 1),
   -1    21         Dir::A => (2, 1),
   -1    22     };
   -1    23 }
   -1    24 
   -1    25 fn get_pos_numeric(v: u8) -> (usize, usize) {
   -1    26     return match v {
   -1    27         b'0' => (1, 1),
   -1    28         b'A' => (2, 1),
   -1    29         b'1' => (0, 2),
   -1    30         b'2' => (1, 2),
   -1    31         b'3' => (2, 2),
   -1    32         b'4' => (0, 3),
   -1    33         b'5' => (1, 3),
   -1    34         b'6' => (2, 3),
   -1    35         b'7' => (0, 4),
   -1    36         b'8' => (1, 4),
   -1    37         b'9' => (2, 4),
   -1    38         _ => unreachable!(),
   -1    39     };
   -1    40 }
   -1    41 
   -1    42 fn press(x1: usize, y1: usize, x2: usize, y2: usize, steps: usize, cache: &mut HashMap<(Dir, Dir, usize), usize>) -> usize {
   -1    43     let mut count1 = 0;
   -1    44     let mut count2 = 0;
   -1    45 
   -1    46     if x2 == 0 && y1 == 1 {
   -1    47         count1 = usize::MAX;
   -1    48     } else {
   -1    49         let mut pos = Dir::A;
   -1    50         for _ in x1..x2 {
   -1    51             count1 += press_dir(Dir::Right, pos, steps - 1, cache);
   -1    52             pos = Dir::Right;
   -1    53         }
   -1    54         for _ in x2..x1 {
   -1    55             count1 += press_dir(Dir::Left, pos, steps - 1, cache);
   -1    56             pos = Dir::Left;
   -1    57         }
   -1    58         for _ in y1..y2 {
   -1    59             count1 += press_dir(Dir::Up, pos, steps - 1, cache);
   -1    60             pos = Dir::Up;
   -1    61         }
   -1    62         for _ in y2..y1 {
   -1    63             count1 += press_dir(Dir::Down, pos, steps - 1, cache);
   -1    64             pos = Dir::Down;
   -1    65         }
   -1    66         count1 += press_dir(Dir::A, pos, steps - 1, cache);
   -1    67     }
   -1    68 
   -1    69     if x1 == 0 && y2 == 1 {
   -1    70         count2 = usize::MAX;
   -1    71     } else {
   -1    72         let mut pos = Dir::A;
   -1    73         for _ in y1..y2 {
   -1    74             count2 += press_dir(Dir::Up, pos, steps - 1, cache);
   -1    75             pos = Dir::Up;
   -1    76         }
   -1    77         for _ in y2..y1 {
   -1    78             count2 += press_dir(Dir::Down, pos, steps - 1, cache);
   -1    79             pos = Dir::Down;
   -1    80         }
   -1    81         for _ in x1..x2 {
   -1    82             count2 += press_dir(Dir::Right, pos, steps - 1, cache);
   -1    83             pos = Dir::Right;
   -1    84         }
   -1    85         for _ in x2..x1 {
   -1    86             count2 += press_dir(Dir::Left, pos, steps - 1, cache);
   -1    87             pos = Dir::Left;
   -1    88         }
   -1    89         count2 += press_dir(Dir::A, pos, steps - 1, cache);
   -1    90     }
   -1    91 
   -1    92     return count1.min(count2);
   -1    93 }
   -1    94 
   -1    95 fn press_dir(button: Dir, prev: Dir, steps: usize, cache: &mut HashMap<(Dir, Dir, usize), usize>) -> usize {
   -1    96     if steps == 0 {
   -1    97         return 1;
   -1    98     } else if let Some(count) = cache.get(&(button, prev, steps)) {
   -1    99         return *count;
   -1   100     } else {
   -1   101         let (x1, y1) = get_pos_dir(prev);
   -1   102         let (x2, y2) = get_pos_dir(button);
   -1   103         let count = press(x1, y1, x2, y2, steps, cache);
   -1   104         cache.insert((button, prev, steps), count);
   -1   105         return count;
   -1   106     }
   -1   107 }
   -1   108 
   -1   109 fn get_sequence(code: &str, steps: usize, cache: &mut HashMap<(Dir, Dir, usize), usize>) -> usize {
   -1   110     let mut pos = b'A';
   -1   111     let mut count = 0;
   -1   112     for b in code.bytes() {
   -1   113         let (x1, y1) = get_pos_numeric(pos);
   -1   114         let (x2, y2) = get_pos_numeric(b);
   -1   115         count += press(x1, y1, x2, y2, steps, cache);
   -1   116         pos = b;
   -1   117     }
   -1   118     return count;
   -1   119 }
   -1   120 
   -1   121 fn main() {
   -1   122     let mut sum1 = 0;
   -1   123     let mut sum2 = 0;
   -1   124     let mut cache = HashMap::new();
   -1   125 
   -1   126     for line in lib::iter_input() {
   -1   127         let value = line[..line.len() - 1].parse::<usize>().unwrap();
   -1   128         sum1 += get_sequence(&line, 2 + 1, &mut cache) * value;
   -1   129         sum2 += get_sequence(&line, 25 + 1, &mut cache) * value;
   -1   130     }
   -1   131 
   -1   132     println!("part1: {}", sum1);
   -1   133     println!("part2: {}", sum2);
   -1   134 }

diff --git a/2024/21/test.txt b/2024/21/test.txt

@@ -0,0 +1,5 @@
   -1     1 029A
   -1     2 980A
   -1     3 179A
   -1     4 456A
   -1     5 379A