127 lines
2.7 KiB
PHP
127 lines
2.7 KiB
PHP
|
<?php
|
||
|
$input_file = '../inputs/day11.txt';
|
||
|
if (file_exists($input_file)) {
|
||
|
$input = file_get_contents($input_file);
|
||
|
if ($input != null) {
|
||
|
$rows = array_map('trim', explode("\n", $input));
|
||
|
print 'Part 1 answer: ' . solve($rows, false) . "\n";
|
||
|
print 'Part 2 answer: ' . solve($rows, true) . "\n";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function solve(array $rows, bool $moreTolerant): int
|
||
|
{
|
||
|
$changed = true;
|
||
|
$occupied = 0;
|
||
|
$newState = $rows;
|
||
|
|
||
|
while ($changed) {
|
||
|
$simulation_result = simulate($newState, $moreTolerant);
|
||
|
$changed = $simulation_result->changed;
|
||
|
$occupied = $simulation_result->full;
|
||
|
$newState = $simulation_result->state;
|
||
|
}
|
||
|
|
||
|
return $occupied;
|
||
|
}
|
||
|
|
||
|
function simulate(array $rows, bool $moreTolerant): day11_state
|
||
|
{
|
||
|
$newState = $rows;
|
||
|
$changed = false;
|
||
|
$empty = 0;
|
||
|
$floor = 0;
|
||
|
$full = 0;
|
||
|
for ($i = 0; $i < count($rows); $i++) {
|
||
|
for ($j = 0; $j < strlen($rows[$i]); $j++) {
|
||
|
$adjacent_occupied = get_adjacent_occupied($moreTolerant, $rows, $i, $j);
|
||
|
if ($rows[$i][$j] === 'L' && $adjacent_occupied === 0) {
|
||
|
$changed = true;
|
||
|
$full += 1;
|
||
|
$newState[$i][$j] = '#';
|
||
|
} elseif ($rows[$i][$j] === '#' && $adjacent_occupied >= ($moreTolerant ? 5 : 4)) {
|
||
|
$changed = true;
|
||
|
$empty += 1;
|
||
|
$newState[$i][$j] = 'L';
|
||
|
} else {
|
||
|
if ($rows[$i][$j] === 'L')
|
||
|
$empty += 1;
|
||
|
elseif ($rows[$i][$j] === '#')
|
||
|
$full += 1;
|
||
|
else
|
||
|
$floor += 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new day11_state($newState, $changed, $empty, $floor, $full);
|
||
|
}
|
||
|
|
||
|
function get_adjacent_occupied(bool $moreTolerant, array $state, int $y, int $x): int
|
||
|
{
|
||
|
$occupied = 0;
|
||
|
|
||
|
if ($moreTolerant === false) {
|
||
|
for ($i = $y - 1; $i < $y + 2; $i++) {
|
||
|
if ($i >= 0 && $i < count($state)) {
|
||
|
for ($j = $x - 1; $j < $x + 2; $j++) {
|
||
|
if ($j >= 0 && $j < strlen($state[$i]) && !($i === $y && $j === $x)) {
|
||
|
$occupied += $state[$i][$j] === '#' ? 1 : 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
$x_dir = -1;
|
||
|
$y_dir = -1;
|
||
|
while (true) {
|
||
|
$x_pos = $x;
|
||
|
$y_pos = $y;
|
||
|
|
||
|
while (true) {
|
||
|
if ($x_dir === 0 && $y_dir === 0)
|
||
|
break;
|
||
|
|
||
|
$x_pos += $x_dir;
|
||
|
$y_pos += $y_dir;
|
||
|
if ($y_pos < 0 || $y_pos >= count($state) || $x_pos < 0 || $x_pos >= strlen($state[$y_pos]))
|
||
|
break;
|
||
|
elseif ($state[$y_pos][$x_pos] === '.')
|
||
|
continue;
|
||
|
else {
|
||
|
$occupied += $state[$y_pos][$x_pos] === '#';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$y_dir += 1;
|
||
|
if ($y_dir == 2) {
|
||
|
$y_dir = -1;
|
||
|
$x_dir += 1;
|
||
|
}
|
||
|
if ($x_dir == 2)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $occupied;
|
||
|
}
|
||
|
|
||
|
class day11_state
|
||
|
{
|
||
|
public array $state;
|
||
|
public bool $changed;
|
||
|
public int $empty;
|
||
|
public int $floor;
|
||
|
public int $full;
|
||
|
|
||
|
function __construct(array $state, bool $changed, int $empty, int $floor, int $full)
|
||
|
{
|
||
|
$this->state = $state;
|
||
|
$this->changed = $changed;
|
||
|
$this->empty = $empty;
|
||
|
$this->floor = $floor;
|
||
|
$this->full = $full;
|
||
|
}
|
||
|
}
|