Java の FizzBuzz コードゴルフ
- Java の各バージョンでの FizzBuzz の最短コードと思われるものを、とりあえずメモ
- 基本的に java と javac はセットで使う
- 普通のコードゴルフ同様、標準エラー出力や終了コードは無視する
- 基本的にコードの最後に改行はつけない(文字数を減らすため)
Java1.4.2 (105char)
A.java
class A{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 の時代は、三項演算子は同じ型でないとコンパイルエラーになる
-
class
にmain
メソッドがなくてもスタティックイニシャライザが動いてしまう。ただしエラーメッセージは出る
$ 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 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
$ javac A.java
A.java:1: ? に対する互換性のない型 : どちらも他方のサブタイプではありません。
2 番目のオペランド : int
3 番目のオペランド : java.lang.String
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:1: ? に対する互換性のない型 : どちらも他方のサブタイプではありません。
2 番目のオペランド : int
3 番目のオペランド : java.lang.String
class A{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~20 (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"));}}
-
interface
にmain
メソッドが書けるようになって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
Java21 (97char?)仮
2023-09 リリース予定の Java21 では JEP445 がプレビューとして取り込まれることになっているため、以下のように FizzBuzz が実装できるようです。
Main.java
int i;void main(){for(;i++<100;)System.out.println((i%3>0?"":"Fizz")+(i%5>0?i%3>0?i:"":"Buzz"));}
Java21 時点では実行時にプレビュー機能を有効にする指定をしないと実行できません。
$ javac --release 21 --enable-preview Main.java
$ java --enable-preview Main
あるいは(JEP330 を使って、ソースを直接実行)
$ java --source 21 --enable-preview Main.java
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