[memo] Java の FizzBuzz コードゴルフ


Java の FizzBuzz コードゴルフ

  • Java の各バージョンでの FizzBuzz の最短コードと思われるものを、とりあえずメモ
  • 基本的に java と javac はセットで使う
  • 普通のコードゴルフ同様、標準エラー出力は無視する
  • 基本的にコードの最後に改行はつけない(文字数を減らすため)

Java1.4.2 (105char)

A.java
class B{static{for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i+"":"":"Buzz"));}}
  • Java1.4.2 の時代は、三項演算子は同じ型でないとコンパイルエラーになる
  • classmain メソッドがなくてもスタティックイニシャライザが動いてしまう。ただしエラーメッセージは出る
$ java -version
java version "1.4.2_19"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_19-b04)
Java HotSpot(TM) Client VM (build 1.4.2_19-b04, mixed mode)
$ javac -version
javac: -version は無効なフラグです。
使い方: javac <options> <source files>
使用可能なオプションには次のものがあります。
  -g                        すべてのデバッグ情報を生成する
  -g:none                   デバッグ情報を生成しない
  -g:{lines,vars,source}    いくつかのデバッグ情報だけを生成する
  -nowarn                   警告を発生させない
  -verbose                  コンパイラの動作についてメッセージを出力する
  -deprecation              推奨されない API が使用されているソースの位置を出力する
  -classpath <path>         ユーザクラスファイルを検索する位置を指定する
  -sourcepath <path>        入力ソースファイルを検索する位置を指定する
  -bootclasspath <path>     ブートストラップクラスファイルの位置を置き換える
  -extdirs <dirs>           インストール済み拡張機能の位置を置き換える
  -d <directory>            生成されたクラスファイルを格納する位置を指定する
  -encoding <encoding>      ソースファイルが使用する文字エンコーディングを指定する
  -source <release>         指定されたリリースとソースの互換性を保つ
  -target <release>         特定の VM バージョン用のクラスファイルを生成する
  -help                     標準オプションの概要を出力する

$ echo -n 'class B{static{for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}' > A.java
$ javac A.java
A.java:1: ? に対する互換性のない型 : どちらも他方のサブタイプではありません。
2 番目のオペランド : int
3 番目のオペランド : java.lang.String
class B{static{for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}
                                                                                     ^
A.java:1: ? に対する互換性のない型 : どちらも他方のサブタイプではありません。
2 番目のオペランド : int
3 番目のオペランド : java.lang.String
class B{static{for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}
                                                                               ^
エラー 2 個
$ echo -n 'class A{static{for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i+"":"":"Buzz"));}}' > A.java
$ wc -c
105 A.java
$ javac A.java
$ java A
1
2
Fizz
4
Buzz
(略)
97
98
Fizz
Buzz
Exception in thread "main" java.lang.NoSuchMethodError: main
  • Java1.4.2 の時代には javac に -version オプションがないらしい

Java5~Java6 (96char)

A.java
enum A{B;int i;{for(;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}
  • java での最短記録の時期
  • 実行時にエラーメッセージが出るが main メソッド無しでも動いてしまう
  • Java5 で追加された enum でさらに短く
$ java -version
java version "1.5.0_22"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03)
Java HotSpot(TM) Client VM (build 1.5.0_22-b03, mixed mode, sharing)
$ javac -version
javac 1.5.0_22
javac: ソースファイルがありません。
使い方: javac <options> <source files>
使用可能なオプションには次のものがあります。
  -g                         すべてのデバッグ情報を生成する
  -g:none                    デバッグ情報を生成しない
  -g:{lines,vars,source}     いくつかのデバッグ情報だけを生成する
  -nowarn                    警告を発生させない
  -verbose                   コンパイラの動作についてメッセージを出力する
  -deprecation               推奨されない API が使用されているソースの位置を出力する
  -classpath <path>          ユーザクラスファイルを検索する位置を指定する
  -cp <path>                 ユーザクラスファイルを検索する位置を指定する
  -sourcepath <path>         入力ソースファイルを検索する位置を指定する
  -bootclasspath <path>      ブートストラップクラスファイルの位置を置き換える
  -extdirs <dirs>            インストール済み拡張機能の位置を置き換える
  -endorseddirs <dirs>       推奨規格パスの位置を置き換える
  -d <directory>             生成されたクラスファイルを格納する位置を指定する
  -encoding <encoding>       ソースファイルが使用する文字エンコーディングを指定する
  -source <release>          指定されたリリースとソースの互換性を保つ
  -target <release>          特定の VM バージョン用のクラスファイルを生成する
  -version                   バージョン情報
  -help                      標準オプションの概要を出力する
  -X                         非標準オプションの概要を出力する
  -J<flag>                   <flag> を実行システムに直接渡す

$ echo -n 'enum A{B;int i;{for(;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}' > A.java
$ wc -c A.java
96 A.java
$ javac A.java
$ java A
1
2
Fizz
4
Buzz
(略)
97
98
Fizz
Buzz
Exception in thread "main" java.lang.NoSuchMethodError: main
  • Java5 の時代は javac に -version が付いたけど、ソースファイルを省略すると怒られる

Java7 (130char)

A.java
class A{public static void main(String[]a){for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}
  • Java6 までは main 無しでも(エラーを出しつつ)スタティックイニシャライザで動いていたけど、Java7 からは動かなくなってしまった
  • 一番長く、一番素直なコードの時期
$ java -version
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) Client VM (build 24.80-b11, mixed mode, sharing)
$ javac -version
javac 1.7.0_80
$ echo -n 'enum A{B;int i;{for(;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}' > A.java
$ javac A.java
$ java A
エラー: メイン・メソッドがクラスAで見つかりません。次のようにメイン・メソッドを定義してください。
   public static void main(String[] args)
$ echo -n 'class A{public static void main(String[]a){for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}' > A.java
$ wc -c A.java
130 A.java
$ javac A.java
$ java A
1
2
Fizz
4
Buzz
(略)
97
98
Fizz
Buzz

Java8以降 (127char)

A.java
interface A{static void main(String[]a){for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}
  • interfacemain メソッドが書けるようになって public が不要になったのでちょこっと短く
$ java -version
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)
$ javac -version
javac 1.8.0_212
$ echo -n 'interface A{static void main(String[]a){for(int i=0;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}}' > A.java
$ wc -c A.java
127 A.java
$ javac A.java
$ java A
1
2
Fizz
4
Buzz
(略)
97
98
Fizz
Buzz

Jshell (83char)

int i;for(;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"))
  • Java9 から使えるようになった Jshell 版
$ jshell --version
jshell 11.0.3
$ echo -n 'int i;for(;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"))' | jshell -
1
2
Fizz
4
Buzz
(略)
97
98
Fizz
Buzz

Jshell PRINTING 版 (72char)

int i;for(;i++<100;)println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"))
  • jshell のコードゴルフのレギュレーション詳細を知りませんが、なんとなく PRINTING 版
  • 単に System.out. を取り除いただけ
$ echo -n 'int i;for(;i++<100;)println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"))' | jshell PRINTING -
1
2
Fizz
4
Buzz
(略)
97
98
Fizz
Buzz