120 lines
2.6 KiB
PHP
120 lines
2.6 KiB
PHP
|
<?php
|
||
|
|
||
|
// prepare numbers and grids
|
||
|
$parts = explode("\n\n", file_get_contents('./input.txt'));
|
||
|
|
||
|
$numbers = array_map('intval', explode(',', array_shift($parts)));
|
||
|
|
||
|
$grids = array_map(static function($part) { return explode("\n", $part); }, $parts);
|
||
|
|
||
|
array_walk_recursive($grids, static function (&$grid) {
|
||
|
if (is_string($grid)) {
|
||
|
$grid = array_map(static function($g) {
|
||
|
return 0;
|
||
|
}, array_flip(array_map('trim', str_split($grid, 3))));
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* Marks cell as done
|
||
|
*
|
||
|
* @param array $grids
|
||
|
* @param int $number
|
||
|
*/
|
||
|
function modify_grids(array &$grids, int $number)
|
||
|
{
|
||
|
foreach ($grids as $i_grid => $grid) {
|
||
|
foreach ($grid as $i_row => $row) {
|
||
|
foreach ($row as $cell => $cell_val) {
|
||
|
if ($cell === $number) {
|
||
|
$grids[$i_grid][$i_row][$cell] = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* List all unmarked cell from a grid
|
||
|
*
|
||
|
* @param array $grid
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
function get_unmarked_from(array $grid): array
|
||
|
{
|
||
|
$unmarked = [];
|
||
|
foreach ($grid as $row) {
|
||
|
$unmarked = array_merge($unmarked, array_keys(array_filter($row, static function($cell) {
|
||
|
return $cell === 0;
|
||
|
})));
|
||
|
}
|
||
|
return $unmarked;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if a grid is winning
|
||
|
*
|
||
|
* @param array $grids
|
||
|
*
|
||
|
* @return bool|array
|
||
|
*/
|
||
|
function check_grids(array &$grids): bool|array
|
||
|
{
|
||
|
$result = false;
|
||
|
|
||
|
foreach ($grids as $i => $grid) {
|
||
|
if (check_lines($grid)) {
|
||
|
if (count($grids) === 1) return $grid;
|
||
|
unset($grids[$i]);
|
||
|
$result = true;
|
||
|
}
|
||
|
$rotated_grid = [];
|
||
|
$i = 0;
|
||
|
while (!empty($grid)) {
|
||
|
foreach ($grid as $j => $row) {
|
||
|
$rotated_grid[$i][array_key_last($row)] = array_pop($row);
|
||
|
$grid[$j] = $row;
|
||
|
if (empty($row)) unset($grid[$j]);
|
||
|
}
|
||
|
$i++;
|
||
|
}
|
||
|
if (check_lines($rotated_grid)) {
|
||
|
if (count($rotated_grid) === 1) return $grid;
|
||
|
unset($grids[$i]);
|
||
|
$result = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if a line is all done
|
||
|
*
|
||
|
* @param array $grid
|
||
|
*
|
||
|
* @return bool|array
|
||
|
*/
|
||
|
function check_lines(array $grid): bool|array
|
||
|
{
|
||
|
foreach ($grid as $row) {
|
||
|
if (array_sum($row) === 5) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
foreach ($numbers as $number) {
|
||
|
modify_grids($grids, (int)$number);
|
||
|
$count = count($grids);
|
||
|
$test = check_grids($grids);
|
||
|
if ($count === 1 && $test) {
|
||
|
$grid = get_unmarked_from(is_array($test) ? $test : current($grids));
|
||
|
echo array_sum($grid) * $number;
|
||
|
break;
|
||
|
}
|
||
|
}
|