Answer ⏱
[VISUALISATION]
Part 1 :
Part 2 :
$bot = new Intcode($input);
$bot->run();
$grid = new Grid(
trim($bot->output->map(fn ($c) => chr($c))->join(""))
);
// ==================================================
// > PART 1
// ==================================================
$solution_1 = 0;
foreach ($grid->searchAll("#") as $pos) {
if ($grid->getNeighbors($pos)->keep("#")->count() == 4) {
$solution_1 += $pos[0] * $pos[1];
}
}
// ==================================================
// > PART 2
// ==================================================
// Step 1 : Find the full route
$pos = $grid->search("^");
$dir = 0;
$path = set([]);
while (true) {
$neig = $grid->getNeighbors($pos);
$ndir = null;
if ($neig->values()[$dir] == "#") {
$path[count($path) - 1]++;
$ndir = $dir;
}
elseif ($neig->values()[($dir + 1) % 4] == "#") {
$path->insert(["R", 1]);
$ndir = ($dir + 1) % 4;
}
elseif ($neig->values()[($dir + 3) % 4] == "#") {
$path->insert(["L", 1]);
$ndir = ($dir + 3) % 4;
}
if (is_null($ndir)) break;
$pos = explode(";", $neig->keys()[$ndir]);
$dir = $ndir;
}
// Step 2 : Find the patterns A, B, C
$path = (string) $path->join(",");
$func = [];
while (true) {
$i = 1;
$f = false;
while (true) {
if (preg_match("/.*((?:(?:R|L),[0-9]+,?){".$i."}).*\\1.*\\1.*/", $path, $match)) {
$f = trim($match[1], ",");
$i++;
} else break;
}
if (!$f) break;
$func[["A", "B", "C"][count($func)]] = $f;
$path = str_replace($f, array_keys($func)[count($func) - 1], $path);
}
// Step 3 : run with functions
$bot = (new Intcode($input->numbers()->set(0, 2)));
$bot->input = set(array_map("ord", str_split(implode("\n", array_merge([$path], $func, ["n\n"])))));
$solution_2 = $bot->run();