2010年5月14日金曜日

J #2 q:

Jには,素因数分解を行ってくれる素晴らしい動詞があります.

q: Prime Factors / Prime Exponents

こんな感じ
q: 700
2 2 5 5 7
2 q: 700
2 0
10 q: 700
2 0 2 1 0 0 0 0 0 0
_ q: 700
2 0 2 1
__ q: 700
2 5 7
2 2 1

・q: 700
700の約数を並べたものをアレイとして返します(700=225271).
・2 q: 700
700 = Πk pkrk(pkはk番目の素数)としたとき,rkを2個並べたものを返します.10 q: 700も同様です.
・_ q: 700
上のrkを必要最低限だけ並べたものを返します.上の例でriは,2 0 2 1 0 0 0 0 …であり,2 0 2 1以降は全て0となるため,2 0 2 1となります.
・__ q: 700
rk≠0であるpkとrkを並べたテーブルを返します.

動詞q:を使うと,オイラーのφ関数を簡潔に記述することができます.

φ(n)は,1~nまでの自然数に対しnと互いに素なものの個数を表し,
n = Πk pkrk
としたとき(pkはk番目の素数),
φ(n) = n Πk (1 - 1/pk)
が成立します.

Euler’s totient function(オイラーのφ関数)
totient=: * -.@%@~.&.q:
totient 700
240

まず,totientを構成する動詞,副詞について説明します.
定義
x y(動詞への)引数
m n名詞
u v動詞
f g h動詞

動詞
x * yx*yTimes乗算(二項演算)
-. y1-yComplement補数(単項演算)
% y1/yReciprocal逆数(単項演算)
~. y-Nub重複要素削除(単項演算)
q: y-Prime Factors素因数分解(単項演算)

副詞
@u@v y ⇔ u v yAtop
&.u&.v y ⇔ vi u v y (viはvの逆演算)Under


これより,
-.@%@~.
は,(厳密には演算の順序が)以下のようになります.
-. % ~.
また,
-.@%@~.&.q: y
は,以下のようになります.
q:の逆演算 -. % ~. q: y
結果として,
(* -.@%@~.&.q:) y
は,(Hookが適用され)以下のようになります.
y * (q:の逆演算 -. % ~. q:) y

実際に順を追ってみていきましょう.
y=700とすると,
1. q:でyを素因数分解.
2 2 5 5 7
2. ~.で重複要素を削除.
2 5 7
3. %でそれぞれの要素について逆数をとる.
0.5 0.2 0.142857
4. -.で補数をとる.
0.5 0.8 0.857143
5. q:の逆演算を適用.q:の逆演算は(多分)アレイの要素全てを掛け合わせたものです.
0.342857
ここまでで,(q:の逆演算 -. % ~. q:) yが計算できました.Πk (1-1/pk)と同じ計算をしているのが分かるでしょうか?
6. y=700 に ((q:の逆演算 -. % ~. q:) y)=0.342857をかける.
240

というわけで.Jであらわしたφ関数は,
φ(n) = n Πk (1-1/pk)
を忠実に計算していたのです.

まだJを始めて間もないですので,間違いがありましたら指摘して下さると助かります.

0 件のコメント: