LoginSignup
5
2

More than 3 years have passed since last update.

J言語でFizzBuzzを作る

Last updated at Posted at 2020-08-19

はじめに

プログラミング言語 J を使ってFizzBuzzを作ったので、その解説をします。
J言語はとても面白いので、使ってない人もぜひ読んでみてください。

J言語とは

変態の使うプログラミング言語です。ひたすら記号の羅列で、まず読めません。負の数を表すのに_5のように-(ハイフン)ではなく_(アンダースコア)を使ったり、コメントを表すのがNB.だったりと、クセの強い言語です。
そのかわり、慣れてくるとかなり短く記述できる、便利な言語です。配列の処理に優れていて、総和や総乗を求めたり、配列同士で演算したりすることが簡単にできます。対話型で実行でき、手軽さもあります。
マイナーですが、素晴らしい言語です。みんな使うべきです。

※ 個人の感想が含まれています。

実行環境

J言語は、Windows、MacOS、Android、iOSなど、様々なプラットホームで実行できます。
私は J Android を使用してAndroidで実行しています。

J言語の環境は、iOSでなければJ言語のホームページからダウンロードできます。
インストールのページから最新バージョンのリンクに飛び、そのページの Download and Install にあるリンクから、それぞれのプラットホームにあったものをダウンロードし、Jシステムをインストールします。
たとえば、Androidならapkファイルをダウンロードしてインストールできます。

iOSの場合は、AppStoreからインストールできます。
ただし、iOS版はアップデートされておらず、バージョンがだいぶ古いので注意です。

FizzBuzz

J言語でFizzBuzzを作る方法はいろいろありますが、私が作ったFizzBuzzがこちらです。

