function xmd5($salt, $start, $count, $part2) {
$md5 = "";
for ($i = 0; $i < $count; $i++) {
$add = md5($salt . ($start + $i)) ;
if ($part2) for ($j = 0; $j < 2016; $j++) $add = md5($add);
$md5 .= $add . "|";
};
return [$md5, $start + $count];
}
function solve($salt, $part2 = false) {
[$md5, $i] = xmd5($salt, 0, 10000, $part2);
$found = 0; $pos = -1;
while ($found < 64) {
preg_match("/([^|]*)(.)\\2\\2.{0,33000}\\2{5}/", $md5, $match, PREG_OFFSET_CAPTURE);
$three = floor($match[2][1] / 33) + 1;
[$extra, $i] = xmd5($salt, $i, $three, $part2);
$md5 = substr($md5, $three * 33) . $extra;
$pos += $three;
if (!preg_match("/(.)\\1\\1/", $match[1][0], $test)) $found++;
}
return $pos;
}
// ==================================================
// > SOLUTIONS
// ==================================================
$solution_1 = solve($input);
$solution_2 = solve($input, true);