Advertisement
Guest User

Untitled

a guest
Jan 15th, 2025
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.76 KB | None | 0 0
  1. // Return the Manhattan distance between two points.
  2. private static int getDistance(Point a, Point b) {
  3.     return Math.abs(a.x-b.x) + Math.abs(a.y-b.y);
  4. }
  5.  
  6. // Given a source and destination point, return one of '<', 'v', '^', or '>' characters to indicate
  7. // the direction needed to travel to get from the source to destination point.
  8. private static Character getDirection(Point source, Point dest) {
  9.     if (source.x != dest.x) {
  10.         if (source.x > dest.x) return '^';
  11.         return 'v';
  12.     } else if (source.y != dest.y) {
  13.         if (source.y > dest.y) return '<';
  14.         return '>';
  15.     }
  16.  
  17.     return '\0';
  18. }
  19.  
  20. // Given a list of sequences, return a list only containing the sequences with the shortest length.
  21. private static List<String> shortestSequences(List<String> cumulativeSequences) {
  22.     List<String> shortestSequences = new ArrayList<>();
  23.  
  24.     int min = Integer.MAX_VALUE;
  25.  
  26.     for (String s : cumulativeSequences) {
  27.         min = Math.min(s.length(), min);
  28.     }
  29.  
  30.     for (String s : cumulativeSequences) {
  31.         if (s.length() == min)
  32.             shortestSequences.add(s);
  33.     }
  34.  
  35.     return shortestSequences;
  36. }
  37.  
  38. // This is a general solver that takes:
  39. // - a given sequence to type
  40. // - a map between a point on a keypad grid and its neighbors
  41. // - a map between a character on a keypad grid and its point
  42. // and generates all possible sequences of directions and button presses it would take to achieve that.
  43. private static List<String> getAllValidButtonPresses(String sequence,
  44.                                                         Map<Point, List<Point>> keypadNeighbors,
  45.                                                         Map<Character, Point> keypadPositions) {
  46.     List<String> cumulativeSequences = new ArrayList<>();
  47.  
  48.     Point source = keypadPositions.get('A');
  49.  
  50.     // For each character in the sequence
  51.     for (int i = 0; i < sequence.length(); i++) {
  52.         // Stores each intermediate sequence
  53.         List<String> sequencesFromSourceToDest = new ArrayList<>();
  54.  
  55.         Point destination = keypadPositions.get(sequence.charAt(i)); // Find where am I trying to go
  56.         int distance = getDistance(source, destination); // The length of the optimal sequence
  57.  
  58.         Queue<KeypadState> queue = new LinkedList<>();
  59.         Set<Point> visited = new HashSet<>();
  60.         queue.add(new KeypadState(source, ""));
  61.  
  62.         // We run a BFS through the grid where each state is a point on the grid and the sequence of button presses
  63.         // it would take to get there.
  64.         while (!queue.isEmpty()) {
  65.             KeypadState keypadState = queue.poll();
  66.             Point currPoint = keypadState.point();
  67.  
  68.             // If we've found our destination, add that as a possible sequence and keep searching.
  69.             // (not forgetting to actually push the button too)
  70.             if (currPoint.equals(destination)) {
  71.                 sequencesFromSourceToDest.add(keypadState.sequence() + 'A');
  72.                 continue;
  73.             }
  74.  
  75.             visited.add(currPoint);
  76.  
  77.             List<Point> neighbors = keypadNeighbors.get(currPoint);
  78.  
  79.             for (Point neighbor : neighbors) {
  80.                 if (!visited.contains(neighbor)) {
  81.                     // The new sequence is how we got here so far plus the direction it takes to get to this neighbor.
  82.                     String updatedSequence = keypadState.sequence() + getDirection(currPoint, neighbor);
  83.  
  84.                     // We don't want to consider sequences longer than necessary
  85.                     if (updatedSequence.length() <= distance) {
  86.                         queue.add(new KeypadState(neighbor, updatedSequence));
  87.                     }
  88.                 }
  89.             }
  90.         }
  91.  
  92.         // At this point, the BFS has finished so we want to accumulate our intermediate sequences
  93.         // into a cumulative sequence.
  94.         List<String> newCumulativeSequences = new ArrayList<>();
  95.         if (cumulativeSequences.isEmpty()) {
  96.             // For the first character, we've just found the starting sequences.
  97.             cumulativeSequences.addAll(sequencesFromSourceToDest);
  98.         } else {
  99.             // For getting to subsequent characters, we need to append the
  100.             // intermediate sequence found with each sequence generated so far.
  101.             for (String sequenceSoFar : cumulativeSequences) {
  102.                 for (String intermediate : sequencesFromSourceToDest) {
  103.                     String combined = sequenceSoFar + intermediate;
  104.                     newCumulativeSequences.add(combined);
  105.                 }
  106.             }
  107.             cumulativeSequences = newCumulativeSequences;
  108.         }
  109.  
  110.         // Don't forget to update our new starting point
  111.         source = destination;
  112.     }
  113.  
  114.     // Only keep the sequences that are the shortest.
  115.     return shortestSequences(cumulativeSequences);
  116. }
  117.  
  118. // Part 1: Iterate through each door pad code and work backwards, finding all the sequences it would take
  119. // the first robot to type on the number pad and from that, all the sequences it would take the second robot
  120. // to type on the directional pad, and so on. Filter down to only the shortest sequences
  121. // and return the complexity sum.
  122. private static int part1() {
  123.     int sum = 0;
  124.  
  125.     // Iterate through each code.
  126.     for (String code : codes) {
  127.         // Get all the possible sequences for the first robot to type on the number pad.
  128.         List<String> firstLevelAbstraction = getAllValidButtonPresses(code, numpadMap, numpadPositions);
  129.  
  130.         List<String> secondLevelAbstraction = new ArrayList<>();
  131.  
  132.         // For each possible sequence that the first robot generated, get all the possible sequences
  133.         // for the second robot to type on the directional pad.
  134.         for (String first : firstLevelAbstraction) {
  135.             secondLevelAbstraction.addAll(getAllValidButtonPresses(first, dirpadMap, dirpadPositions));
  136.         }
  137.  
  138.         // Only keep the shortest sequences.
  139.         secondLevelAbstraction = shortestSequences(secondLevelAbstraction);
  140.  
  141.         List<String> thirdLevelAbstraction = new ArrayList<>();
  142.  
  143.         // For each possible sequence that the second robot generated, get all the possible sequences
  144.         // for the third robot to type on the directional pad.
  145.         for (String second : secondLevelAbstraction) {
  146.             thirdLevelAbstraction.addAll(getAllValidButtonPresses(second, dirpadMap, dirpadPositions));
  147.         }
  148.  
  149.         // Only keep the shortest sequences.
  150.         thirdLevelAbstraction = shortestSequences(thirdLevelAbstraction);
  151.  
  152.         // Calculate complexity
  153.         int numeric = Integer.parseInt(code.substring(0, code.length()-1));
  154.         int shortestLength = thirdLevelAbstraction.get(0).length();
  155.  
  156.         sum += numeric * shortestLength;
  157.     }
  158.  
  159.     return sum;
  160. }
  161.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement