Guest User

Untitled

a guest
Jan 3rd, 2025
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.40 KB | None | 0 0
  1. enum ReindeerDirection { NORTH, SOUTH, EAST, WEST }
  2.  
  3. class MazeState {
  4.     private int points;
  5.     private final Point location;
  6.     private final ReindeerDirection direction;
  7.  
  8.     public MazeState() { this.location = new Point(); this.direction = ReindeerDirection.EAST; this.points = 0; }
  9.     public MazeState(Point location, ReindeerDirection direction, int points) {
  10.         this.location = location;
  11.         this.direction = direction;
  12.         this.points = points;
  13.     }
  14.  
  15.     public Point getLocation() { return location; }
  16.     public ReindeerDirection getDirection() { return direction; }
  17.     public int getPoints() { return points; }
  18.     public void setPoints(int points) { this.points = points; }
  19.     public String toString() { return this.location.toString(); }
  20.  
  21.     @Override
  22.     public boolean equals(Object o) {
  23.         if (this == o) return true;
  24.         if (o == null || getClass() != o.getClass()) return false;
  25.         MazeState mazeState = (MazeState) o;
  26.         return Objects.equals(location, mazeState.location) && direction == mazeState.direction;
  27.     }
  28.  
  29.     @Override
  30.     public int hashCode() {
  31.         return Objects.hash(location, direction);
  32.     }
  33. }
  34.  
  35. class MazePointComparator implements Comparator<MazeState> {
  36.     @Override
  37.     public int compare(MazeState x, MazeState y) {
  38.         return Integer.compare(x.getPoints(), y.getPoints());
  39.     }
  40. }
  41.  
  42. // Fairly confident the bug is not in here as this is the same neighbor-finding function I used in part 1.
  43. private static List<MazeState> getNeighbors(char[][] grid, MazeState node) {
  44.     List<MazeState> neighbors = new ArrayList<>();
  45.  
  46.     Point p = node.getLocation();
  47.     ReindeerDirection direction = node.getDirection();
  48.     int points = node.getPoints();
  49.  
  50.     if (direction == ReindeerDirection.NORTH) {
  51.         if (grid[p.x-1][p.y] == '.') {
  52.             neighbors.add(new MazeState(new Point(p.x-1, p.y), direction, points + 1));
  53.         }
  54.         if (grid[p.x][p.y-1] == '.') {
  55.             neighbors.add(new MazeState(p, ReindeerDirection.WEST, points + 1000));
  56.         }
  57.         if (grid[p.x][p.y+1] == '.') {
  58.             neighbors.add(new MazeState(p, ReindeerDirection.EAST, points + 1000));
  59.         }
  60.     } else if (direction == ReindeerDirection.EAST) {
  61.         if (grid[p.x][p.y+1] == '.') {
  62.             neighbors.add(new MazeState(new Point(p.x, p.y+1), direction, points + 1));
  63.         }
  64.         if (grid[p.x-1][p.y] == '.') {
  65.             neighbors.add(new MazeState(p, ReindeerDirection.NORTH, points + 1000));
  66.         }
  67.         if (grid[p.x+1][p.y] == '.') {
  68.             neighbors.add(new MazeState(p, ReindeerDirection.SOUTH, points + 1000));
  69.         }
  70.     } else if (direction == ReindeerDirection.SOUTH) {
  71.         if (grid[p.x+1][p.y] == '.') {
  72.             neighbors.add(new MazeState(new Point(p.x+1, p.y), direction, points + 1));
  73.         }
  74.         if (grid[p.x][p.y-1] == '.') {
  75.             neighbors.add(new MazeState(new Point(p.x, p.y), ReindeerDirection.WEST, points + 1000));
  76.         }
  77.         if (grid[p.x][p.y+1] == '.') {
  78.             neighbors.add(new MazeState(new Point(p.x, p.y), ReindeerDirection.EAST, points + 1000));
  79.         }
  80.     } else if (direction == ReindeerDirection.WEST) {
  81.         if (grid[p.x][p.y-1] == '.') {
  82.             neighbors.add(new MazeState(new Point(p.x, p.y-1), direction, points + 1));
  83.         }
  84.         if (grid[p.x-1][p.y] == '.') {
  85.             neighbors.add(new MazeState(new Point(p.x, p.y), ReindeerDirection.NORTH, points + 1000));
  86.         }
  87.         if (grid[p.x+1][p.y] == '.') {
  88.             neighbors.add(new MazeState(new Point(p.x, p.y), ReindeerDirection.SOUTH, points + 1000));
  89.         }
  90.     }
  91.  
  92.     return neighbors;
  93. }
  94.  
  95.  
  96. private static int part2(char[][] grid, Point start, Point end) {
  97.     Map<MazeState, Integer> costs = new HashMap<>(); // maps the best known costs to reach a given maze state so far
  98.     Set<MazeState> visited = new HashSet<>();
  99.     PriorityQueue<MazeState> pq = new PriorityQueue<>(new MazePointComparator());
  100.     // for each maze state key, tracks a list of parent maze states that could get us to that maze state.
  101.     Map<MazeState, List<MazeState>> parents = new HashMap<>();
  102.  
  103.     MazeState initial = new MazeState(start, ReindeerDirection.EAST, 0);
  104.     pq.add(initial);
  105.     costs.put(initial, 0);
  106.  
  107.     while (!pq.isEmpty()) {
  108.         MazeState node = pq.poll();
  109.         Point p = node.getLocation();
  110.  
  111.         if (visited.contains(node)) continue;
  112.  
  113.         visited.add(node);
  114.  
  115.         List<MazeState> neighbors = getNeighbors(grid, node);
  116.  
  117.         // For each neighbor, if the distance of the source node to the current node (dist[current]) plus
  118.         // the cost to get from current node to the neighbor (weight[current, neighbor])
  119.         // is less than the best recorded cost of the source node to the neighbor (dist[neighbor]) already,
  120.         // we update the cost to the neighbor to the new cost value.
  121.         // In other words, we update if: dist[current] + cost[current, neighbor] < dist[neighbor]
  122.         for (MazeState neighbor : neighbors) {
  123.             if (!visited.contains(neighbor)) {
  124.                 // Check if our costs map contains these maze states. If not, initialize their costs to infinity.
  125.                 if (!costs.containsKey(node)) {
  126.                     costs.put(node, Integer.MAX_VALUE);
  127.                 }
  128.                 if (!costs.containsKey(neighbor)) {
  129.                     costs.put(neighbor, Integer.MAX_VALUE);
  130.                 }
  131.  
  132.                 int newCost = costs.get(node) + neighbor.getPoints();
  133.  
  134.                 // If we've found a better cost, update it.
  135.                 if (newCost <= costs.get(neighbor)) {
  136.                     costs.put(neighbor, newCost);
  137.                     pq.add(neighbor);
  138.  
  139.                     // And keep track of where we've come from
  140.                     if (parents.containsKey(neighbor)) {
  141.                         parents.get(neighbor).add(node);
  142.                     } else {
  143.                         List<MazeState> parentsOfNeighbor = new ArrayList<>();
  144.                         parentsOfNeighbor.add(node);
  145.                         parents.put(neighbor, parentsOfNeighbor);
  146.                     }
  147.                 }
  148.             }
  149.         }
  150.     }
  151.  
  152.     Set<Point> uniquePoints = new HashSet<>();
  153.  
  154.     // Find the min points.
  155.     int min = Integer.MAX_VALUE;
  156.     for (MazeState state : parents.keySet()) {
  157.         if (state.getLocation().equals(end)) {
  158.             min = Math.min(min, state.getPoints());
  159.         }
  160.     }
  161.  
  162.     // Find each end state that results in the minimum points in reaching it.
  163.     List<MazeState> endStates = new ArrayList<>();
  164.     for (MazeState state : parents.keySet()) {
  165.         if (state.getLocation().equals(end) && state.getPoints() == min) {
  166.             endStates.add(state);
  167.         }
  168.     }
  169.    
  170.     for (MazeState endState: endStates) {
  171.         Stack<MazeState> stack = new Stack<>();
  172.         stack.add(endState);
  173.  
  174.         // Work backwards from the end state, visiting the parent/previous states that got us to that state
  175.         // and add their points to a set.
  176.         while (!stack.isEmpty()) {
  177.             MazeState curr = stack.pop();
  178.             uniquePoints.add(curr.getLocation());
  179.  
  180.             if (parents.containsKey(curr)) {
  181.                 for (MazeState ms : parents.get(curr)) {
  182.                     stack.push(ms);
  183.                 }
  184.             }
  185.         }
  186.     }
  187.  
  188.     return uniquePoints.size();
  189. }
Advertisement
Add Comment
Please, Sign In to add comment