aoc2024

Advent of Code 2024
Log | Files | Refs | README

day12_pt1.java (2678B)


      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_pt1 {
      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   public static void main(String[] args) throws IOException {
     21     var grid = Files.readAllLines(Path.of(args[0]));
     22     // iterate the grid. Recursively find regions and their perimeters.
     23     var pts = new HashSet<Point>();
     24     var nRegions = 0;
     25     var regions = new HashMap<Integer, HashSet<Point>>();
     26     int height = grid.size();
     27     int width = grid.get(0).length();
     28     for (int y=0; y<height; y++) {
     29       for (int x=0; x<width; x++) {
     30         var pt = new Point(x, y);
     31         if (pts.contains(pt)) continue;
     32         var region = expandRegion(grid, pt);
     33         regions.put(nRegions++, region);
     34         pts.addAll(region);
     35       }
     36     }
     37     
     38     var res = regions.entrySet().stream().mapToLong(e -> {
     39       var region = e.getValue();
     40       var perim = perimeter(grid, region);
     41       //System.out.printf("Region %d: size: %d perimeter: %d\n", e.getKey(), e.getValue().size(), perim);
     42       return perim * region.size();
     43     })
     44     .sum();
     45     System.out.printf("Day 12, pt1: %d\n", res);
     46   }
     47   static long perimeter(List<String> grid, HashSet<Point> region) {
     48     var val = gv(grid, region.stream().findFirst().get());
     49     return region.stream().mapToLong(p -> {
     50       return Arrays.stream(DIRS).map(d -> p.add(d))
     51         .filter(pp -> gv(grid, pp) != val)
     52         .count();
     53     }).sum();
     54   //   return region.stream().mapToInt(p -> {
     55   //     var val = gv(grid, p);
     56   //     return Arrays.stream(DIRS)
     57   //       .map(d -> p.add(d))
     58   //       .filter(pp -> gv(grid, pp) != val)
     59   //       .count();
     60   //   });
     61   }
     62   static HashSet<Point> expandRegion(List<String> grid, Point p) {
     63     var res = new HashSet<Point>();
     64     expandRegionInternal(grid, p, gv(grid, p), res);
     65     return res;
     66   }
     67   static void expandRegionInternal(List<String> grid, Point p, int val, HashSet<Point> region) {
     68     if (region.contains(p)) return;
     69     region.add(p);
     70     Arrays.stream(DIRS).forEach(d -> {
     71       var pp = p.add(d);
     72       if (gv(grid, pp) == val) {
     73         expandRegionInternal(grid, pp, val, region);
     74       }
     75     });
     76   }
     77   static int gv(List<String> grid, Point p) {
     78     var height = grid.size();
     79     if (p.y < 0 || p.y >= height) return -1;
     80     var width = grid.get(0).length();
     81     if (p.x < 0 || p.x >= width) return -1;
     82     return grid.get(p.y).charAt(p.x);
     83   }
     84 }