Windows PowerShellでProject Euler(28)

Problem 21

エラトステネスのふるい的に約数の和を求めるだけですね。

function fold($f, $x0) {
    begin   { $x = $x0 }
    process { $x = &$f $x $_ }
    end     { $x }
}

function div_pow($n, $d) {
    $e = 0
    while($n % $d -eq 0) {
        ++$e
        $n /= $d
    }
    ($e, $n)
}

function sum_divs($n) {
    $a = 0..$n
    $b = $a | foreach { 1 }
    foreach($p in 2..$n) {
        if($p * $p -gt $n) {
            break
        }
        elseif($a[$p] -eq $p) {
            for($k = $p; $k -le $n; $k += $p) {
                $e, $a[$k] = div_pow $a[$k] $p
                $b[$k] *= (1..$e | fold { $args[0] * $p + 1 } 1)
            }
        }
    }
    
    foreach($k in 2..$n) {
        if($a[$k] -ne 1) {
            $b[$k] *= $a[$k] + 1
        }
    }
    0..$n | foreach { $b[$_] - $_ }
}

function gen_amicables($n) {
    $d = sum_divs $n
    foreach($k in 2..$n) {
        $m = $d[$k]
        if($m -lt $k -and $d[$m] -eq $k) {
            $k, $m
        }
    }
}

(gen_amicables 10000 | measure -sum).sum