function get_solution($input, $rope_size)
{
    // Create a rope of XY pointers
    $rope = set()->fill(0, $rope_size, fn () => xy([0, 0]));
    // Apply each movement
    foreach ($input->lines as $line) {
        [$direction, $count] = $line->split(" ");
        // Apply movement X times
        for ($count = $count->int; $count; $count--) {
            // Move first pointer in a direction (L/R/U/D)
            $rope->first()->direction(direction($direction));
            // Move the following parts of the rope if necessary
            for ($part = 1; $part < $rope_size; $part++) {
                $distance = xy($rope[$part]->getDistanceTo($rope[$part - 1]));
                // Not more that 2 units away in any direction from parent, stay in place
                if (set($distance->xy)->map("abs")->searchNumberOver(2) === false) continue;
                // Move towards the parent, but no more than one step in each direction
                $rope[$part]->move(set($distance->xy)->map(fn ($dir) => $dir / (abs($dir) ?: 1)));
            }
        }
    }
    return $rope->last()->getVisitedCount();
}
// ==================================================
// > SOLUTIONS
// ==================================================
$solution_1 = get_solution($input, 2);
$solution_2 = get_solution($input, 10);