Windows PowerShellでProject Euler(8) 配列

Problem 4

今回は回文数の判定を行います。そのために配列の使い方を覚えます。

about_Arrays

配列は次のように作成します。

$a = 3, 5, 7
$a[2]           # 7

これでもOKです。

$a = @(3, 5, 7)

次のようにすると2次元配列のようになります。

$b = @(@(3, 4), @(5, 6))
$b[1][1]                    # 6

配列で気を付けなければいけないのは次のようなときです。

function g() {
    @(1, 2)
    3
}

filter f() {
    $_.GetType()
}

g | f

filterはbegin, process, endの構文からprocessのみを残したようなものです。これを実行すると、

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType
True     True     Int32                                    System.ValueType
True     True     Int32                                    System.ValueType

と配列が分解されて排出しまいます。配列を排出するなら、頭に「,」をつけます。

function g() {
    ,@(1, 2)
    3
}
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
True     True     Int32                                    System.ValueType

ここでfoldを作りましょう。

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

1, 2, 3 | fold { $args[0] * 10 + $args[1] } 0

スクリプトブロックの$argsは引数の配列です。引数が複数の場合はこれを使います。スクリプトブロックを変数にしたとき&をつけると関数として使うことができます。これで回文数の判定ができます。

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

function digits($n) {
    while($n -gt 0) {
        $d = $n % 10
        $d
        $n = ($n - $d) / 10
    }
}

function is_palindromic($n) {
    $m = digits $n | fold { $args[0] * 10 + $args[1] } 0
    $m -eq $n
}

is_palindromic 12321    # True
is_palindromic 12345    # False