// ==================================================
// > PART 1
// ==================================================
// X, Y, Size, Used, Avail, Use%
$nodes = $input->lines->slice(2)->map(fn ($l) => $l->numbers());
$solution_1 = 0;
foreach ($nodes as $a) foreach ($nodes as $b) {
if ($a[0] == $b[0] && $a[1] == $b[1]) continue;
if (empty($a[3])) continue;
if ($b[4] < $a[3]) continue;
$solution_1++;
}
// ==================================================
// > PART 2
// ==================================================
// Define graph : empty space can move everywhere except to heavy nodes
$graph = new Graph(function ($graph) {
$neighbors = neighbors(explode(";", $graph->current), false, 0, $graph->width, 0, $graph->height);
$neighbors = array_filter($neighbors, fn ($n) => !in_array($n, $graph->heavy));
return array_fill_keys(array_map(fn ($xy) => implode(";", $xy), $neighbors), 1);
});
// Compute nodes
$cells = $input->lines->slice(2)->mapAssoc(function ($i, $line) {
[$x, $y, $size, $used] = $line->numbers;
return ["$x;$y" => [$x, $y, $used, $size]];
});
$graph->width = $cells->column(0)->max();
$graph->height = $cells->column(1)->max();
$average_space = $cells->column(3)->average();
$graph->heavy = (array) $cells->filter(fn ($n) => $n[3] > $average_space)->keys()->map(fn ($k) => explode(";", $k));
// Start exploring : shortest path to move empty cell to the left of the target
$solution_2 = $graph->explore(
$cells->column(2)->search(0),
($graph->width - 1).";0"
);
// Move the target to the goal (0;0) by moving the empty cell around it (5 moves per cell)
$solution_2 = $solution_2[1] + ($graph->width - 1) * 5 + 1;