aoc2024

Advent of Code 2024
Log | Files | Refs | README

day12_pt2.java (3655B)


      1 import java.nio.file.Files;
      2 import java.nio.file.Path;
      3 import java.io.IOException;
      4 import java.util.*;
      5 import java.util.stream.*;
      6 
      7 class day12_pt2 {
      8   record Point(int x, int y) {
      9     Point add(Vec v) {
     10       return new Point(this.x + v.x, this.y + v.y);
     11     }
     12   }
     13   record Vec(int x, int y) {}
     14   static Vec[] DIRS = new Vec[]{
     15     new Vec(0, 1),
     16     new Vec(1, 0),
     17     new Vec(0, -1),
     18     new Vec(-1, 0)
     19   };
     20   static Vec[][] DIRPAIRS = new Vec[][]{
     21     new Vec[]{new Vec(0, 1),  new Vec(1, 0)},
     22     new Vec[]{new Vec(1, 0),  new Vec(0, -1)},
     23     new Vec[]{new Vec(0, -1), new Vec(-1, 0)},
     24     new Vec[]{new Vec(-1, 0), new Vec(0, 1)},
     25   };
     26   public static void main(String[] args) throws IOException {
     27     var grid = Files.readAllLines(Path.of(args[0]));
     28     // iterate the grid. Recursively find regions and their perimeters.
     29     var pts = new HashSet<Point>();
     30     var nRegions = 0;
     31     var regions = new HashMap<Integer, HashSet<Point>>();
     32     int height = grid.size();
     33     int width = grid.get(0).length();
     34     for (int y=0; y<height; y++) {
     35       for (int x=0; x<width; x++) {
     36         var pt = new Point(x, y);
     37         if (pts.contains(pt)) continue;
     38         var region = expandRegion(grid, pt);
     39         regions.put(nRegions++, region);
     40         pts.addAll(region);
     41       }
     42     }
     43     
     44     var res = regions.entrySet().stream().mapToLong(e -> {
     45       var region = e.getValue();
     46       var ss = sides(grid, region);
     47       System.out.printf("Region %d: size: %d sides: %d\n", e.getKey(), e.getValue().size(), ss);
     48       return ss * region.size();
     49     })
     50     .sum();
     51     System.out.printf("Day 12, pt1: %d\n", res);
     52   }
     53 
     54   static long sides(List<String> grid, HashSet<Point> region) {
     55     return region.stream()
     56       .mapToLong(p -> {
     57         var v = gv(grid, p);
     58         // consider pairs of cardinal directions, e.g. N+E. Look at the squares in these directions
     59         // if both are not the same as us; then that's definitely a corner. +1;
     60         // if one's the same and one's not, we're not a corner
     61         // if both are the smae as us, look at the diagnoal. 
     62         //   if it's the same, not a corner
     63         //   if it's different, we're an inside corner.
     64 
     65         // Oo = 0 corner  Ox = 1 corner  Ox = 1 corner  Ox = 1 corner Oo = 0 corner
     66         // oo             oo             xo             xx            xx
     67         return Arrays.stream(DIRPAIRS).mapToLong(dp -> {
     68           var p1 = p.add(dp[0]);
     69           var p2 = p.add(dp[1]);
     70           var v1_m = gv(grid, p1) == v; 
     71           var v2_m = gv(grid, p2) == v;
     72           if (!v1_m && !v2_m) {
     73             return 1l;
     74           } else if (v1_m && v2_m){
     75             var p3 = p2.add(dp[0]);
     76             var v3_m = gv(grid, p3) == v;
     77             if (v3_m) {
     78               return 0l;
     79             } else {
     80               return 1l;
     81             }
     82           } else {
     83             return 0l;
     84           }
     85         }).sum();
     86       })
     87       .sum();
     88   }
     89   static HashSet<Point> expandRegion(List<String> grid, Point p) {
     90     var res = new HashSet<Point>();
     91     expandRegionInternal(grid, p, gv(grid, p), res);
     92     return res;
     93   }
     94   static void expandRegionInternal(List<String> grid, Point p, int val, HashSet<Point> region) {
     95     if (region.contains(p)) return;
     96     region.add(p);
     97     Arrays.stream(DIRS).forEach(d -> {
     98       var pp = p.add(d);
     99       if (gv(grid, pp) == val) {
    100         expandRegionInternal(grid, pp, val, region);
    101       }
    102     });
    103   }
    104   static int gv(List<String> grid, Point p) {
    105     var height = grid.size();
    106     if (p.y < 0 || p.y >= height) return -1;
    107     var width = grid.get(0).length();
    108     if (p.x < 0 || p.x >= width) return -1;
    109     return grid.get(p.y).charAt(p.x);
    110   }
    111 }