Windows PowerShellでProject Euler(15)

Problem 9

この問題は、ピタゴラス数の生成を使えば、

a + b + c = 2 lm(m + n)

だから、500を3分割してそれぞれがl, m, m + nに対応させて、それが条件

m + n : 奇数
m < m + n
m + n < 2m
gcd(m, n) = 1

を満たせばよいです。そのために約数を生成しなければなりません。本来は素因数分解して求めるのですが、大変なのでnの約数は√nまでで割ることにします。これでごく簡単になります。

function pow($n, $e) {
    if($e -eq 0) { 1 } else { $n * (pow $n ($e - 1)) }
}

function gcd($m, $n) {
    if($n -eq 0) { $m } else { gcd $n ($m % $n) }
}

function divisors($n) {
    for($d = 1; $d * $d -le $n; ++$d) {
        if($n % $d -eq 0) {
            $d
            $d2 = $n / $d
            if($d2 -ne $d) {
                $d2
            }
        }
    }
}

function divisors3($n) {
    foreach($d1 in divisors($n)) {
        $d2 = $n / $d1
        foreach($d3 in divisors($d2)) {
            ,@($d1, $d3, ($d2 / $d3))
        }
    }
}

function is_right_triangle($tria) {
    $l, $m, $d = $tria
    $d % 2 -eq 1 -and $m -lt $d -and $d -lt ($m * 2) -and (gcd $m $d) -eq 1
}

# a = l(m^2 - n^2)
# b = 2lmn
# c = l(m^2 + n^2)
# a + b + c = 2lm(n + m)
# abc = 2l^3mn(m^4 - n^4)

$N = 1000
divisors3 ($N / 2) | where { is_right_triangle $_ } |
        foreach { 2 * (pow $_[0] 3) * $_[1] * ($_[2] - $_[1]) *
                            ((pow $_[1] 4) - (pow ($_[2] - $_[1]) 4)) }