<?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;
    }
}