Windows PowerShellでProject Euler(18)

Problem 12

素因数分解がなかなかうまくいきません。配列の配列を一つ関数から出すと、配列の配列になってくれません。仕方がないので、配列の要素の型を調べてInt32だったら配列の配列にします。

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

filter next() {
    $_
    break
}

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

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

function factorize($n) {
    function f($n, $p0) {
        if($n -gt 1) {
            for($p = $p0; $p * $p -le $n; ++$p) {
                if($n % $p -eq 0) {
                    $e, $m = div_pow $n $p
                    ,@($p, $e)
                    f $m ($p + 1)
                    return
                }
            }
            ,($n, 1)
        }
    }
    
    $fs = f $n 2
    if($fs[0].GetType().Name -eq "Int32") {
        ,(,$fs)
    }
    else {
        $fs
    }
}

function value_f($fs) {
    $fs | fold { $args[0] * (pow $args[1][0] $args[1][1]) } 1
}

filter half_f() {
    if($_[0] -eq 2) {
        if($_[1] -gt 1) {
            ,@($_[0], ($_[1] - 1))
        }
    }
    else {
        ,$_
    }
}

function triangle() {
    $prev_fs = @(,(3, 1))
    for($n = 4; ; ++$n) {
        $fs = factorize $n
        ,($prev_fs + $fs | half_f)
        $prev_fs = $fs
    }
}

function num_divs($fs) {
    $fs | fold { $args[0] * ($args[1][1] + 1) } 1
}

$N = 500
triangle | foreach { ,((value_f $_), (num_divs $_)) } |
            where { $_[1] -gt $N } | foreach { $_[0] } | next
trap { continue }