@@ -26,53 +26,80 @@ protected void runPartTwo(final Scanner in) {
2626 run (in , true );
2727 }
2828
29- private void run (final Scanner in , final boolean loop ) {
29+ private void run (final Scanner in , final boolean repeat ) {
3030 final List <String > rows = new ArrayList <>();
3131
3232 while (in .hasNextLine ()) {
3333 rows .add (in .nextLine ());
3434 }
3535
36- char [][] grid = new char [rows .size ()][rows .get (0 ).length ()];
36+ final boolean [][] done = new boolean [rows .size ()][rows .getFirst ().length ()];
37+ final Queue <Coordinate > queue = new ArrayDeque <>(getInitialEmptyCoordinates (rows ));
38+
39+ int movable = 0 ;
40+ while (!queue .isEmpty ()) {
41+ final Coordinate coordinate = queue .poll ();
42+ if (done [coordinate .x ][coordinate .y ]) {
43+ continue ;
44+ }
45+
46+ final char current = rows .get (coordinate .x ).charAt (coordinate .y );
47+ final Set <Coordinate > neighbours = getNeighbours (done , coordinate , rows , repeat );
48+ if (current == '.' ) {
49+ queue .addAll (neighbours );
50+ done [coordinate .x ][coordinate .y ] = true ;
51+ } else {
52+ if (neighbours .size () < 4 ) {
53+ ++movable ;
54+ done [coordinate .x ][coordinate .y ] = true ;
55+ if (repeat ) {
56+ queue .addAll (neighbours );
57+ }
58+ } else {
59+ done [coordinate .x ][coordinate .y ] = !repeat ;
60+ }
61+ }
62+ }
63+
64+ print (movable );
65+ }
66+
67+ private static List <Coordinate > getInitialEmptyCoordinates (final List <String > rows ) {
68+ final List <Coordinate > coordinates = new ArrayList <>();
3769 for (int i = 0 ; i < rows .size (); ++i ) {
3870 for (int j = 0 ; j < rows .get (i ).length (); ++j ) {
39- grid [i ][j ] = rows .get (i ).charAt (j );
71+ if (rows .get (i ).charAt (j ) == '.' ) {
72+ coordinates .add (new Coordinate (i , j ));
73+ }
4074 }
4175 }
4276
43- int movable = 0 ;
44- boolean moved = false ;
45- do {
46- char [][] newGrid = new char [grid .length ][grid [0 ].length ];
47- moved = false ;
48-
49- for (int row = 0 ; row < grid .length ; ++row ) {
50- for (int column = 0 ; column < grid [row ].length ; ++column ) {
51- int surrounding = 0 ;
52-
53- for (int i = Math .max (row - 1 , 0 ); i <= Math .min (row + 1 , grid .length - 1 ); ++i ) {
54- for (int j = Math .max (column - 1 , 0 );
55- j <= Math .min (column + 1 , grid [i ].length - 1 );
56- ++j ) {
57- if (i != row || j != column ) {
58- surrounding += grid [i ][j ] == '@' ? 1 : 0 ;
59- }
60- }
61- }
77+ return coordinates ;
78+ }
6279
63- if (grid [row ][column ] == '@' && surrounding < 4 ) {
64- moved = true ;
65- ++movable ;
66- newGrid [row ][column ] = '.' ;
67- } else {
68- newGrid [row ][column ] = grid [row ][column ];
69- }
80+ private Set <Coordinate > getNeighbours (
81+ final boolean [][] done ,
82+ final Coordinate coordinate ,
83+ final List <String > rows ,
84+ final boolean repeat ) {
85+ final Set <Coordinate > neighbours = new HashSet <>();
86+
87+ for (int x = Math .max (coordinate .x - 1 , 0 );
88+ x <= Math .min (coordinate .x + 1 , done .length - 1 );
89+ ++x ) {
90+ for (int y = Math .max (coordinate .y - 1 , 0 );
91+ y <= Math .min (coordinate .y + 1 , done [coordinate .x ].length - 1 );
92+ ++y ) {
93+ if ((x != coordinate .x || y != coordinate .y )
94+ && rows .get (x ).charAt (y ) == '@'
95+ && (!done [x ][y ] || !repeat )) {
96+ neighbours .add (new Coordinate (x , y ));
7097 }
7198 }
99+ }
72100
73- grid = newGrid ;
74- } while (loop && moved );
75-
76- print (movable );
101+ return neighbours ;
77102 }
103+
104+ private record Coordinate (int x , int y ) {}
78105}
0 commit comments