7
7
import java .util .List ;
8
8
import java .util .Map ;
9
9
import java .util .Set ;
10
- import java .util .function .ToIntBiFunction ;
11
10
12
11
import com .github .pareronia .aoc .Grid .Cell ;
13
- import com .github .pareronia .aoc .Utils ;
12
+ import com .github .pareronia .aoc .IterTools . IterToolsIterator ;
14
13
import com .github .pareronia .aoc .geometry .Direction ;
15
14
import com .github .pareronia .aoc .graph .BFS ;
16
15
import com .github .pareronia .aoc .solution .Sample ;
17
16
import com .github .pareronia .aoc .solution .Samples ;
18
17
import com .github .pareronia .aoc .solution .SolutionBase ;
19
18
20
19
public final class AoC2024_12 extends SolutionBase <List <String >, Integer , Integer > {
21
-
22
- private static final List <List <Direction >> CORNER_DIRS = List .of (
23
- List .of (Direction .LEFT_AND_UP , Direction .LEFT , Direction .UP ),
24
- List .of (Direction .RIGHT_AND_UP , Direction .RIGHT , Direction .UP ),
25
- List .of (Direction .RIGHT_AND_DOWN , Direction .RIGHT , Direction .DOWN ),
26
- List .of (Direction .LEFT_AND_DOWN , Direction .LEFT , Direction .DOWN )
27
- );
28
20
29
21
private AoC2024_12 (final boolean debug ) {
30
22
super (debug );
@@ -43,17 +35,14 @@ protected List<String> parseInput(final List<String> inputs) {
43
35
return inputs ;
44
36
}
45
37
46
- private int solve (
47
- final List <String > input ,
48
- final ToIntBiFunction <Cell , Set <Cell >> count
49
- ) {
38
+ private int solve (final List <String > input , final Pricing pricing ) {
50
39
final Map <Character , Set <Cell >> plotsByPlant = new HashMap <>();
51
40
range (input .size ()).forEach (r ->
52
41
range (input .get (r ).length ()).forEach (c ->
53
42
plotsByPlant
54
43
.computeIfAbsent (input .get (r ).charAt (c ), k -> new HashSet <>())
55
44
.add (Cell .at (r , c ))));
56
- final Iterator <Set <Cell >> regions = new Iterator <>() {
45
+ final IterToolsIterator <Set <Cell >> regions = new IterToolsIterator <>() {
57
46
final Iterator <Character > keys = plotsByPlant .keySet ().iterator ();
58
47
char key = keys .next ();
59
48
Set <Cell > allPlotsWithPlant = plotsByPlant .get (key );
@@ -77,36 +66,51 @@ public boolean hasNext() {
77
66
return !allPlotsWithPlant .isEmpty () || keys .hasNext ();
78
67
}
79
68
};
80
- return Utils .stream (regions )
69
+ return regions .stream ()
81
70
.mapToInt (region -> region .stream ()
82
- .mapToInt (plot -> count . applyAsInt (plot , region ) * region . size ( ))
83
- .sum ())
71
+ .mapToInt (plot -> pricing . calculate (plot , region ))
72
+ .sum () * region . size () )
84
73
.sum ();
85
74
}
86
75
87
76
@ Override
88
77
public Integer solvePart1 (final List <String > input ) {
89
- final ToIntBiFunction <Cell , Set <Cell >> countEdges
90
- = (plot , region ) -> (4 - (int ) plot .capitalNeighbours ()
91
- .filter (region ::contains )
92
- .count ());
93
- return solve (input , countEdges );
78
+ return solve (input , Pricing .PERIMETER );
94
79
}
95
80
96
81
@ Override
97
82
public Integer solvePart2 (final List <String > input ) {
98
- final Set <int []> matches = Set .of (
83
+ return solve (input , Pricing .NUMBER_OF_SIDES );
84
+ }
85
+
86
+ private enum Pricing {
87
+ PERIMETER , NUMBER_OF_SIDES ;
88
+
89
+ private static final List <List <Direction >> CORNER_DIRS = List .of (
90
+ List .of (Direction .LEFT_AND_UP , Direction .LEFT , Direction .UP ),
91
+ List .of (Direction .RIGHT_AND_UP , Direction .RIGHT , Direction .UP ),
92
+ List .of (Direction .RIGHT_AND_DOWN , Direction .RIGHT , Direction .DOWN ),
93
+ List .of (Direction .LEFT_AND_DOWN , Direction .LEFT , Direction .DOWN )
94
+ );
95
+ private static final Set <int []> MATCHES = Set .of (
99
96
new int [] {0 , 0 , 0 }, new int [] {1 , 0 , 0 }, new int [] {0 , 1 , 1 });
100
- final ToIntBiFunction <Cell , Set <Cell >> countCorners
101
- = (plot , region ) -> ((int ) CORNER_DIRS .stream ()
97
+
98
+ public int calculate (final Cell plot , final Set <Cell > region ) {
99
+ return switch (this ) {
100
+ case PERIMETER -> 4 - (int ) plot .capitalNeighbours ()
101
+ .filter (region ::contains )
102
+ .count ();
103
+ case NUMBER_OF_SIDES -> (int ) CORNER_DIRS .stream ()
102
104
.filter (d -> {
103
105
final int [] test = range (3 ).intStream ()
104
106
.map (i -> region .contains (plot .at (d .get (i ))) ? 1 : 0 )
105
107
.toArray ();
106
- return matches .stream ().anyMatch (m -> Arrays .equals (m , test ));
108
+ return MATCHES .stream ()
109
+ .anyMatch (m -> Arrays .equals (m , test ));
107
110
})
108
- .count ());
109
- return solve (input , countCorners );
111
+ .count ();
112
+ };
113
+ }
110
114
}
111
115
112
116
@ Override
0 commit comments