APL/J言語でFizzBuzz(つづき)


J言語でFizzBuzz(http://recompile.net/2007/05/jfizzbuzz.html)というところに、satzeさんが

                • -

例えばこんなのどうでしょうか?
' ' (('|' E. B) # i.#B) } B=.}.}:1{":(<'FizzBuzz') (<:(0 E. 15 | A) # A) } (<'Buzz') (<:(0 E. 5 | A) # A) } (<'Fizz') (<:(0 E. 3 | A) # A) } <"0 A=.>:i.100
(1行)

もしくは,
FizzBuzz=: 3 : 0
' ' (('|' E. B) # i.#B) } B=.}.}:1{":(<'FizzBuzz') (<:(0 E. 15 | A) # A) } (<'Buzz') (<:(0 E. 5 | A) # A) } (<'Fizz') (<:(0 E. 3 | A) # A) } <"0 A=.>:i.y.
)
として,
FizzBuzz 100

                • -

と書かれています。これを解析します。J言語ではワンライナーは後ろから読んでいきます。

   i.100      NB.これはご存知0..99の配列作成
   >:i.100   NB.'>:'はデクリメンとで各要素に1を足します。かっこいいですね。
   <"0         NB.これで要素別にボックス作成。"0がないとひとつのボックスになる。

ここまでをまとめると以下のようになります。

   <"0 A=.>:i.100
 +-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+
 |1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|
 +-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+ ...

次が大変参考になったところです。

   (<'Fizz') (

}(みぎブレイス)は左辺の引数を二つとって、右辺の配列について左辺の二つ目で示す場所に左辺の一つ目の引数を代入します。この場合はAを3で割った結果ゼロになる場所にある数字の配列をおのおのデクリメントした場所に'Fizz'というボックスを入れる、という意味になる。同じように'Buzz'も、'FizzBuzz'も処理します。ここまでで、おおかた私の達成したところまでと同様なことをやっている。
次に、冒頭の部分でボックスから外に出しているようです。

   ' ' (('|' E. B) # i.#B) } B=.}.}:1{":

結果は一つの巨大な文字列になります。冒頭に$を置いてみたら412という数字が返って来ました。

   1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz ...

":(クオートコロン)はボックスをボックス描画の線も中の文字列も数字もすべて文字列にしてしまう強力な動詞です。

   ]box=:1;2;'Fizz'
 +-+-+----+
 |1|2|Fizz|
 +-+-+----+
   $box
 3
   $":box
 3 10
   1{":box
 |1|2|Fizz|

{(左ブレイス)は左辺で指定した要素を右辺から取り出しますので、この例ではボックスの切れ目を示すたてぼうがついた状態の行がとりだせました。次に}.}:で前後の一文字を消したものをBに代入します。

   ]B=:}.}:1{":box
1|2|Fizz

この結果のBについて、たてぼうの位置を調べてそこにスペースを代入していくのが残りです。

    ' ' (('|' E. B) # i.#B) } B
1 2 Fizz

うむ。すばらしい。
FizzBuzzという動詞を定義している例についてひと言。

   FizzBuzz 100
 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 ...

となるような単項動詞の定義方法が最近変わっていて、上記のままではエラーになります。定義内の変数yとかに以前はドットをつけていましたが、現在はドットがあるとえらーになります。したがって、正しくは最後のドットを取って、以下のような定義になります。

FizzBuzz=: 3 : 0
 ' ' (('|' E. B) # i.#B) } B=.}.}:1{":(<'FizzBuzz') (<:(0 E. 15 | A) # A) } (<'Buzz') (<:(0 E. 5 | A) # A) } (<'Fizz') (<:(0 E. 3 | A) # A) } <"0 A=.>:i.y
)

以上