1
+ package com .macasaet ;
2
+
3
+ import java .util .ArrayList ;
4
+ import java .util .List ;
5
+ import java .util .stream .Stream ;
6
+ import java .util .stream .StreamSupport ;
7
+
8
+ import org .junit .jupiter .api .Test ;
9
+
10
+ /**
11
+ * --- Day 11: Dumbo Octopus ---
12
+ */
13
+ public class Day11 {
14
+
15
+ protected Stream <String > getInput () {
16
+ return StreamSupport
17
+ .stream (new LineSpliterator ("day-11.txt" ),
18
+ false );
19
+ }
20
+
21
+ /**
22
+ * @return a spatial grid of the cavern indicating the location of the octopuses
23
+ */
24
+ protected Octopus [][] getOctopusGrid () {
25
+ final var list = getInput ().map (line -> {
26
+ final var chars = line .toCharArray ();
27
+ final byte [] result = new byte [chars .length ];
28
+ for (int i = chars .length ; --i >= 0 ; result [i ] = (byte ) (chars [i ] - '0' )) ;
29
+ return result ;
30
+ }).collect (ArrayList <byte []>::new , List ::add , List ::addAll );
31
+ final var result = new Octopus [list .size ()][];
32
+ for (int i = list .size (); --i >= 0 ; ) {
33
+ final var row = list .get (i );
34
+ result [i ] = new Octopus [row .length ];
35
+ for (int j = row .length ; --j >= 0 ; result [i ][j ] = new Octopus (i , j , row [j ])) ;
36
+ }
37
+ return result ;
38
+ }
39
+
40
+ /**
41
+ * A rare bioluminescent dumbo octopus
42
+ */
43
+ public static class Octopus {
44
+ private final int x , y ;
45
+ private byte energyLevel ;
46
+
47
+ public Octopus (final int x , final int y , final byte energyLevel ) {
48
+ this .x = x ;
49
+ this .y = y ;
50
+ this .energyLevel = energyLevel ;
51
+ }
52
+
53
+ /**
54
+ * Increase the octopus' energy level and, if appropriate, propagate side effects to its neighbours.
55
+ *
56
+ * @param population the full population of octopuses
57
+ */
58
+ public void prepareStep (final Population population ) {
59
+ if (this .energyLevel > 9 ) {
60
+ // "An octopus can only flash at most once per step."
61
+ return ;
62
+ }
63
+ // "First, the energy level of each octopus increases by 1."
64
+ this .energyLevel ++;
65
+ if (this .energyLevel > 9 ) {
66
+ // "Then, any octopus with an energy level greater than 9 flashes. This increases the energy level of
67
+ // all adjacent octopuses by 1, including octopuses that are diagonally adjacent."
68
+ final var grid = population .grid ();
69
+ final var hasRowAbove = x > 0 ;
70
+ final var hasRowBelow = x < grid .length - 1 ;
71
+ final var hasColumnToLeft = y > 0 ;
72
+ final var hasColumnToRight = y < grid [x ].length - 1 ;
73
+
74
+ if (hasRowAbove ) {
75
+ grid [x - 1 ][y ].prepareStep (population );
76
+ if (hasColumnToLeft ) {
77
+ grid [x - 1 ][y - 1 ].prepareStep (population );
78
+ }
79
+ if (hasColumnToRight ) {
80
+ grid [x - 1 ][y + 1 ].prepareStep (population );
81
+ }
82
+ }
83
+ if (hasColumnToLeft ) {
84
+ grid [x ][y - 1 ].prepareStep (population );
85
+ }
86
+ if (hasColumnToRight ) {
87
+ grid [x ][y + 1 ].prepareStep (population );
88
+ }
89
+ if (hasRowBelow ) {
90
+ grid [x + 1 ][y ].prepareStep (population );
91
+ if (hasColumnToLeft ) {
92
+ grid [x + 1 ][y - 1 ].prepareStep (population );
93
+ }
94
+ if (hasColumnToRight ) {
95
+ grid [x + 1 ][y + 1 ].prepareStep (population );
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Complete the step and finalise any side effects.
103
+ *
104
+ * @return true if and only if the octopus flashed during this step.
105
+ */
106
+ public boolean finishStep () {
107
+ if (this .energyLevel > 9 ) {
108
+ // "Finally, any octopus that flashed during this step has its energy level set to 0, as it used all of
109
+ // its energy to flash."
110
+ this .energyLevel = 0 ;
111
+ return true ;
112
+ }
113
+ return false ;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * The full population of dumbo octopuses. The population members will be modified with each step.
119
+ */
120
+ public record Population (Octopus [][] grid ) {
121
+ public int step () {
122
+ for (int i = grid .length ; --i >= 0 ; ) {
123
+ final var row = grid [i ];
124
+ for (int j = row .length ; --j >= 0 ; ) {
125
+ row [j ].prepareStep (this );
126
+ }
127
+ }
128
+ int flashes = 0 ;
129
+ for (int i = grid .length ; --i >= 0 ; ) {
130
+ final var row = grid [i ];
131
+ for (int j = row .length ; --j >= 0 ; ) {
132
+ if (row [j ].finishStep ()) flashes ++;
133
+ }
134
+ }
135
+ return flashes ;
136
+ }
137
+
138
+ }
139
+
140
+ @ Test
141
+ public final void part1 () {
142
+ final var energyLevels = getOctopusGrid ();
143
+ final var population = new Population (energyLevels );
144
+
145
+ int flashes = 0 ;
146
+
147
+ for (int step = 0 ; step < 100 ; step ++) {
148
+ flashes += population .step ();
149
+ }
150
+
151
+ System .out .println ("Part 1: " + flashes );
152
+ }
153
+
154
+ @ Test
155
+ public final void part2 () {
156
+ final var energyLevels = getOctopusGrid ();
157
+ final var population = new Population (energyLevels );
158
+ int step = 0 ;
159
+ while (true ) {
160
+ final int flashes = population .step ();
161
+ step ++;
162
+ if (flashes == 100 ) {
163
+ System .out .println ("Part 2: " + step );
164
+ break ;
165
+ }
166
+ }
167
+ }
168
+
169
+ }
0 commit comments