Windows PowerShellでProject Euler(34) 連想配列

Problem 27

素数判定のメモ化のために連想配列を使います。連想配列にキーが存在するかの判定は、こうすればいいようですね。

$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