Advertisement
Guest User

Untitled

a guest
Dec 20th, 2024
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.50 KB | None | 0 0
  1. import java.io.BufferedReader;
  2. import java.io.FileReader;
  3. import java.util.*;
  4.  
  5. public class Code20B {
  6.     public static void main(String[] args) {
  7.         List<String> file;
  8.         try (
  9.             BufferedReader in = new BufferedReader(new FileReader(args[0]))
  10.         ) {
  11.             file = in.lines().collect(Collectors.toList());
  12.         } catch (Exception e) {
  13.             return;
  14.         }
  15.  
  16.         LPAGrid grid = new LPAGrid(file);
  17.  
  18.         int count = 0;
  19.         int LIMIT = 100;
  20.         int RADIUS = 50;
  21.         List<Point> offsets = new ArrayList<>();
  22.         for (int r = -RADIUS; r <= RADIUS; r++) {
  23.             for (int c = Math.abs(r) - RADIUS; c <= RADIUS - Math.abs(r); c++) {
  24.                 if (r != 0 || c != 0) {
  25.                     offsets.add(new Point(r, c));
  26.                 }
  27.             }
  28.         }
  29.  
  30.         for (int r = 1; r < grid.rows - 1; r++) {
  31.             for (int c = 1; c < grid.columns - 1; c++) {
  32.                 Point p1 = new Point(r, c);
  33.                 if (!grid.isWall(p1)) {
  34.                     for (Point offset : offsets) {
  35.                         Point p2 = p1.add(offset);
  36.                         int savings = grid.getDist(p2) - grid.getDist(p1) - Math.abs(offset.r) - Math.abs(offset.c);
  37.                         if (!grid.isWall(p2) && savings >= LIMIT) {
  38.                             System.out.printf("Found cheat! (%d, %d) -> (%d, %d), with length %d\n", p1.r, p1.c, p2.r, p2.c, savings);
  39.                             count++;
  40.                         }
  41.                     }
  42.                 }
  43.             }
  44.         }
  45.  
  46.         System.out.println(count);
  47.     }
  48. }
  49.  
  50. public class LPAGrid {
  51.     private int[][] walls;
  52.     private int[][] dist;
  53.     private int[][] exp;
  54.     private final int INFINITY;
  55.     private LPAQueue queue = new LPAQueue();
  56.     private final Point[] DIRECTIONS = {Point.UP, Point.DOWN, Point.LEFT, Point.RIGHT};
  57.  
  58.     public Point start = new Point(0,0);
  59.     public Point end = null;
  60.     public final int rows;
  61.     public final int columns;
  62.  
  63.     private class LPAQueue extends PriorityQueue<Point> {
  64.         public LPAQueue() {
  65.             super((a,b) -> LPAGrid.this.getScore(a) - LPAGrid.this.getScore(b));
  66.         }
  67.  
  68.         public boolean hasNext() {
  69.             if (this.isEmpty()) {
  70.                 return false;
  71.             }
  72.  
  73.             return !LPAGrid.this.isConsistent(LPAGrid.this.end) ||
  74.                    LPAGrid.this.getScore(LPAGrid.this.end) >= LPAGrid.this.getScore(this.peek());
  75.         }
  76.     }
  77.  
  78.     public LPAGrid(int rows, int columns) {
  79.         this.rows = rows;
  80.         this.columns = columns;
  81.         this.walls = new int[rows][columns];
  82.         this.dist = new int[rows][columns];
  83.         this.exp = new int[rows][columns];
  84.         this.end = new Point(rows - 1, columns - 1);
  85.         this.INFINITY = 2 * rows * columns;
  86.  
  87.         for (int r = 0; r < this.rows; r++) {
  88.             for (int c = 0; c < this.columns; c++) {
  89.                 this.dist[r][c] = this.exp[r][c] = r+c;
  90.             }
  91.         }
  92.     }
  93.  
  94.     public LPAGrid(List<String> file) {
  95.         this.rows = file.size();
  96.         this.columns = file.get(0).length();
  97.         this.walls = new int[rows][columns];
  98.         this.dist = new int[rows][columns];
  99.         this.exp = new int[rows][columns];
  100.         this.INFINITY = 2 * rows * columns;
  101.  
  102.         for (int r = 0; r < this.rows; r++) {
  103.             for (int c = 0; c < this.columns; c++) {
  104.                 switch (file.get(r).charAt(c)) {
  105.                 case 'S':
  106.                     this.walls[r][c] = 0;
  107.                     this.exp[r][c] = 0;
  108.                     this.dist[r][c] = this.INFINITY;
  109.                     this.start = new Point(r, c);
  110.                     break;
  111.                 case 'E':
  112.                     this.end = new Point(r, c);
  113.                     // Fall through, because apart from setting this.end, it's otherwise a normal free space
  114.                 case '.':
  115.                     this.walls[r][c] = 0;
  116.                     this.exp[r][c] = this.INFINITY;
  117.                     this.dist[r][c] = this.INFINITY;
  118.                     break;
  119.                 case '#':
  120.                     this.walls[r][c] = 1;
  121.                     break;
  122.                 }
  123.             }
  124.         }
  125.  
  126.         this.queue.add(start);
  127.         this.update();
  128.     }
  129.  
  130.     private void update() {
  131.         while (this.queue.hasNext()) {
  132.             Point curr = this.queue.poll();
  133.  
  134.             if (this.getDist(curr) > this.getExp(curr)) {
  135.                 this.setDist(curr, this.getExp(curr));
  136.             } else if (this.getDist(curr) < this.getExp(curr)) {
  137.                 this.setDist(curr, this.INFINITY);
  138.                 if (!this.isConsistent(curr)) {
  139.                     this.queue.remove(curr);
  140.                     this.queue.add(curr);
  141.                 }
  142.             }
  143.         }
  144.     }
  145.  
  146.     public void inspect() {
  147.         for (int r = 0; r < this.rows; r++) {
  148.             for (int c = 0; c < this.columns; c++) {
  149.                 if (this.isWall(new Point(r,c))) {
  150.                     System.out.print("   ");
  151.                 } else {
  152.                     System.out.printf("%2d ", this.dist[r][c]);
  153.                 }
  154.             }
  155.             System.out.println();
  156.         }
  157.     }
  158.  
  159.     private boolean isInBounds(Point p) {
  160.         return p.r >= 0 && p.r < this.rows && p.c >= 0 && p.c < this.columns;
  161.     }
  162.  
  163.     public boolean isWall(Point p) {
  164.         return !this.isInBounds(p) || this.walls[p.r][p.c] == 1;
  165.     }
  166.  
  167.     public int getDist(Point p) {
  168.         if (!this.isInBounds(p) || this.isWall(p)) {
  169.             return this.INFINITY;
  170.         }
  171.  
  172.         return this.dist[p.r][p.c];
  173.     }
  174.  
  175.     private int getExp(Point p) {
  176.         if (!this.isInBounds(p) || this.isWall(p)) {
  177.             return this.INFINITY;
  178.         }
  179.  
  180.         return this.exp[p.r][p.c];
  181.     }
  182.  
  183.     private int getScore(Point p) {
  184.         if (!this.isInBounds(p) || this.isWall(p)) {
  185.             return this.INFINITY;
  186.         }
  187.  
  188.         return Math.min(this.dist[p.r][p.c], this.exp[p.r][p.c]);
  189.     }
  190.  
  191.     private boolean isConsistent(Point p) {
  192.         if (!this.isInBounds(p) || this.isWall(p)) {
  193.             return true;
  194.         }
  195.  
  196.         return this.dist[p.r][p.c] == this.exp[p.r][p.c];
  197.     }
  198.  
  199.     private void setDist(Point p, int dist) {
  200.         if (!this.isInBounds(p) || this.isWall(p) || this.getDist(p) == dist) {
  201.             return;
  202.         }
  203.  
  204.         this.dist[p.r][p.c] = dist;
  205.         for (Point dir : this.DIRECTIONS) {
  206.             this.updateExp(p.add(dir));
  207.         }
  208.         this.queue.remove(p);
  209.         this.queue.add(p);
  210.     }
  211.  
  212.     private void updateExp(Point p) {
  213.         if (!this.isInBounds(p) || this.isWall(p) || p.equals(this.start)) {
  214.             return;
  215.         }
  216.  
  217.         int minDist = this.INFINITY;
  218.         for (Point dir : this.DIRECTIONS) {
  219.             int test = this.getDist(p.add(dir)) + 1;
  220.             if (test < minDist && !isWall(p.add(dir))) {
  221.                 minDist = test;
  222.             }
  223.         }
  224.  
  225.         if (this.exp[p.r][p.c] != minDist) {
  226.             this.exp[p.r][p.c] = minDist;
  227.             this.queue.remove(p);
  228.             this.queue.add(p);
  229.         }
  230.     }
  231.  
  232.     public boolean addWall(Point p) {
  233.         if (this.isInBounds(p) && !this.isWall(p)) {
  234.             this.walls[p.r][p.c] = 1;
  235.             for (Point dir : this.DIRECTIONS) {
  236.                 this.updateExp(p.add(dir));
  237.             }
  238.             this.queue.remove(p);
  239.             this.update();
  240.         }
  241.  
  242.         return this.getDist(this.end) < this.INFINITY;
  243.     }
  244. }
  245.  
  246. public class Point {
  247.     public static Point UP    = new Point(-1,0);
  248.     public static Point DOWN  = new Point(1,0);
  249.     public static Point LEFT  = new Point(0,-1);
  250.     public static Point RIGHT = new Point(0,1);
  251.  
  252.     public final int r, c;
  253.  
  254.     public Point(int r, int c) {
  255.         this.r = r;
  256.         this.c = c;
  257.     }
  258.  
  259.     public Point add(Point p) {
  260.         return new Point(p.r + this.r, p.c + this.c);
  261.     }
  262.  
  263.     public int dist(Point p) {
  264.         return Math.abs(this.r - p.r) + Math.abs(this.c - p.c);
  265.     }
  266.  
  267.     public Point ccw() {
  268.         return new Point(-this.c, this.r);
  269.     }
  270.  
  271.     public Point cw() {
  272.         return new Point(this.c, -this.r);
  273.     }
  274.  
  275.     public boolean equals(Object obj) {
  276.         if (obj instanceof Point) {
  277.             return ((Point) obj).r == this.r && ((Point) obj).c == this.c;
  278.         } else {
  279.             return false;
  280.         }
  281.     }
  282.  
  283.     public int hashCode() {
  284.         return Objects.hash(this.c, this.r);
  285.     }
  286. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement