プログラミング言語/J
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
#contents
* J [#w69ef1bc]
J、その可読性の低さゆえ全く流行していないプログラミング言...
* まずはJをゲット [#x9b7b79a]
Jの処理系は[[Jsoftware>http://www.jsoftware.com/]]で配布...
Download→Stableからそれぞれの環境にあった処理系のインスト...
インストーラでは、一人で使うのか、それともPCのユーザー全...
これは人それぞれ自由に選んでおk。~
一人で使う場合はそのユーザのホームフォルダに、全員で使う...
* Jに触ってみる [#u1786b04]
** Jの起動 [#oc3780d4]
Jの処理系は、Jがインストールされたディレクトリから~
./bin/j.exe~
と辿ったところにあるので起動する。
Jの処理系は対話型なので、プログラムを入力するとその場で実...
これを使ってJを高性能かつ簡単な電卓として使うこともできる。
** Hello, world! [#td4009da]
Jでは、文字列は''(シングルクォーテーション)で囲ったもので...
また、文字列を入力するとそのまま返すので、Hello, world!プ...
'Hello, world!'
上の通りにJに入力してやると、Hello, world!という表示が返...
Jの窓は以下のような状態になっているはず。
'Hello, world!'
Hello, world!
このように、Jでは入力を半角スペース三つ分インデントして表...
また出力は行頭から表示される。~
以降に示すサンプルも全てこれに則って書いてあるので~
実際に試すときはインデントされている部分だけを入力すれば...
** 呼称について [#e707e479]
例えば普通のプログラミング言語の場合、以下のプログラムで...
int a = 10;
printf("%d\n", a + 10)
だがJの場合、演算子とか関数とか言った呼称は用いず、次のよ...
- 演算子、関数 → 動詞
- 定数、変数 → 名詞
ほかにも、動詞の動作に影響を与える副詞、品詞同士をつなぐ...
余談だがこのように自然言語っぽい呼び方をする所は俺大好き。
* まずは簡単な計算から [#d62311d2]
** 四則演算+α [#bc98a58a]
まず加算減算乗算除算そして剰余を求める計算をやってみる。~
加算減算乗算を行う動詞はそのまんま、+と-と*。
5 + 3
8
7 - 4
3
6 * 5
30
除算の動詞は % を使う。~
普通の言語だと除算は / で、剰余が % とかいうことが多いけ...
Jでは除算が % なので間違ったりこんがらがったりしないよう...
16 % 8
2
5 % 2
2.5
13 % 7
1.85714
で、剰余(あまりを求める)の動詞は | (縦線)。~
注意しなきゃいけないのは、剰余を求めようとして「x | y」と...
「xをyで割ったときのあまり」ではなく''「yをxで割ったとき...
名詞の順番を間違えないように。
5 | 13
3
2 | 30
0
とりあえず理解確認のために以下の問題を解いてみようか。
- 123×456をJ言語で求めてください
- 98÷17をJ言語で求めてください
- 200を21で割ったあまりを求めてください
答がそれぞれ56088、5.76471、11になったら読み進めよう。~
ならなかったら読み直せ。
** 数値リテラル [#n621dd07]
一口に数といってもいろいろある。~
整数、小数、正の数、負の数、実数、複素数・・・~
それらの数を表現するための方法が幾つかある。
*** 指数表現 [#t55b0cd8]
とても大きい数やとても小さい数を表すのに使う「x * 10のy乗...
「x * ''10''のy乗」ということで、10を底とした指数表現にな...
たとえば「13000000000」は「1.3*10の10乗」で''「1.3e10」''...
1.3 * 10000000000
1.3e10
1.2345e5
123450
*** 負の数 [#qa2e1595]
負の数はふつう「-」(マイナス)の符号をつけるが~
Jの場合は少し違う。Jで負数を表すには _ (アンダースコア)を...
3 - 5
_2
_3 + 9
6
_5 * 4
_20
*** 無限・未定義 [#y81803e2]
数が大きすぎたり、定義されない値をとった場合の表現の仕方...
まあ普通、ほとんど使わない。~
無限は _ (アンダースコア)、未定義は _. (アンダースコアと...
無限と負数の表現が同じだけれども、無限の場合はアンダース...
負数の場合は数も書くので区別できる。~
ちなみに、アンダースコアを二つ繋げるとマイナス無限大を表...
1.2345e999 * 6.789e999
_
_. * 123 + 456 - 789 % 999
_.
_1 * _
__
*** その他 [#n8de987a]
その他にも複素数とか分数とかあるけどまあ後々説明する。
** 優先順位 [#oa012429]
優先順位は数学と同じ、''なんて甘いことを言っちゃいかん。''~
だからといって複雑な順位が決められてるわけでもなく、~
''右から順番に計算''されるだけ。つまり、
1 - 2 - 3 - 4
_2
こうなる。~
「1 - 2 - 3 - 4」は「1 - (2 - (3 - 4))」になるので答はマ...
というわけで確認問題
- 「10 - 3 + 3」がどのような答になるか予測して、J言語で実...
- 「2 * 3 - 4」がどのような答になるか予測して、J言語で実...
- 「0.3 * 20 - 10」がどのような答になるか予測して、J言語...
予測と実際の答が合っていれば読み進めよう。~
合ってなかったら読み直せ。
** 単項と二項 [#o6d3e273]
Jの動詞は単項で使った場合(動詞の右にだけ名詞がくる)と~
二項で使った場合(動詞の左右両方に名詞がくる)場合で全く異...
詳しい挙動については後々品詞一覧で述べようと思うが~
代表的なものを挙げておこうと思う。
「*」は単項だと符号の判定、二項だと乗算になる。
2 * 4
8
3 * 5
15
* 3
1
* _12
_1
* 0
0
「|」は単項だと絶対値、二項だと剰余になる。
3 | 15
0
4 | 22
2
| 50
50
| _13
13
| 0
0
この単項と二項の使い分けはJのコードを読む上でとても重要だ...
単項と二項で動作が変わるということは覚えておいてほしい。
* コメント [#tecae16a]
コメントは「NB.」でつけることができる。
NB.以降は行末までがコメントになる。
3 * 5 + 6 NB. 5と6を足して3倍する
33
* アレイ [#vc22a891]
** アレイの基本 [#jfbdf907]
Jでは沢山の値を纏めて扱うことができる。~
他の言語でいう配列のようなものをアレイと呼ぶ。~
アレイを定義するには、数値同士を半角空白で区切ればいい。~
アレイ同士の演算も可能である。
1 2 3 + 4 5 6
5 7 9
1 2 3 * 6 5 4
6 10 12
アレイ同士で演算を行う場合、両方の長さが等しくなければな...
長さの等しくないアレイ同士で演算を行おうとすると、length ...
1 2 3 4 + 5 6
|length error
| 1 2 3 4 +5 6
また、アレイと単一の名詞との演算もできる。
1 2 3 + 5
6 7 8
1 2 3 * 10
10 20 30
** アレイの操作 [#h29a9f16]
アレイの要素数は動詞 # (シャープ)で求めることができる。
# 1 2 3
3
# 1 2 3 4 5 6 7 8 9 10
10
0から指定された値 - 1までのアレイを作る動詞 i. (イオタ)と...
i. 10
0 1 2 3 4 5 6 7 8 9
5 + i. 10
5 6 7 8 9 10 11 12 13 14
# i. 10
10
** アレイの整形 [#j2556f87]
動詞 $ (ドル)を使うと、アレイを整形することができる。~
整形する場合、$は二項動詞として用い、左に形、右に値をもっ...
二次元以上のものを作り出すことができる。
3 4 $ i. 12 NB. 3 * 4のテーブルの形に i. 12 を整形...
0 1 2 3
4 5 6 7
8 9 10 11
2 4 $ 1 2 3 NB. 要素が足りない場合は繰り返される
1 2 3 1
2 3 1 2
3 3 $ i.100 NB. 要素が余る場合は切り捨てられる
0 1 2
3 4 5
6 7 8
* 副詞を使ってみる [#se546a3d]
副詞は、動詞の動作に影響するもので、使いようによってはか...
とりあえず一番よく使うであろう副詞 / (スラッシュ)の説明を...
まず副詞はどうやって使うかというと、動詞の直後につけて使...
動詞 + に副詞 / をつけると +/ となる。~
この場合、 +/ という新しい動詞ができたと考えた方が簡単。
で、この副詞 / というものの効果は「挿入」(もちろん性的な...
「挿入」というのはアレイの各要素の間にその動詞を挿入する...
「+/ 1 2 3 4 5」という文は「1 + 2 + 3 + 4 + 5」と解釈され...
つまり +/ というのはアレイの要素の合計を求める新しい動詞...
これを使えば、1~100までの自然数の和を求めるプログラムだ...
+/ i. 101
5050
* フックとフォーク [#yc0eb80b]
さて、それではJ言語の一番の特徴である「動詞の合成」の説明...
ここは結構複雑だから一気に理解しようとせずに、ゆっくり理...
** フック [#g5488e75]
フックは動詞二つを合成するときの決まりで、以下のようにな...
(f, gは動詞、x, yは名詞)
(f g) y → y f g y
x (f g) y → x f g y
まず単項の場合、動詞gを単項動詞としてyを与えて評価させる。~
そして動詞fを二項動詞として「g y」の値と、元のyを与えて評...
(+ *) 5
6
この場合、まず動詞*に5が渡されて「* 5」が評価される。~
単項*動詞は符号の判定なので、「* 5」は1となる。~
次に動詞+に 1 と 5 が渡され、結果は6となる。
二項の場合、最後の動詞fに渡す名詞がyではなくxになるだけで...
単項の場合の動作が分かれば簡単に理解することができる。
** フォーク [#ad981d8b]
フォークは動詞三つを合成するときの決まりで、以下のように...
(f, g, hは動詞、x, yは名詞)
(f g h) y → (f y) g h y
x (f g h) y → (x f y) g x h y
まず単項の場合、動詞fとhにyを与えて評価し、~
その結果の二つ値をgに与えて評価させる。例えば
(+/ % #) 3 5 7 9
6
この場合、
- f = +/
- g = %
- h = #
- y = 3 5 7 9
となるから、
(+/ 3 5 7 9) % # 3 5 7 9
と解釈される。~
#はアレイの要素数を求めるので 4 (これが「h y」の値)~
+/はアレイの要素の合計を求めるので 24 (これが「f y」の値)~
よって、
24 % 4
になるから、答は6となる。~
合計を要素数で割る操作、つまりこれは平均を求めていること...
フォークをうまく使うことで、平均を求める操作を (+/ % #) ...
** トレイン [#r8ec94dc]
四つ以上の動詞の合成時の決まりで、これはフックとフォーク...
例えば、四つの動詞a, b, c, dを合成するときは
(a b c d) → (a (b c d))
となり、右から三つ b, c, d でフォークが起きる。~
その結果と a でフックが起きる。
トレインの合成規則はかなり複雑になるが、所詮フックとフォ...
フックとフォークを理解できていれば読むのは難しくはない。
* 代入と定義 [#r9653681]
Jでは、代入の操作を行うことによって、名詞や動詞などを定義...
代入には二種類あって、 =. (ローカル)、 =: (グローバル) が...
** ローカル [#m48dd72f]
ローカルな代入は、その範囲内でしか利用しない単語の定義に...
例えば以下の例では、名詞 a は動詞 test 内でしか利用できな...
(3 : 0の意味などについては後述する。)
test =: 3 : 0 NB. 動詞の定義
a =. y
2 * a
)
** グローバル [#m74a5c92]
グローバルな代入は、あらゆる場所でその単語を利用すること...
例えば以下の例では、動詞の定義外で定義された名詞を動詞の...
global =: 0
test2 =: 3 : 0
global =: global + 1
)
** 名詞の定義 [#t634f696]
名詞を定義するのは簡単で、代入の動詞を使えばおk。
a =. 5
a NB. a の値を表示する
5
すべての文は右から評価されるから、名詞の内容に文をもって...
それが評価されて、名詞に代入されることになる。
b =. 5 + i. 10
b
5 6 7 8 9 10 11 12 13 14
名詞どうしの演算もできるし、名詞を使った演算の結果を別の...
c =. 10
d =. i. 5
c + d
10 11 12 13 14
e =. c * d
e
0 10 20 30 40
** 動詞の定義 [#z411061c]
動詞といっても、単項と二項があって~
さらに二種類の定義方法が存在する。
*** 暗黙(Tacit)の定義 [#i38b4df0]
暗黙の定義では引数といったものは存在せず、~
ただ動詞の中身が展開されるだけである。~
一番簡単な暗黙の定義を見てみよう。
plus =: +
これを使うコードは例えば以下のようになる。
10 plus 20
30
つまり、コードは以下のように展開されたことになる。
10 plus 20 → 10 (+) 20
暗黙の定義は、括弧つきで展開されるのと同等なので~
動詞の合成を効果的に使うことができる。
avg =: +/ % # NB. 平均を求める
avg 10 15 22 34 42
24.6
このコードは以下のように展開されたことになる。
avg 10 15 22 34 42 → (+/ % #) 10 15 22 34 42
*** 明示的(Explict)な定義 [#y1f435ff]
明示的な定義は、引数を受け取って値を返すという動作を明確...
引数は単項か二項かによって数が変わるため、~
定義する時点で単項動詞か二項動詞かを明示しておく必要があ...
(暗黙の定義は展開されるだけなので明示の必要はない。)
動詞の種類の明示には、接続詞 : (コロン)を使う。~
: の左に動詞の種類、右に動詞の中身を''文字列''として記述...
例えばさっきの加算を行う動詞 plus を明示的な定義で書き直...
plus =: 4 : 'x + y'
まず、 4 というのが二項動詞の明示である。~
で、動詞の左側に置かれる引数が x 、右側に置かれる引数が y...
次に、平均を求める動詞を明示的な定義で書き直してみる。
avg =: 3 : '(+/ y) % # y' NB. もちろん合成も使える...
さて、定義したい動詞が長いと、どうしても一行じゃ読みにく...
そこで、接続詞 : の右側に 0 を持ってくると複数行の動詞を...
test =: 3 : 0
y + y
)
複数行の動詞の定義は ) で終了する。
*** 暗黙の定義と明示的な定義 [#c1ee296c]
上の二つの例(動詞 plus, avg)でも分かる通り、~
明示的な定義の方が長く、冗長になりがちだが、暗黙の定義は...
どちらを使うかは好みだろうが、明示的な定義の方が定義しや...
一方暗黙の定義はスマートで、こちらの方がJの特色をより反映...
なのでどちらを使ったほうがいいというものはないから、好み...
ここでもう一つ、動詞の定義方法を紹介しようと思う。~
でもまあ新しいわけではなく、明示的な定義を暗黙の定義に変...
明示的な定義を暗黙の定義に変換するには、接続詞 : の左側に...
fx =: 3 : '32 + y * 9 % 5' NB. 摂氏を華氏に変換する
ft =: 13 : '32 + y * 9 % 5' NB. 摂氏を華氏に変換す...
ここで動詞の中身を見てみると
fx
3 : '32 + y * 9 % 5'
ft
32 + 1.8 * ]
となり、ftの方が暗黙の定義に変換されているのが分かる。
* さあプログラムを書こう [#c2e33b68]
これまでで大体Jの基本は抑えられたと思う。~
後は語彙の問題で、どんな単語があって、どんな動作をするの...
これを覚えていけばいいだけ。~
ただ、語彙はけっこう豊富だし、それも記号の羅列になるから...
増してや勉強感覚で覚えようと思っても身につくわけがない。~
だからここからは、ひたすらたくさんプログラムを書いて、~
その中で語彙を増やしていってほしいと思う。
ちなみに単語の一覧表はJsoftwareの[[Vocabulary>http://www....
ブックマークに突っ込むなり何なりしておくと便利だと思う。
英語が読める人はJsoftwareからWikiを辿って色々な文章を読ん...
** Project Euler [#vcf633d5]
さて、書くプログラムのお題だが、ここではJの得意な数学分野...
Project Eulerの問題は英語で書かれているが、[[Project Eule...
*** Problem 1 [#r8c7728a]
- [[Problem 1 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>10未満の自然数のうち、3 もしくは 5 の倍数になっているも...
>同じようにして、1,000 未満の 3 か 5 の倍数になっている数...
まず、1000未満の数ということなので、999までの数列を用意す...
これは前に説明した i. (イオタ)を使えば簡単にできる。~
とりあえず数列を適当な名詞に代入しておく。
t =. i. 1000
さて、次に3もしくは5の倍数になっている数を取り出して、そ...
ということはまず、どれが3もしくは5の倍数かを判断する必要...
ここではまず3の倍数から考えていく。
3の倍数ということは、3で割った余りが0になるということなの...
動詞 | を使って余りを求めた結果が0ならば3の倍数ということ...
比較の動詞には = (イコール)を使う。二項が等しければ1、等...
0 = 3 | t
1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ...
次に、上のアレイの 1 に対応する部分だけを t から取り出せ...
ここではその為に動詞 # を二項動詞として使う。
二項動詞としての # は「コピー」の動作を行う。~
左辺のアレイの要素の値ぶん、右辺の要素を繰り返す。まずは...
3 # 1 NB. 1 を 3回繰り返す
1 1 1
1 2 3 # 4 5 6 NB. 4 5 6 をそれぞれ 1 2 3回繰り返す
4 5 5 6 6 6
1 1 0 0 1 1 # 1 2 3 4 5 6 NB. 0 の部分は繰り返され...
1 2 5 6
これを使えば、 t から3の倍数だけを取り出すことができる。
(0 = 3 | t) # t
0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 ...
同じようにして、 t から5の倍数だけを取り出すと
(0 = 5 | t) # t
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 ...
残った作業は
+ 二つのアレイを連結
+ 重複する要素(つまり15の倍数)を一つにする
+ 総和を計算する
となる。
まず、二つのアレイを連結するには動詞 , (カンマ)を使う。
((0 = 3 | t) # t) , (0 = 5 | t) # t
0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 ...
重複する要素を一つにするのは結構難しいと思うかもしれないが~
幸運なことに、Jにはその作業を行ってくれる動詞 ~. がある。
~. ((0 = 3 | t) # t) , (0 = 5 | t) # t
0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 ...
後はこれをすべて加算すればおk。~
副詞 / の力を借りて
+/ ~. ((0 = 3 | t) # t) , (0 = 5 | t) # t
233168
纏めると
+/ ~. ((0 = 3 | t) # t) , (0 = 5 | t) # t =. i. 1000
また、ちょっと狡賢く頭を働かせれば、以下のようにも書ける。~
ぜひ解読にチャレンジしてみてほしい。
+/ ~. (3 * i. 334) , 5 * i. 200
*** Problem 2 [#j80272d1]
- [[Problem 2 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>フィボナッチ数列の項は前の2つの項の和である。 最初の2項...
> 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
>数列の項が400万を超えない範囲で、偶数の項の総和を求めよ。
>Note:この問題は最近更新されました。お使いのパラメータが...
よくあるフィボナッチ数列を使った問題。~
数列をどんどん求めていくので、フィボナッチ数列の第n項が求...
ちょうどWikipediaに[[フィボナッチ数 - 一般項>http://ja.wi...
そこにある式によると黄金比を使ってフィボナッチ数列の第n項...
というわけでまずは黄金比を定義してみる。~
φ≡(1 + √5)/2 ということで、平方根を求める必要がある。~
平方根は動詞 %: によって求めることができる。~
また、二で割るということは、値を半分にするのと同じなので...
phi =. -: 1 + %: 5
phi
1.61803
次にこれを使ってフィボナッチ数列の第n項を求める動詞を書く...
ここで注意しなければならないのは、Wikipediaの式は第0項と...
この問題の場合は 1, 2と定義されている。~
二つの数列をよく見ると、問題の数列の第n項とWikipediaの数...
つまり、引数よりも二つ右隣の項を計算すればいいことになる。~
これをもとに動詞を定義すると
fib =: 3 : '<. 0.5 + (phi ^ y + 2) % %: 5'
となる。未解説の動詞の説明をすると
- 動詞 ^ ・・・ 累乗の計算をする
- 動詞 <. ・・・ 床関数、つまり切り捨ての計算をする
Wikipediaの式と見比べて、解読に挑戦してほしい。
さて、これでフィボナッチ数は求められるようになった。~
次は400万までの数列を作り出し、偶数だけを取り出し、総和を...
まず400万までの数列を作るには、適当な数まで数列を作ってお...
そこから400万に満たない数だけを取り出せばいい。取り出す作...
f =. fib i.40 NB. 適当な数までのフィボナッチ数列
(4e6 > f) # f
1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 ...
比較の動詞 > を使っている。これは見たまま「より大きいかど...
次にそのアレイからさらに偶数だけを取り出したい。~
偶数は2で割った余りが0な数なわけだから、Problem 1と同様の...
g =. (4e6 > f) # f
(0 = 2 | g) # g
2 8 34 144 610 2584 10946 46368 196418 832040 3524578
あとはこれらの総和を求めればいいわけだから
+/ (0 = 2 | g) # g
4613732
纏めると
phi =. -: 1 + %: 5
fib =: 3 : '<. 0.5 + (phi ^ y + 2) % %: 5'
+/ (0 = 2 | g) # g =. (4e6 > f) # f =. fib i.40
*** Problem 3 [#w88cc810]
- [[Problem 3 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>13195 の素因数は 5、7、13、29 である。
>600851475143 の素因数のうち最大のものを求めよ。
今度は素因数分解、しかも巨大な数を素因数分解する問題。~
かなりややこしそうだし、かなり難しそうに感じるかもしれな...
だが、そこを何とかしてくれるのがJ言語である。
これはもう8割反則だが、Jには''素因数分解を行ってくれる動...
その動詞は q: 。~
q: は素因数をアレイにして返すので、後は最大値をとればいい...
JにとってはProblem 3なんて朝飯前なわけだ。
q:600851475143
71 839 1471 6857
最大値をとるには次の動詞をうまく使ってやる。
- >. ・・・ 二項を比較して、大きい方の値を返す
二項を比較して大きい方を返すわけだから、例えば「5 9 3 1 6...
5 >. 9 >. 3 >. 1 >. 6
9
という風に、全要素に対して <. をかけてやればいい。~
ここで副詞 / の存在を思い出した奴は天才。~
副詞 / を使って全要素に <. を挿入すれば最大値が得られる。
>./ q:600851475143
6857
*** Problem 4 [#l99db569]
- [[Problem 4 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>左右どちらから読んでも同じ値になる数を回文数という。 2桁...
>では、3桁の数の積で表される回文数のうち最大のものはいく...
まあこれは所謂総当りで解けるだろう。~
問題は、以下の二つになる。
- 3桁の数の積の表をどう作るか?
- 回文数をどう判断するか?
というわけでまずは、3桁の数の積の表をどう作るかを考えよう...
まず、3桁の数をすべて用意する。
100 + i.900
100 101 102 103 104 105 106 107 108 109 110 ...
で、これを使って積の表を作りたいわけだが、~
表を作るには副詞 / を使う。
ここで注目すべきことは、副詞も単項と二項で動作が異なると...
副詞 / は単項の場合は「挿入」だったが、二項の場合は「表」...
副詞 / を二項で使った場合の例を見てみよう。
2 3 4 */ 3 4 5 6 NB. 2 3 4と3 4 5 6の積の表
6 8 10 12
9 12 15 18
12 16 20 24
これを使って、3桁の数の積の表が作れる。
(100 + i.900) */ 100 + i.900
これでまあおkなんだが、このコードをよく見ると */ の二項...
これでは何だかスマートじゃないし、見てくれもあまりよくな...
そこで、 */ に更に副詞 ~ を追加する。~
副詞 ~ は、単項を二項に拡張する。どういうことかと言うと、...
(ここで、 f は適当な動詞、 y は適当な名詞)
f~ y → y f y
つまり、 ~ を適用した動詞に引数を一個与えると、それが二個...
これは二項に同じ値がくるときに使うことができる。~
よって、先ほどの3桁の数の積の表は以下のように短縮すること...
*/~ 100 + i.900
次に、回文数の判定をしたいと思う。~
回文数は逆に並べても同じになる数のことだから、実際に逆に...
ここで、逆にするのを簡単にするために、数値を文字列化した...
値の文字列化には動詞 ": を使う。
kaibun =: ": NB. とりあえず文字列化だけしてみる
次に、これを反転したものと比較したい。~
文字列やアレイを反転するのには動詞 |. を使う。~
で、次に比較だが、動詞 = は文字単位で比較するので使えない...
文字列やアレイ全体が全く同じかどうかを比較するには動詞 -:...
1 2 3 = 3 2 1
0 1 0
1 2 3 -: 3 2 1
0
'abcd' = 'abcd'
1 1 1 1
'abcd' -: 'abcd'
1
動詞 |. で反転したものと、元の文字列を比較するというコー...
フックを利用して以下のように書ける。ぜひ解読にチャレンジ...
(-: |.)
で、これを動詞 kaibun に組み込みたいわけだが、~
そのまま kaibun に入れてしまうと既にある ": とフックを起...
こちらの思惑としては ": で文字列化した結果を、 (-: |.)で...
フックを起こされてしまうとこれができない。
そこで使うのが接続詞 @ である。~
@ の動作は以下のように定義されている。
(f, gは適当な動詞、yは適当な名詞)
f @ g y → f g y
何も変わっていないように見えるが、これを使った例を見てほ...
f =: % @ -:
g =: % -:
f 1 2 3 4
2 1 0.666667 0.5
g 1 2 3 4
2 2 2 2
@ を使用した動詞 f では、 % と -: が''フックを起こさず''、~
値を半分にして、その逆数をとっている。~
一方使用しなかった動詞 g では、 % と -: がフックを起こし、~
「値÷値の半分」つまり2を返す動詞になっている。~
これを使えば、 ": と (-: |.) でフックを起こさないコードを...
kaibun =: (-: |.) @ ":
kaibun 234
0
kaibun 9009
1
ところが、この動詞はこのままだとアレイには適用できない。~
なぜならアレイを渡すと、アレイを丸ごと文字列化して、アレ...
アレイの各要素が回文数かどうかを判定してくれない。~
そこで、接続詞 " を使う。
接続詞 " は「動詞 " 数値」という使い方をし、~
動詞が影響する''列''を、数値によって指定できる。~
列といっても分かりにくいが、以下の例を見てほしい。
t =. 3 4 $ i.12
t
0 1 2 3
4 5 6 7
8 9 10 11
+/ t NB. 縦方向に和が求められる(+/ "1 tとしても動...
12 15 18 21
+/ "2 t NB. 横方向に和が求められる
6 22 38
+/ "0 t NB. 各要素ごとに和が求められる(何もしない)
0 1 2 3
4 5 6 7
8 9 10 11
"0 と指定した例では、各要素ごとに +/ としているが、~
当然意味がないので値はそのままである。
そこで動詞 kaibun に接続詞 " で0を指定してやれば、~
アレイの各要素に kaibun が作用することになるから~
アレイの各要素が回文数かそうでないかを判定することができ...
kaibun 123 45654 2002 1010
0
kaibun"0 (123 45654 2002 1010) NB. 0 がアレイの一部...
0 1 1 0
で、これでいよいよ出来るか、と思ったがまだ問題がひとつあ...
さっき作った3桁の数の積の表は二次元以上のものなので、kaib...
そこで、二次元以上の表を単純なアレイにするために動詞 , を...
t =. 3 3 $ i.9
t
0 1 2
3 4 5
6 7 8
, t
0 1 2 3 4 5 6 7 8 9
さて、これでProblem 4を解くために必要な知識は全て得られた...
後は纏めのコードだけ置いておくので、残りの解読にチャレン...
kaibun =: (-: |.) @ ":
>./ (kaibun"0 t) # t =. , */~ 100 + i.900
ちなみにこの纏めのコードの空白を省いて、更にフック、フォ...
Jの難解さがより際立つコードになる。
>./(((-:|.)@":)"0#]),*/~i.1000
こっちの解読もやってみるといいかも。難解なコードを読める...
終了行:
#contents
* J [#w69ef1bc]
J、その可読性の低さゆえ全く流行していないプログラミング言...
* まずはJをゲット [#x9b7b79a]
Jの処理系は[[Jsoftware>http://www.jsoftware.com/]]で配布...
Download→Stableからそれぞれの環境にあった処理系のインスト...
インストーラでは、一人で使うのか、それともPCのユーザー全...
これは人それぞれ自由に選んでおk。~
一人で使う場合はそのユーザのホームフォルダに、全員で使う...
* Jに触ってみる [#u1786b04]
** Jの起動 [#oc3780d4]
Jの処理系は、Jがインストールされたディレクトリから~
./bin/j.exe~
と辿ったところにあるので起動する。
Jの処理系は対話型なので、プログラムを入力するとその場で実...
これを使ってJを高性能かつ簡単な電卓として使うこともできる。
** Hello, world! [#td4009da]
Jでは、文字列は''(シングルクォーテーション)で囲ったもので...
また、文字列を入力するとそのまま返すので、Hello, world!プ...
'Hello, world!'
上の通りにJに入力してやると、Hello, world!という表示が返...
Jの窓は以下のような状態になっているはず。
'Hello, world!'
Hello, world!
このように、Jでは入力を半角スペース三つ分インデントして表...
また出力は行頭から表示される。~
以降に示すサンプルも全てこれに則って書いてあるので~
実際に試すときはインデントされている部分だけを入力すれば...
** 呼称について [#e707e479]
例えば普通のプログラミング言語の場合、以下のプログラムで...
int a = 10;
printf("%d\n", a + 10)
だがJの場合、演算子とか関数とか言った呼称は用いず、次のよ...
- 演算子、関数 → 動詞
- 定数、変数 → 名詞
ほかにも、動詞の動作に影響を与える副詞、品詞同士をつなぐ...
余談だがこのように自然言語っぽい呼び方をする所は俺大好き。
* まずは簡単な計算から [#d62311d2]
** 四則演算+α [#bc98a58a]
まず加算減算乗算除算そして剰余を求める計算をやってみる。~
加算減算乗算を行う動詞はそのまんま、+と-と*。
5 + 3
8
7 - 4
3
6 * 5
30
除算の動詞は % を使う。~
普通の言語だと除算は / で、剰余が % とかいうことが多いけ...
Jでは除算が % なので間違ったりこんがらがったりしないよう...
16 % 8
2
5 % 2
2.5
13 % 7
1.85714
で、剰余(あまりを求める)の動詞は | (縦線)。~
注意しなきゃいけないのは、剰余を求めようとして「x | y」と...
「xをyで割ったときのあまり」ではなく''「yをxで割ったとき...
名詞の順番を間違えないように。
5 | 13
3
2 | 30
0
とりあえず理解確認のために以下の問題を解いてみようか。
- 123×456をJ言語で求めてください
- 98÷17をJ言語で求めてください
- 200を21で割ったあまりを求めてください
答がそれぞれ56088、5.76471、11になったら読み進めよう。~
ならなかったら読み直せ。
** 数値リテラル [#n621dd07]
一口に数といってもいろいろある。~
整数、小数、正の数、負の数、実数、複素数・・・~
それらの数を表現するための方法が幾つかある。
*** 指数表現 [#t55b0cd8]
とても大きい数やとても小さい数を表すのに使う「x * 10のy乗...
「x * ''10''のy乗」ということで、10を底とした指数表現にな...
たとえば「13000000000」は「1.3*10の10乗」で''「1.3e10」''...
1.3 * 10000000000
1.3e10
1.2345e5
123450
*** 負の数 [#qa2e1595]
負の数はふつう「-」(マイナス)の符号をつけるが~
Jの場合は少し違う。Jで負数を表すには _ (アンダースコア)を...
3 - 5
_2
_3 + 9
6
_5 * 4
_20
*** 無限・未定義 [#y81803e2]
数が大きすぎたり、定義されない値をとった場合の表現の仕方...
まあ普通、ほとんど使わない。~
無限は _ (アンダースコア)、未定義は _. (アンダースコアと...
無限と負数の表現が同じだけれども、無限の場合はアンダース...
負数の場合は数も書くので区別できる。~
ちなみに、アンダースコアを二つ繋げるとマイナス無限大を表...
1.2345e999 * 6.789e999
_
_. * 123 + 456 - 789 % 999
_.
_1 * _
__
*** その他 [#n8de987a]
その他にも複素数とか分数とかあるけどまあ後々説明する。
** 優先順位 [#oa012429]
優先順位は数学と同じ、''なんて甘いことを言っちゃいかん。''~
だからといって複雑な順位が決められてるわけでもなく、~
''右から順番に計算''されるだけ。つまり、
1 - 2 - 3 - 4
_2
こうなる。~
「1 - 2 - 3 - 4」は「1 - (2 - (3 - 4))」になるので答はマ...
というわけで確認問題
- 「10 - 3 + 3」がどのような答になるか予測して、J言語で実...
- 「2 * 3 - 4」がどのような答になるか予測して、J言語で実...
- 「0.3 * 20 - 10」がどのような答になるか予測して、J言語...
予測と実際の答が合っていれば読み進めよう。~
合ってなかったら読み直せ。
** 単項と二項 [#o6d3e273]
Jの動詞は単項で使った場合(動詞の右にだけ名詞がくる)と~
二項で使った場合(動詞の左右両方に名詞がくる)場合で全く異...
詳しい挙動については後々品詞一覧で述べようと思うが~
代表的なものを挙げておこうと思う。
「*」は単項だと符号の判定、二項だと乗算になる。
2 * 4
8
3 * 5
15
* 3
1
* _12
_1
* 0
0
「|」は単項だと絶対値、二項だと剰余になる。
3 | 15
0
4 | 22
2
| 50
50
| _13
13
| 0
0
この単項と二項の使い分けはJのコードを読む上でとても重要だ...
単項と二項で動作が変わるということは覚えておいてほしい。
* コメント [#tecae16a]
コメントは「NB.」でつけることができる。
NB.以降は行末までがコメントになる。
3 * 5 + 6 NB. 5と6を足して3倍する
33
* アレイ [#vc22a891]
** アレイの基本 [#jfbdf907]
Jでは沢山の値を纏めて扱うことができる。~
他の言語でいう配列のようなものをアレイと呼ぶ。~
アレイを定義するには、数値同士を半角空白で区切ればいい。~
アレイ同士の演算も可能である。
1 2 3 + 4 5 6
5 7 9
1 2 3 * 6 5 4
6 10 12
アレイ同士で演算を行う場合、両方の長さが等しくなければな...
長さの等しくないアレイ同士で演算を行おうとすると、length ...
1 2 3 4 + 5 6
|length error
| 1 2 3 4 +5 6
また、アレイと単一の名詞との演算もできる。
1 2 3 + 5
6 7 8
1 2 3 * 10
10 20 30
** アレイの操作 [#h29a9f16]
アレイの要素数は動詞 # (シャープ)で求めることができる。
# 1 2 3
3
# 1 2 3 4 5 6 7 8 9 10
10
0から指定された値 - 1までのアレイを作る動詞 i. (イオタ)と...
i. 10
0 1 2 3 4 5 6 7 8 9
5 + i. 10
5 6 7 8 9 10 11 12 13 14
# i. 10
10
** アレイの整形 [#j2556f87]
動詞 $ (ドル)を使うと、アレイを整形することができる。~
整形する場合、$は二項動詞として用い、左に形、右に値をもっ...
二次元以上のものを作り出すことができる。
3 4 $ i. 12 NB. 3 * 4のテーブルの形に i. 12 を整形...
0 1 2 3
4 5 6 7
8 9 10 11
2 4 $ 1 2 3 NB. 要素が足りない場合は繰り返される
1 2 3 1
2 3 1 2
3 3 $ i.100 NB. 要素が余る場合は切り捨てられる
0 1 2
3 4 5
6 7 8
* 副詞を使ってみる [#se546a3d]
副詞は、動詞の動作に影響するもので、使いようによってはか...
とりあえず一番よく使うであろう副詞 / (スラッシュ)の説明を...
まず副詞はどうやって使うかというと、動詞の直後につけて使...
動詞 + に副詞 / をつけると +/ となる。~
この場合、 +/ という新しい動詞ができたと考えた方が簡単。
で、この副詞 / というものの効果は「挿入」(もちろん性的な...
「挿入」というのはアレイの各要素の間にその動詞を挿入する...
「+/ 1 2 3 4 5」という文は「1 + 2 + 3 + 4 + 5」と解釈され...
つまり +/ というのはアレイの要素の合計を求める新しい動詞...
これを使えば、1~100までの自然数の和を求めるプログラムだ...
+/ i. 101
5050
* フックとフォーク [#yc0eb80b]
さて、それではJ言語の一番の特徴である「動詞の合成」の説明...
ここは結構複雑だから一気に理解しようとせずに、ゆっくり理...
** フック [#g5488e75]
フックは動詞二つを合成するときの決まりで、以下のようにな...
(f, gは動詞、x, yは名詞)
(f g) y → y f g y
x (f g) y → x f g y
まず単項の場合、動詞gを単項動詞としてyを与えて評価させる。~
そして動詞fを二項動詞として「g y」の値と、元のyを与えて評...
(+ *) 5
6
この場合、まず動詞*に5が渡されて「* 5」が評価される。~
単項*動詞は符号の判定なので、「* 5」は1となる。~
次に動詞+に 1 と 5 が渡され、結果は6となる。
二項の場合、最後の動詞fに渡す名詞がyではなくxになるだけで...
単項の場合の動作が分かれば簡単に理解することができる。
** フォーク [#ad981d8b]
フォークは動詞三つを合成するときの決まりで、以下のように...
(f, g, hは動詞、x, yは名詞)
(f g h) y → (f y) g h y
x (f g h) y → (x f y) g x h y
まず単項の場合、動詞fとhにyを与えて評価し、~
その結果の二つ値をgに与えて評価させる。例えば
(+/ % #) 3 5 7 9
6
この場合、
- f = +/
- g = %
- h = #
- y = 3 5 7 9
となるから、
(+/ 3 5 7 9) % # 3 5 7 9
と解釈される。~
#はアレイの要素数を求めるので 4 (これが「h y」の値)~
+/はアレイの要素の合計を求めるので 24 (これが「f y」の値)~
よって、
24 % 4
になるから、答は6となる。~
合計を要素数で割る操作、つまりこれは平均を求めていること...
フォークをうまく使うことで、平均を求める操作を (+/ % #) ...
** トレイン [#r8ec94dc]
四つ以上の動詞の合成時の決まりで、これはフックとフォーク...
例えば、四つの動詞a, b, c, dを合成するときは
(a b c d) → (a (b c d))
となり、右から三つ b, c, d でフォークが起きる。~
その結果と a でフックが起きる。
トレインの合成規則はかなり複雑になるが、所詮フックとフォ...
フックとフォークを理解できていれば読むのは難しくはない。
* 代入と定義 [#r9653681]
Jでは、代入の操作を行うことによって、名詞や動詞などを定義...
代入には二種類あって、 =. (ローカル)、 =: (グローバル) が...
** ローカル [#m48dd72f]
ローカルな代入は、その範囲内でしか利用しない単語の定義に...
例えば以下の例では、名詞 a は動詞 test 内でしか利用できな...
(3 : 0の意味などについては後述する。)
test =: 3 : 0 NB. 動詞の定義
a =. y
2 * a
)
** グローバル [#m74a5c92]
グローバルな代入は、あらゆる場所でその単語を利用すること...
例えば以下の例では、動詞の定義外で定義された名詞を動詞の...
global =: 0
test2 =: 3 : 0
global =: global + 1
)
** 名詞の定義 [#t634f696]
名詞を定義するのは簡単で、代入の動詞を使えばおk。
a =. 5
a NB. a の値を表示する
5
すべての文は右から評価されるから、名詞の内容に文をもって...
それが評価されて、名詞に代入されることになる。
b =. 5 + i. 10
b
5 6 7 8 9 10 11 12 13 14
名詞どうしの演算もできるし、名詞を使った演算の結果を別の...
c =. 10
d =. i. 5
c + d
10 11 12 13 14
e =. c * d
e
0 10 20 30 40
** 動詞の定義 [#z411061c]
動詞といっても、単項と二項があって~
さらに二種類の定義方法が存在する。
*** 暗黙(Tacit)の定義 [#i38b4df0]
暗黙の定義では引数といったものは存在せず、~
ただ動詞の中身が展開されるだけである。~
一番簡単な暗黙の定義を見てみよう。
plus =: +
これを使うコードは例えば以下のようになる。
10 plus 20
30
つまり、コードは以下のように展開されたことになる。
10 plus 20 → 10 (+) 20
暗黙の定義は、括弧つきで展開されるのと同等なので~
動詞の合成を効果的に使うことができる。
avg =: +/ % # NB. 平均を求める
avg 10 15 22 34 42
24.6
このコードは以下のように展開されたことになる。
avg 10 15 22 34 42 → (+/ % #) 10 15 22 34 42
*** 明示的(Explict)な定義 [#y1f435ff]
明示的な定義は、引数を受け取って値を返すという動作を明確...
引数は単項か二項かによって数が変わるため、~
定義する時点で単項動詞か二項動詞かを明示しておく必要があ...
(暗黙の定義は展開されるだけなので明示の必要はない。)
動詞の種類の明示には、接続詞 : (コロン)を使う。~
: の左に動詞の種類、右に動詞の中身を''文字列''として記述...
例えばさっきの加算を行う動詞 plus を明示的な定義で書き直...
plus =: 4 : 'x + y'
まず、 4 というのが二項動詞の明示である。~
で、動詞の左側に置かれる引数が x 、右側に置かれる引数が y...
次に、平均を求める動詞を明示的な定義で書き直してみる。
avg =: 3 : '(+/ y) % # y' NB. もちろん合成も使える...
さて、定義したい動詞が長いと、どうしても一行じゃ読みにく...
そこで、接続詞 : の右側に 0 を持ってくると複数行の動詞を...
test =: 3 : 0
y + y
)
複数行の動詞の定義は ) で終了する。
*** 暗黙の定義と明示的な定義 [#c1ee296c]
上の二つの例(動詞 plus, avg)でも分かる通り、~
明示的な定義の方が長く、冗長になりがちだが、暗黙の定義は...
どちらを使うかは好みだろうが、明示的な定義の方が定義しや...
一方暗黙の定義はスマートで、こちらの方がJの特色をより反映...
なのでどちらを使ったほうがいいというものはないから、好み...
ここでもう一つ、動詞の定義方法を紹介しようと思う。~
でもまあ新しいわけではなく、明示的な定義を暗黙の定義に変...
明示的な定義を暗黙の定義に変換するには、接続詞 : の左側に...
fx =: 3 : '32 + y * 9 % 5' NB. 摂氏を華氏に変換する
ft =: 13 : '32 + y * 9 % 5' NB. 摂氏を華氏に変換す...
ここで動詞の中身を見てみると
fx
3 : '32 + y * 9 % 5'
ft
32 + 1.8 * ]
となり、ftの方が暗黙の定義に変換されているのが分かる。
* さあプログラムを書こう [#c2e33b68]
これまでで大体Jの基本は抑えられたと思う。~
後は語彙の問題で、どんな単語があって、どんな動作をするの...
これを覚えていけばいいだけ。~
ただ、語彙はけっこう豊富だし、それも記号の羅列になるから...
増してや勉強感覚で覚えようと思っても身につくわけがない。~
だからここからは、ひたすらたくさんプログラムを書いて、~
その中で語彙を増やしていってほしいと思う。
ちなみに単語の一覧表はJsoftwareの[[Vocabulary>http://www....
ブックマークに突っ込むなり何なりしておくと便利だと思う。
英語が読める人はJsoftwareからWikiを辿って色々な文章を読ん...
** Project Euler [#vcf633d5]
さて、書くプログラムのお題だが、ここではJの得意な数学分野...
Project Eulerの問題は英語で書かれているが、[[Project Eule...
*** Problem 1 [#r8c7728a]
- [[Problem 1 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>10未満の自然数のうち、3 もしくは 5 の倍数になっているも...
>同じようにして、1,000 未満の 3 か 5 の倍数になっている数...
まず、1000未満の数ということなので、999までの数列を用意す...
これは前に説明した i. (イオタ)を使えば簡単にできる。~
とりあえず数列を適当な名詞に代入しておく。
t =. i. 1000
さて、次に3もしくは5の倍数になっている数を取り出して、そ...
ということはまず、どれが3もしくは5の倍数かを判断する必要...
ここではまず3の倍数から考えていく。
3の倍数ということは、3で割った余りが0になるということなの...
動詞 | を使って余りを求めた結果が0ならば3の倍数ということ...
比較の動詞には = (イコール)を使う。二項が等しければ1、等...
0 = 3 | t
1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 ...
次に、上のアレイの 1 に対応する部分だけを t から取り出せ...
ここではその為に動詞 # を二項動詞として使う。
二項動詞としての # は「コピー」の動作を行う。~
左辺のアレイの要素の値ぶん、右辺の要素を繰り返す。まずは...
3 # 1 NB. 1 を 3回繰り返す
1 1 1
1 2 3 # 4 5 6 NB. 4 5 6 をそれぞれ 1 2 3回繰り返す
4 5 5 6 6 6
1 1 0 0 1 1 # 1 2 3 4 5 6 NB. 0 の部分は繰り返され...
1 2 5 6
これを使えば、 t から3の倍数だけを取り出すことができる。
(0 = 3 | t) # t
0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 ...
同じようにして、 t から5の倍数だけを取り出すと
(0 = 5 | t) # t
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 ...
残った作業は
+ 二つのアレイを連結
+ 重複する要素(つまり15の倍数)を一つにする
+ 総和を計算する
となる。
まず、二つのアレイを連結するには動詞 , (カンマ)を使う。
((0 = 3 | t) # t) , (0 = 5 | t) # t
0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 ...
重複する要素を一つにするのは結構難しいと思うかもしれないが~
幸運なことに、Jにはその作業を行ってくれる動詞 ~. がある。
~. ((0 = 3 | t) # t) , (0 = 5 | t) # t
0 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 ...
後はこれをすべて加算すればおk。~
副詞 / の力を借りて
+/ ~. ((0 = 3 | t) # t) , (0 = 5 | t) # t
233168
纏めると
+/ ~. ((0 = 3 | t) # t) , (0 = 5 | t) # t =. i. 1000
また、ちょっと狡賢く頭を働かせれば、以下のようにも書ける。~
ぜひ解読にチャレンジしてみてほしい。
+/ ~. (3 * i. 334) , 5 * i. 200
*** Problem 2 [#j80272d1]
- [[Problem 2 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>フィボナッチ数列の項は前の2つの項の和である。 最初の2項...
> 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
>数列の項が400万を超えない範囲で、偶数の項の総和を求めよ。
>Note:この問題は最近更新されました。お使いのパラメータが...
よくあるフィボナッチ数列を使った問題。~
数列をどんどん求めていくので、フィボナッチ数列の第n項が求...
ちょうどWikipediaに[[フィボナッチ数 - 一般項>http://ja.wi...
そこにある式によると黄金比を使ってフィボナッチ数列の第n項...
というわけでまずは黄金比を定義してみる。~
φ≡(1 + √5)/2 ということで、平方根を求める必要がある。~
平方根は動詞 %: によって求めることができる。~
また、二で割るということは、値を半分にするのと同じなので...
phi =. -: 1 + %: 5
phi
1.61803
次にこれを使ってフィボナッチ数列の第n項を求める動詞を書く...
ここで注意しなければならないのは、Wikipediaの式は第0項と...
この問題の場合は 1, 2と定義されている。~
二つの数列をよく見ると、問題の数列の第n項とWikipediaの数...
つまり、引数よりも二つ右隣の項を計算すればいいことになる。~
これをもとに動詞を定義すると
fib =: 3 : '<. 0.5 + (phi ^ y + 2) % %: 5'
となる。未解説の動詞の説明をすると
- 動詞 ^ ・・・ 累乗の計算をする
- 動詞 <. ・・・ 床関数、つまり切り捨ての計算をする
Wikipediaの式と見比べて、解読に挑戦してほしい。
さて、これでフィボナッチ数は求められるようになった。~
次は400万までの数列を作り出し、偶数だけを取り出し、総和を...
まず400万までの数列を作るには、適当な数まで数列を作ってお...
そこから400万に満たない数だけを取り出せばいい。取り出す作...
f =. fib i.40 NB. 適当な数までのフィボナッチ数列
(4e6 > f) # f
1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 ...
比較の動詞 > を使っている。これは見たまま「より大きいかど...
次にそのアレイからさらに偶数だけを取り出したい。~
偶数は2で割った余りが0な数なわけだから、Problem 1と同様の...
g =. (4e6 > f) # f
(0 = 2 | g) # g
2 8 34 144 610 2584 10946 46368 196418 832040 3524578
あとはこれらの総和を求めればいいわけだから
+/ (0 = 2 | g) # g
4613732
纏めると
phi =. -: 1 + %: 5
fib =: 3 : '<. 0.5 + (phi ^ y + 2) % %: 5'
+/ (0 = 2 | g) # g =. (4e6 > f) # f =. fib i.40
*** Problem 3 [#w88cc810]
- [[Problem 3 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>13195 の素因数は 5、7、13、29 である。
>600851475143 の素因数のうち最大のものを求めよ。
今度は素因数分解、しかも巨大な数を素因数分解する問題。~
かなりややこしそうだし、かなり難しそうに感じるかもしれな...
だが、そこを何とかしてくれるのがJ言語である。
これはもう8割反則だが、Jには''素因数分解を行ってくれる動...
その動詞は q: 。~
q: は素因数をアレイにして返すので、後は最大値をとればいい...
JにとってはProblem 3なんて朝飯前なわけだ。
q:600851475143
71 839 1471 6857
最大値をとるには次の動詞をうまく使ってやる。
- >. ・・・ 二項を比較して、大きい方の値を返す
二項を比較して大きい方を返すわけだから、例えば「5 9 3 1 6...
5 >. 9 >. 3 >. 1 >. 6
9
という風に、全要素に対して <. をかけてやればいい。~
ここで副詞 / の存在を思い出した奴は天才。~
副詞 / を使って全要素に <. を挿入すれば最大値が得られる。
>./ q:600851475143
6857
*** Problem 4 [#l99db569]
- [[Problem 4 - PukiWiki>http://odz.sakura.ne.jp/projecte...
>左右どちらから読んでも同じ値になる数を回文数という。 2桁...
>では、3桁の数の積で表される回文数のうち最大のものはいく...
まあこれは所謂総当りで解けるだろう。~
問題は、以下の二つになる。
- 3桁の数の積の表をどう作るか?
- 回文数をどう判断するか?
というわけでまずは、3桁の数の積の表をどう作るかを考えよう...
まず、3桁の数をすべて用意する。
100 + i.900
100 101 102 103 104 105 106 107 108 109 110 ...
で、これを使って積の表を作りたいわけだが、~
表を作るには副詞 / を使う。
ここで注目すべきことは、副詞も単項と二項で動作が異なると...
副詞 / は単項の場合は「挿入」だったが、二項の場合は「表」...
副詞 / を二項で使った場合の例を見てみよう。
2 3 4 */ 3 4 5 6 NB. 2 3 4と3 4 5 6の積の表
6 8 10 12
9 12 15 18
12 16 20 24
これを使って、3桁の数の積の表が作れる。
(100 + i.900) */ 100 + i.900
これでまあおkなんだが、このコードをよく見ると */ の二項...
これでは何だかスマートじゃないし、見てくれもあまりよくな...
そこで、 */ に更に副詞 ~ を追加する。~
副詞 ~ は、単項を二項に拡張する。どういうことかと言うと、...
(ここで、 f は適当な動詞、 y は適当な名詞)
f~ y → y f y
つまり、 ~ を適用した動詞に引数を一個与えると、それが二個...
これは二項に同じ値がくるときに使うことができる。~
よって、先ほどの3桁の数の積の表は以下のように短縮すること...
*/~ 100 + i.900
次に、回文数の判定をしたいと思う。~
回文数は逆に並べても同じになる数のことだから、実際に逆に...
ここで、逆にするのを簡単にするために、数値を文字列化した...
値の文字列化には動詞 ": を使う。
kaibun =: ": NB. とりあえず文字列化だけしてみる
次に、これを反転したものと比較したい。~
文字列やアレイを反転するのには動詞 |. を使う。~
で、次に比較だが、動詞 = は文字単位で比較するので使えない...
文字列やアレイ全体が全く同じかどうかを比較するには動詞 -:...
1 2 3 = 3 2 1
0 1 0
1 2 3 -: 3 2 1
0
'abcd' = 'abcd'
1 1 1 1
'abcd' -: 'abcd'
1
動詞 |. で反転したものと、元の文字列を比較するというコー...
フックを利用して以下のように書ける。ぜひ解読にチャレンジ...
(-: |.)
で、これを動詞 kaibun に組み込みたいわけだが、~
そのまま kaibun に入れてしまうと既にある ": とフックを起...
こちらの思惑としては ": で文字列化した結果を、 (-: |.)で...
フックを起こされてしまうとこれができない。
そこで使うのが接続詞 @ である。~
@ の動作は以下のように定義されている。
(f, gは適当な動詞、yは適当な名詞)
f @ g y → f g y
何も変わっていないように見えるが、これを使った例を見てほ...
f =: % @ -:
g =: % -:
f 1 2 3 4
2 1 0.666667 0.5
g 1 2 3 4
2 2 2 2
@ を使用した動詞 f では、 % と -: が''フックを起こさず''、~
値を半分にして、その逆数をとっている。~
一方使用しなかった動詞 g では、 % と -: がフックを起こし、~
「値÷値の半分」つまり2を返す動詞になっている。~
これを使えば、 ": と (-: |.) でフックを起こさないコードを...
kaibun =: (-: |.) @ ":
kaibun 234
0
kaibun 9009
1
ところが、この動詞はこのままだとアレイには適用できない。~
なぜならアレイを渡すと、アレイを丸ごと文字列化して、アレ...
アレイの各要素が回文数かどうかを判定してくれない。~
そこで、接続詞 " を使う。
接続詞 " は「動詞 " 数値」という使い方をし、~
動詞が影響する''列''を、数値によって指定できる。~
列といっても分かりにくいが、以下の例を見てほしい。
t =. 3 4 $ i.12
t
0 1 2 3
4 5 6 7
8 9 10 11
+/ t NB. 縦方向に和が求められる(+/ "1 tとしても動...
12 15 18 21
+/ "2 t NB. 横方向に和が求められる
6 22 38
+/ "0 t NB. 各要素ごとに和が求められる(何もしない)
0 1 2 3
4 5 6 7
8 9 10 11
"0 と指定した例では、各要素ごとに +/ としているが、~
当然意味がないので値はそのままである。
そこで動詞 kaibun に接続詞 " で0を指定してやれば、~
アレイの各要素に kaibun が作用することになるから~
アレイの各要素が回文数かそうでないかを判定することができ...
kaibun 123 45654 2002 1010
0
kaibun"0 (123 45654 2002 1010) NB. 0 がアレイの一部...
0 1 1 0
で、これでいよいよ出来るか、と思ったがまだ問題がひとつあ...
さっき作った3桁の数の積の表は二次元以上のものなので、kaib...
そこで、二次元以上の表を単純なアレイにするために動詞 , を...
t =. 3 3 $ i.9
t
0 1 2
3 4 5
6 7 8
, t
0 1 2 3 4 5 6 7 8 9
さて、これでProblem 4を解くために必要な知識は全て得られた...
後は纏めのコードだけ置いておくので、残りの解読にチャレン...
kaibun =: (-: |.) @ ":
>./ (kaibun"0 t) # t =. , */~ 100 + i.900
ちなみにこの纏めのコードの空白を省いて、更にフック、フォ...
Jの難解さがより際立つコードになる。
>./(((-:|.)@":)"0#]),*/~i.1000
こっちの解読もやってみるといいかも。難解なコードを読める...
ページ名: