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 }