Advertisement
saaoijeefhiuh

2024 day 21

Dec 21st, 2024 (edited)
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.29 KB | None | 0 0
  1. use memoize::memoize;
  2.  
  3. fn numpad(key: char) -> (i32, i32) {
  4.     match key {
  5.         '7' => (0, 0),
  6.         '8' => (0, 1),
  7.         '9' => (0, 2),
  8.         '4' => (1, 0),
  9.         '5' => (1, 1),
  10.         '6' => (1, 2),
  11.         '1' => (2, 0),
  12.         '2' => (2, 1),
  13.         '3' => (2, 2),
  14.         '0' => (3, 1),
  15.         'A' => (3, 2),
  16.         _ => panic!(),
  17.     }
  18. }
  19.  
  20. fn arrowpad(key: char) -> (i32, i32) {
  21.     match key {
  22.         '^' => (0, 1),
  23.         'A' => (0, 2),
  24.         '<' => (1, 0),
  25.         'v' => (1, 1),
  26.         '>' => (1, 2),
  27.         _ => panic!(),
  28.     }
  29. }
  30.  
  31. #[memoize]
  32. fn do_arrows(i: i32, j: i32, steps: usize, h_first: bool) -> usize {
  33.     let (ii, jj) = (i.unsigned_abs() as usize, j.unsigned_abs() as usize);
  34.     let mut chunk = vec![if i > 0 { '^' } else { 'v' }; ii];
  35.     chunk.extend(vec![if j > 0 { '<' } else { '>' }; jj]);
  36.  
  37.     if h_first {
  38.         chunk.reverse();
  39.     }
  40.  
  41.     chunk.push('A');
  42.  
  43.     if steps == 0 {
  44.         chunk.len()
  45.     } else {
  46.         let mut loc = arrowpad('A');
  47.  
  48.         chunk
  49.             .into_iter()
  50.             .map(|c| {
  51.                 let n = arrowpad(c);
  52.                 let p = loc;
  53.                 loc = n;
  54.                 let d = (p.0 - n.0, p.1 - n.1);
  55.                 if d.0 == 0 || d.1 == 0 {
  56.                     // straight line, search only once, order is irrelevant
  57.                     do_arrows(d.0, d.1, steps - 1, false)
  58.                 } else if n == (1, 0) && p.0 == 0 {
  59.                     // must search down first
  60.                     do_arrows(d.0, d.1, steps - 1, false)
  61.                 } else if p == (1, 0) && n.0 == 0 {
  62.                     // must search horiz first
  63.                     do_arrows(d.0, d.1, steps - 1, true)
  64.                 } else {
  65.                     // can search in either order
  66.                     std::cmp::min(
  67.                         do_arrows(d.0, d.1, steps - 1, false),
  68.                         do_arrows(d.0, d.1, steps - 1, true),
  69.                     )
  70.                 }
  71.             })
  72.             .sum()
  73.     }
  74. }
  75.  
  76. fn enter_sequence(sequence: &str, steps: usize) -> usize {
  77.     let mut loc = numpad('A');
  78.  
  79.     sequence
  80.         .chars()
  81.         .map(|c| {
  82.             // either move horizontally or vertically first
  83.             // in some cases only one will be valid...
  84.             let n = numpad(c);
  85.             let p = loc;
  86.             let d = (loc.0 - n.0, loc.1 - n.1);
  87.             loc = n;
  88.             if p.0 == 3 && n.1 == 0 {
  89.                 // must move up first
  90.                 do_arrows(d.0, d.1, steps, false)
  91.             } else if p.1 == 0 && n.0 == 3 {
  92.                 // must move right first
  93.                 do_arrows(d.0, d.1, steps, true)
  94.             } else {
  95.                 // move in either direction
  96.                 std::cmp::min(
  97.                     do_arrows(d.0, d.1, steps, true),
  98.                     do_arrows(d.0, d.1, steps, false),
  99.                 )
  100.             }
  101.         })
  102.         .sum::<usize>()
  103.         * sequence[0..3].parse::<usize>().unwrap()
  104. }
  105.  
  106. pub fn part_one(input: &str) -> Option<usize> {
  107.     memoized_flush_do_arrows();
  108.     Some(input.lines().map(|s| enter_sequence(s, 2)).sum())
  109. }
  110.  
  111. pub fn part_two(input: &str) -> Option<usize> {
  112.     memoized_flush_do_arrows();
  113.     Some(input.lines().map(|s| enter_sequence(s, 25)).sum())
  114. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement