<?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
{
    foreach ($grids as $grid) {
        if (check_lines($grid)) {
            return get_unmarked_from($grid);
        }
        $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)) {
            return get_unmarked_from($rotated_grid);
        }
    }

    return false;
}

/**
 * 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);
    $grid = check_grids($grids);
    if ($grid !== false) {
        echo array_sum($grid) * $number;
        break;
    }
}