This fairly abstract version does caching and filtering to reduce the number of values it needs to check and moves calculations out of the hot loop, but is still interminably slow... even for just up to 1,000,000.
All is not lost, however. Through the use of gradual typing, Raku scales down as well as up, so this jit-friendly version is performant enough to brute force the larger calculation:
my @cache;@cache[1] = 1;@cache[89] = 89;subEuler92(int $n) { $n < 649 # 99,999,999 sums to 648, so no point remembering more ?? (@cache.AT-POS($n) //= ids($n)) !! ids($n)}subids(int $num -->int) {myint $n = $num;myint $ten = 10;myint $sum = 0;myint $t;myint $c; repeat until $n == 89 or $n == 1 { $sum = 0; repeat { $t = $n div $ten; $c = $n - $t * $ten; $sum = $sum + $c * $c; } while $n = $t; $n = @cache.AT-POS($sum) // $sum; } $n;}myint $cnt = 0;for 1 .. 100_000_000 ->int $n { $cnt = $cnt + 1 if Euler92($n) == 89;}say $cnt;
Output:
85744333
Which is better, but is still pretty slow.
The biggest gains are often from choosing the right algorithm.