この問題はPriorityQueueを使えばごく自然に書くことができます。PowerShellでは.NETのコンテナを使うことができます。
しかし、なぜかPriorityQueueが無いんですね。
しょうがないので代替を探しましょう。SortedListが使えそうです。SortedListは辞書なんだけどインデックスでキーの昇順に参照できるものです。
$c = New-Object System.Collections.SortedList $c.Add(2, "b") $c.Add(1, "a") $c.GetKey(0) # 1 $c.GetByIndex(0) # a $c.RemoveAt(0)
ここでは値が大きい方から取り出したいので、キーには積を-1倍したもの、値に被乗数と乗数の配列を指定すればよいでしょう。気を付けなければいけないのは、すでにあるキーを加えることができないということです。キーが存在するか調べるメソッドが用意されています。
$c.contains(1)
これでとりあえず答えを出すことができます。
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
}
function products($n) {
function put($a, $b) {
if(-not $c.contains($a)) {
$c.Add($a, $b)
}
}
$c = New-Object System.Collections.SortedList
$m = $n - 1
$c.Add((-$m * $m), @($m, $m))
while($true) {
-$c.GetKey(0)
$a, $b = $c.GetByIndex(0)
$c.RemoveAt(0)
if($a -eq $b) {
put (-($a - 1) * ($a - 1)) @(($a - 1), ($a - 1))
}
put (-$a * ($b - 1)) @($a, ($b - 1))
}
}
$n = 1000
products $n | where { is_palindromic $_ }
しかし、これでは回文数がいくつも出てきてしまいます。