PE #002, #006 in J

id:flappphys:20080322#p1 の続き.「Fibonacci数列の項のうち4,000,000を超えず,かつ偶数のものの和を求めよ」

0 ([+(*-.@(2&|))@{.@] $: (>1 1;1 0)&(+/ .*)@])`[ @. ((4e6&<)@{.@]) 2 1
4613732

Jによる再帰関数の書き方を覚えた.Verb $: が「それを含む(最も外側までの)verb」を参照してくれる.そして x u`v @. w yif. (x w x) = 0 do. (x u y) elseif. (x w y) = 1 do. (x v y) end. の意*1.上式では左引数が末尾再帰化のためのアキュムレータ,右引数が数列の最後の2項から成るvectorで,それに行列を掛けて発展させてゆく.
よしよし,次第に「行列*2有理数の扱える関数電卓」として使えるようになってきたぞ.ただし後知恵で括弧を外してみたものの,式の評価規則(特にadverbやconjunctionの優先順位)がよく分からん.
#006「100以下の自然数の,『和の自乗』と『自乗の和』の差を求めよ」は簡単だった(解いた人が多い順に進めてる

(*:@(+/) - +/@(*:"1)) 1+i.100
25164150

ただしJの配列に対する自動並列化機能((スレッドとかマルチコアとかのHPCな意味でどうなるかは知らない.単に 10 + 1 2 3 = 11 12 13 とかその辺の機能を指して言ってる.))を適切に制御するための "1 に注意.Forkの右側のverb +/@(*:"1) では,これがないと和 +/ が数列の各項に並列化され,無意味になってしまう.

*1:ただしif構文はverbの定義内でしか使えず,ワンライナーには適さない.

*2:Jでは行列演算の多くは組み込みではなくて,あくまでもプリミティブ演算の組み合わせで実現されるのだが.