FizzBuzz.ijs
FizzBuzz=: 'FizzBuzz'&(":@]`(4:{.[)`(4:}.[)`[@.((0:=3:|])++:@(0:=5:|])))&>:&i.

J言語はFizzBuzzを1行で書けます。しかし、パッと見ただけでは何を書いてるのか全然わかりませんね。私もわかりません。

FizzBuzz 15のようにFizzBuzzのうしろに適当な整数をつけて実行すると……

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

ちゃんとFizzBuzzが出力されます。

解説

J言語の品詞

FizzBuzzを解説する前に、少しJ言語の説明をします。
J言語では、ほかの言語で演算子やリテラルと呼ばれているものを、動詞名詞と呼びます。

名詞は、数値や文字列などを指します。たとえば、123'Hello'1 1 2 3 5 8 13 21 34 55(配列)などがあります。

動詞は、関数のように引数を受けて計算するものです。足し算や掛け算などをする記号や文字を指します。
動詞に引数を渡す方法は2つで、(動詞) yのように右から1つ渡す方法と、x (動詞) yのように左右から2つ渡す方法があります。

ほかにも接続詞というものがあります。これは動詞や名詞をつなげて、新たな動詞を作るものです。たとえば、2倍する動詞+:と2乗する動詞*:を接続詞@でつなげて、2乗してから2倍する動詞を作ることができます。

   NB. 6番目の電子殻(P殻)に収用できる電子数
   (+: @ *:) 6
72

副詞というものもあります。これは日本語と同じで、動詞を修飾するものです。たとえば、足し算をする動詞+に、副詞/をつけることで、総和を求める動詞+/を作ることができます。

   NB. 114 + 514 + 191 + _9
   +/ 114 514 191 _9
810

動詞を作る

J言語では、自分で動詞を作ることができます。ほかの言語でいうところの、関数を作るようなことです。
FizzBuzzでは、様々な動詞や名詞、副詞を組み合わせて、FizzBuzzという一つの動詞を作っています。

フォーク

((動詞a) (動詞b) (動詞c))
このように、動詞3つを接続詞なしでつなげて動詞を作ることをフォークといいます。
(フォーク) yというふうに引数を1つ渡した場合は
((動詞a) y) (動詞b) ((動詞c) y)と評価され、動詞aと動詞cがそれぞれ引数を受け取って計算し、計算されたそれぞれの値を動詞bが受け取って計算します。
x (フォーク) yと引数を2つ渡した場合も
(x (動詞a) y) (動詞b) (x (動詞c) y)と評価され、同じように計算されます。

   NB. 並列の合成抵抗
   20 (* % +) 5    NB. 積÷和(%は割り算の動詞)
4

右から処理する

J言語では右から順番に処理します。そのほうがなにかと都合がいいんです。
たとえば、3*3-43-4が先に計算されるので_3になります。

解説

では、FizzBuzzを右から順番に見ていきます。

FizzBuzz =: 'FizzBuzz' & ( ": @ ] ` ( 4: {. [ ) ` ( 4: }. [ ) ` [ @. ( ( 0: = 3: | ] ) + +: @ ( 0: = 5: | ] ) ) ) & >: & i.

i.
0 から (引数)-1 までの整数配列を作る動詞です。

&
動詞と動詞、動詞と名詞を繋げる接続詞です。

>:
インクリメントする動詞です。i.によって作られた0 1 2 ……のような配列を、1 2 3 ……のように、それぞれの要素をインクリメントします。

&
接続詞です。

(":@]`(4:{.[)`(4:}.[)`[@.((0:=3:|])++:@(0:=5:|])))
FizzBuzzしてる部分です。あとで解説します。

&
接続詞です。

'FizzBuzz'
文字列です。FizzBuzzしてる部分の左側の引数になります。

=:
動詞や名詞に名前をつける連結詞です。変数や関数を定義するようなものです。副詞や接続詞などにも名前をつけることができます。

FizzBuzz
=:の右側の動詞の名前です。

つまり、1 から 引数として与えられる整数 までの整数配列と文字列'FizzBuzz'を、FizzBuzzしてる部分の引数として渡す動詞を、FizzBuzzという名前で定義しているということです。

FizzBuzzしてる部分

FizzBuzzしてる部分の解説をします。

( ":@] ` (4:{.[) ` (4:}.[) ` [ @. ((0:=3:|])++:@(0:=5:|])) )

(動詞0) ` (動詞1) ` …… @. (条件)
接続詞の`は、動詞どうしをつなげて動詞の配列を作ります。
また接続詞@.は、左側の動詞の配列から、右側に与えられるインデックスの位置の動詞を返します。

つまりこの構文は、条件の部分が 0 なら動詞0を、1 なら動詞1を、…… というふうに実行します。

FizzBuzzしてる部分では、":@]が動詞0、(4:{.[)が動詞1、(4:}.[)が動詞2、[が動詞3、((0:=3:|])++:@(0:=5:|]))が条件にあたります。


条件: ((0:=3:|])++:@(0:=5:|]))

条件の部分にはフォークが使われています。
フォークしている動詞は、(0:=3:|])++:@(0:=5:|])の3つです。

(0:=3:|])を動詞a、+を動詞b、+:@(0:=5:|])を動詞cとして解説します。


条件: 動詞a: (0:=3:|])

ここにもフォークが使われています。
0:=3:|]がフォークになっていて、さらに3:|]のなかで3:|]がフォークになっています。

]
右の引数をそのまま返す動詞です。FizzBuzzしてる部分の右の引数はi.などを使って作った1 2 3 ……のような整数配列なので、それが返ります。

|
右の引数を左の引数で割った余りを計算する動詞です。

3:
3 を返す動詞です。引数になにを渡されても、絶対に 3 しか返しません。

=
右の引数と左の引数が等しければ 1 を、そうでなければ 0 を返す動詞です。

0:
0 を返す動詞です。引数になにを渡されても、絶対に 0 しか返しません。

動詞aの計算結果は、引数を3で割った余りが0なら 1、そうでなければ 0 になります。
つまり、3の倍数なら 1、そうでなければ 0 になります。


条件: 動詞c: +:@(0:=5:|])

(0:=5:|])
ここはさっきとほとんど同じです。5の倍数なら 1、そうでなければ 0 になります。

@
動詞どうしをつなげる接続詞です。

+:
引数を2倍する動詞です。

つまり動詞cの計算結果は、5の倍数なら 2、そうでなければ 0 になります。


条件: 動詞b: +

動詞aと動詞cの結果を足します。
つまり条件の部分は、3の倍数かつ5の倍数なら 3、5の倍数なら 2、3の倍数なら 1、それ以外なら 0 になります。

したがってFizzBuzzしてる部分では、整数配列の要素が3の倍数かつ5の倍数なら動詞3を、5の倍数なら動詞2を、3の倍数なら動詞1を、それ以外なら動詞0を実行します。


動詞0: ":@]

]
右の引数をそのまま返す動詞です。つまり整数配列です。

@
接続詞です。

":
数値を文字列を変換する動詞です。'Fizz''Buzz'は文字列なので、14などの数値も文字列に変えなければうまくいきません。

つまり動詞0は、引数の数値を文字列に変換します。


動詞1: (4:{.[)

ここにもフォークが使われています。

[
左の引数をそのまま返す動詞です。FizzBuzzしてる部分の左の引数は文字列'FizzBuzz'なので、それが返ります。

{.
配列の要素を取り出す動詞です。配列の要素を指定された数だけ前から取り出して、新たな配列を作ります。

4:
4 を返す動詞です。

動詞1は、'FizzBuzz'の前から4つを取り出します。
つまり、'Fizz'を返します。


動詞2: (4:}.[)

ここにもフォークが使われています。
J言語は、フォークのおかげで短く書けるといっても過言ではありません。

[
左の引数をそのまま返す動詞です。つまり'FizzBuzz'です。

}.
配列の要素を落とす動詞です。配列の要素を指定された数だけ前から落として、新たな配列を作ります。

4:
4 を返す動詞です。

動詞2は、'FizzBuzz'の前から4つを落とします。
つまり、'Buzz'を返します。


動詞3: [

動詞3は、左の引数を返します。
つまり'FizzBuzz'をそのまま返します。

したがってFizzBuzzしてる部分は、整数配列の要素が3の倍数かつ5の倍数なら'FizzBuzz'を、5の倍数なら'Buzz'を、3の倍数なら'Fizz'を、それ以外なら文字列に変換した数値を返します。


これでようやくFizzBuzzができました!

あとは整数を指定すれば、1からその整数までの配列が作られて、その要素がFizzBuzzに変換されていきます。

追記(2020/12/27)

フォークの左の部分には名詞を使うこともできます。
なので、3:5:は、35というふうに、単に数値に置き換えることができます。

FizzBuzz=: 'FizzBuzz'&(":@]`(4{.[)`(4}.[)`[@.((0=3|])++:@(0=5|])))&>:&i.

ちなみに

J言語はif文やfor文も使えます。

FizzBuzz.ijs
FizzBuzz =: 3 : 0
for_i. >: i. y do.
  if. 0 = 15 | i do.
    echo 'FizzBuzz'
  elseif. 0 = 3 | i do.
    echo 'Fizz'
  elseif. 0 = 5 | i do.
    echo 'Buzz'
  else.
    echo i
  end.
end.
)

こっちのほうが読みやすい。

おわりに

最後まで読んでくださって、ありがとうございます。パズルみたいで楽しくなかったですか?
この記事を読んで、J言語に少しでも興味を持ってもらえたらうれしいです。

参考サイト

Jsoftware
J Software - J 言語
J言語基礎講座
Rubyist のための他言語探訪 【第 12 回】 APL と J
J言語の使用によるASCII文字の地獄への手引き - TopCoderとJ言語と時々F#
J言語 カテゴリーの記事一覧 - (保存用) 檜山正幸のキマイラ飼育記 メモ編
J言語でFizzBuzz - ふるつき
J言語のエッセンスとクイックレファレンス そして講義、特にファイル処理(須田)(未定稿)

5
2
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2