$aler = set();
$ingr = set();
foreach ($input->lines as $line) {
    [$_, $i, $a] = $line->match("/^(.+) \(contains (.*)\)$/");
    $i = explode(" ", $i);
    $ingr = $ingr->merge($i);
    foreach (explode(", ", $a) as $al) {
        $aler[$al] = isset($aler[$al]) ? $aler[$al]->keep($i) : set($i);
    }
}
// ==================================================
// > PART 1
// ==================================================
$solution_1 = $ingr->remove($aler->merge()->unique())->count();
// ==================================================
// > PART 2
// ==================================================
while (true) {
    foreach ($aler as $i=>$a) {
        if (!is_string($a) && $a->count() == 1) {
            $aler[$i] = $al = $a->values()[0];
            foreach ($aler as $j=>$b) if (!is_string($aler[$j])) $aler[$j] = $aler[$j]->remove([$al]);
            continue 2;
        }
    }
    break;
}
$solution_2 = $aler->sortKeys()->join(",");