8
8
9
9
class Day11 extends DayBehaviour implements DayInterface
10
10
{
11
- protected function applyRulesToSeats (array $ seats ): array
12
- {
13
- return [];
14
- }
11
+ protected int $ i = 0 ;
15
12
16
13
/**
17
14
* All decisions are based on the number of occupied seats adjacent to a given seat
18
15
* (one of the eight positions immediately up, down, left, right, or diagonal from the seat).
19
16
* The following rules are applied to every seat simultaneously:.
17
+ * Rules:
18
+ * If a seat is empty (L) and there are no occupied seats adjacent to it, the seat becomes occupied.
19
+ * If a seat is occupied (#) and four or more seats adjacent to it are also occupied, the seat becomes empty.
20
+ *
21
+ * Simulate your seating area by applying the seating rules repeatedly until no seats change state. How many seats end up occupied?
20
22
*
21
23
* @return int|null
22
24
*/
23
25
public function solvePart1 (): ?int
24
26
{
25
- $ this ->input = [
27
+ /* $this->input = [
26
28
'L.LL.LL.LL',
27
29
'LLLLLLL.LL',
28
30
'L.L.L..L..',
@@ -33,21 +35,73 @@ public function solvePart1(): ?int
33
35
'LLLLLLLLLL',
34
36
'L.LLLLLL.L',
35
37
'L.LLLLL.LL',
36
- ];
37
- $ this ->input = array_map (static fn (string $ s ): string => trim ($ s ), $ this ->input );
38
- $ i = 0 ;
39
- /*while(true) {
40
- $seatsChanged = 0;
38
+ ];*/
39
+ // convert into [y][x] array
40
+ $ this ->input = array_map (static fn (string $ s ): array => str_split (trim ($ s )), $ this ->input );
41
+ $ finalSeatingPlan = $ this ->seatTraverse ();
42
+ $ occupied = array_filter (array_merge (...$ finalSeatingPlan ), static fn (string $ s ) => '# ' === $ s );
43
+
44
+ return count ($ occupied );
45
+ }
41
46
42
- foreach($this->input as &$row) {
43
- $adjacent = '';
44
- array_walk($row, static function(string $s) use (&$seatsChanged) {
47
+ protected function seatTraverse (?array $ seatLayout = null ): array
48
+ {
49
+ ++$ this ->i ;
50
+ // final recursive check
51
+ if ($ seatLayout === $ this ->input ) {
52
+ return $ this ->input ;
53
+ }
54
+
55
+ // if we haven't been seeded then start with input
56
+ $ this ->input = $ seatLayout ?? $ this ->input ;
45
57
46
- });
58
+ $ newInput = $ this ->input ; // clone it, we'll make all changes to the new input
59
+ for ($ y = 0 , $ yMax = count ($ this ->input ); $ y < $ yMax ; ++$ y ) {
60
+ for ($ x = 0 , $ xMax = count ($ this ->input [$ y ]); $ x < $ xMax ; ++$ x ) {
61
+ $ adjacentSeats = [
62
+ // above
63
+ $ this ->input [$ y - 1 ][$ x - 1 ] ?? '' ,
64
+ $ this ->input [$ y - 1 ][$ x ] ?? '' ,
65
+ $ this ->input [$ y - 1 ][$ x + 1 ] ?? '' ,
66
+ // below
67
+ $ this ->input [$ y + 1 ][$ x - 1 ] ?? '' ,
68
+ $ this ->input [$ y + 1 ][$ x ] ?? '' ,
69
+ $ this ->input [$ y + 1 ][$ x + 1 ] ?? '' ,
70
+ // left
71
+ $ this ->input [$ y ][$ x - 1 ] ?? '' ,
72
+ // right
73
+ $ this ->input [$ y ][$ x + 1 ] ?? '' ,
74
+ ];
75
+ $ occupiedAdjacent = array_filter ($ adjacentSeats , static fn (string $ v ) => '# ' === $ v );
76
+ $ seat = $ this ->input [$ y ][$ x ];
77
+ switch ($ seat ) { // faster than using match
78
+ case '. ' :
79
+ continue 2 ;
80
+ case 'L ' :
81
+ if (empty ($ occupiedAdjacent )) {
82
+ $ newInput [$ y ][$ x ] = '# ' ;
83
+ }
84
+ break ;
85
+ case '# ' :
86
+ if (4 <= count ($ occupiedAdjacent )) {
87
+ $ newInput [$ y ][$ x ] = 'L ' ;
88
+ }
89
+ break ;
90
+ }
47
91
}
92
+ /*printf("y: %d\n%s\n%s\n",
93
+ $y,
94
+ implode('', $this->input[$y]),
95
+ implode('', $newInput[$y]),
96
+ );*/
48
97
}
49
- print_r($this->input);*/
50
- return null ;
98
+ /*printf("%d: new: %d old: %d\n",
99
+ $this->i,
100
+ count(array_filter(array_merge(...$newInput), static fn (string $s) => '#' === $s)),
101
+ count(array_filter(array_merge(...$this->input), static fn (string $s) => '#' === $s)),
102
+ );*/
103
+
104
+ return $ this ->seatTraverse ($ newInput );
51
105
}
52
106
53
107
public function solvePart2 (): ?int
0 commit comments