素数判定のメモ化のために連想配列を使います。連想配列にキーが存在するかの判定は、こうすればいいようですね。
$a = @{ 2 = $true; 3 = $true; 4 = $false } $a[5] -ne $null
無いキーを参照すると$nullが返るようです。
5分弱かかりました。
function fold($f, $x0) {
begin { $x = $x0 }
process { $x = &$f $x $_ }
end { $x }
}
$memo = @{ }
function is_prime($n) {
if($n -eq 2) {
return $true
}
elseif($n -lt 2 -or $n % 2 -eq 0) {
return $false
}
if($memo[$n] -ne $null) {
return $memo[$n]
}
for($p = 3; $p * $p -le $n; $p += 2) {
if($n % $p -eq 0) {
$memo[$n] = $false
return $false
}
}
$memo[$n] = $true
$true
}
function length($a, $b) {
for($n = 0; ; ++$n) {
if(!(is_prime (($n + $a) * $n + $b))) {
return $n
}
}
}
function abs($n) {
$a0 = -$n + 1 + $n % 2
for($b = 2; $b -lt $n; ++$b) {
if(!(is_prime $b)) { continue }
for($a = $a0; $a -lt $n; $a += 2) {
,@($a, $b)
}
}
}
function max($a, $b) {
if($a[0] -lt $b[0]) { $b } else { $a }
}
$watch = New-Object System.Diagnostics.Stopwatch
$watch.Start();
$N = 1000
abs $N | foreach { ,((length $_[0] $_[1]), ($_[0] * $_[1])) } |
fold { max $args[0] $args[1] } @(0, 0)
$watch.Stop();
$watch.Elapsed.TotalMilliSeconds / 1000