-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathDay12.java
80 lines (68 loc) · 2.75 KB
/
Day12.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package com.sbaars.adventofcode.year24.days;
import com.sbaars.adventofcode.common.Direction;
import com.sbaars.adventofcode.common.grid.InfiniteGrid;
import com.sbaars.adventofcode.common.location.Loc;
import com.sbaars.adventofcode.year24.Day2024;
import org.apache.commons.lang3.function.TriFunction;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Stream;
import static java.util.stream.Stream.concat;
import static com.sbaars.adventofcode.util.AoCUtils.al;
import static com.sbaars.adventofcode.util.AoCUtils.appendWhile;
public class Day12 extends Day2024 {
public Day12() {
super(12);
}
public static void main(String[] args) {
new Day12().printParts();
}
@Override
public Object part1() {
return solve((grid, edge, direction) -> Stream.of());
}
@Override
public Object part2() {
return solve((grid, edge, direction) -> concat(explorePerimeter(grid, edge.a(), direction, grid.getChar(edge.a()), true), explorePerimeter(grid, edge.a(), direction, grid.getChar(edge.a()), false)));
}
record Edge(Loc a, Loc b) {}
public long solve(TriFunction<InfiniteGrid, Edge, Direction, Stream<Edge>> lambda) {
Set<Loc> visited = new HashSet<>();
var stack = new LinkedList<Loc>();
var grid = new InfiniteGrid(dayGrid());
return grid.stream().filter(loc -> !visited.contains(loc)).mapToLong(loc -> {
Set<Edge> visitedEdges = new HashSet<>();
stack.clear();
stack.push(loc);
AtomicLong area = al(), perimeter = al();
while (!stack.isEmpty()) {
Loc current = stack.pop();
if (visited.add(current)) {
area.incrementAndGet();
grid.walkAround(current).forEach((next, direction) -> {
if (grid.getChar(next) == grid.getChar(loc)) {
stack.push(next);
} else {
var edge = new Edge(current, next);
if (visitedEdges.add(edge)) {
perimeter.incrementAndGet();
lambda.apply(grid, edge, direction).forEach(visitedEdges::add);
}
}
});
}
}
return area.get() * perimeter.get();
}).sum();
}
private Stream<Edge> explorePerimeter(InfiniteGrid grid, Loc current, Direction direction, char charValue, boolean turnRight) {
Direction newDirection = direction.turn(turnRight);
return appendWhile(
edge -> new Edge(edge.a().move(newDirection), edge.a().move(newDirection).move(direction)),
edge -> grid.contains(edge.a()) && grid.getChar(edge.a()) == charValue && (!grid.contains(edge.b()) || grid.getChar(edge.b()) != charValue),
new Edge(current.move(newDirection), current.move(newDirection).move(direction))
);
}
}