$num = $input->numbers;
// ==================================================
// > PART 1
// ==================================================
$pos = [$num[1] - 1, $num[3] - 1];
$score = [0, 0];
$turn = 0;
for ($d = 1;; $d += 3) {
$t = $turn++ % 2;
$pos[$t] = ($pos[$t] + ($d * 3) + 3) % 10;
$score[$t] += $pos[$t] + 1;
if ($score[$t] >= 1000) break;
}
$solution_1 = $score[($t + 1) % 2] * $turn * 3;
// ==================================================
// > PART 2
// ==================================================
$winrates = [];
$rolls = [];
foreach ([1,2,3] as $d1) foreach ([1,2,3] as $d2) foreach ([1,2,3] as $d3)
$rolls["$d1$d2$d3"] = $d1+$d2+$d3;
$get_winrate = function ($state) use (&$get_winrate, &$winrates, $rolls) {
$key = implode(",", $state);
if (isset($winrates[$key])) return $winrates[$key];
[$p1, $p2, $s1, $s2, $t] = $state;
if ($s1 >= 21) return [1, 0];
if ($s2 >= 21) return [0, 1];
$winrate = [0, 0];
$nt = $t ? 0 : 1;
foreach ($rolls as $roll) {
if ($t) {
$pn = ($p2 + $roll) % 10;
$next = [$p1, $pn, $s1, $s2 + $pn + 1, $nt];
} else {
$pn = ($p1 + $roll) % 10;
$next = [$pn, $p2, $s1 + $pn + 1, $s2, $nt];
}
$next_winrate = $get_winrate($next);
$winrate[0] += $next_winrate[0];
$winrate[1] += $next_winrate[1];
}
$winrates[$key] = $winrate;
return $winrate;
};
$solution_2 = max($get_winrate([$num[1] - 1, $num[3] - 1, 0, 0, 0]));