LoginSignup
4
3

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

Last updated at Posted at 2019-09-07

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 の時代は、三項演算子は同じ型でないとコンパイルエラーになる
  • 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 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"));}}
  • 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

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
4
3
0

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
4
3