FizzBuzzを真面目にやってみた

#まずはとっさに書いたやつをjavaのクラスで再現した
こないだとっさにFizzBuzzやってみろって言われた時のコードを清書して実行して、縮めてみた
ちなみにjava。

```original_FizzBuzz.java
class FizzBuzz{
	public static void main(String[] args){
		int num = Integer.parseInt(args[0]);
		for(int i = 1; i <= num; i++){
			String out = "";
			if(i % 3 ==  0){
				out = "Fizz";
			}
			
			if(i % 5 == 0){
				out += "Buzz";
			}
			
			if(out.length() == 0){
				out += i;
			}
			
			System.out.println(out);
		}
	}
}
```
#三項演算子つかってみた
三項演算子つかう

```FizzBuzz2.java
class FizzBuzz{
	public static void main(String[] args){
		int num = Integer.parseInt(args[0]);
		for(int i = 1; i <= num; i++){
			String out = i % 3 == 0 ? "Fizz" : "";
			out += i % 5 == 0 ? "Buzz" : "";
			out += out.length() == 0  ? i : "";
			System.out.println(out);
		}
	}
}
```
#限界まで縮めてみた
↓ワンライナーにする

``` FizzBuzz3.java
class FizzBuzz{
	public static void main(String[] args){
		int num = Integer.parseInt(args[0]);
		for(int i = 1; i <= num; i++){
			System.out.println((i % 3 == 0 ? "Fizz" : "") + (i % 5 == 0 ? "Buzz" : i % 3 > 0 ? i : ""));
		}
	}
}

```

実行速度は僕の環境では1,000,000までの処理でそれぞれ3.8秒程度なので見やすさ重視なら上か真ん中が職業プログラマとしては良いかと。

#最初のコードを改良してみた
最初のコードで

```java
 if(i % 5 == 0){
     out += "Buzz";
     System.out.println(out);
     continue;
 }
```

にして

##10,000,000回処理させる

上から
37549秒
38617秒
42779秒
だった。
上と真ん中は誤差。
５秒の差がでるのは大きいのでやっぱり上２つなのかなと。

##標準出力を無くして計測
とここで、計測時に差し込んだループ実行時間の出力以外。
標準出力をなくして10000回を何度もやらせると
上から平均
17ミリ秒
32ミリ秒
27ミリ秒
なので、最初のコードの5余り判定改が一番良いのでは見やすいし

```決定項FizzBuzz.java
class FizzBuzz{
	public static void main(String[] args){
		int num = Integer.parseInt(args[0]);
		for(int i = 1; i <= num; i++){
			String out = "";
			if(i % 3 ==  0){
				out = "Fizz";
			}
			
			if(i % 5 == 0){
				out += "Buzz";
				//System.out.println(out);
				continue;
			}
			
			if(out.length() == 0){
				out += i;
			}
			
			//System.out.println(out);
		}
	}
}
```
最初に戻ったw

#決定版修正
continueが見苦しいのでelse ifに

```決定項修正FizzBuzz.java
class FizzBuzz{
	public static void main(String[] args){
		for(int i = 1; i <= num; i++){
			String out = "";
			if(i % 3 ==  0){
				out = "Fizz";
			}
			
			if(i % 5 == 0){
				out += "Buzz";
			}
			else if(out.length() == 0){
				out += i;
			}
			
			//System.out.println(out);
		}
	}
}

```

縮める選手権の意味について。

#ご指摘を受けて速度向上を目指してみた

```FizzBuzz.java
import java.util.Date;

class FizzBuzz{
    public static void main(String[] args){
        int num = Integer.parseInt(args[0]);
        for(int i = 1; i <= num; i++){
            String out;
            if(i % 15 == 0){
                out = "FizzBuzz";
            }
            else if(i % 3 ==  0){
                out = "Fizz";
            }
            else if(i % 5 == 0){
                out = "Buzz";
            }
            else {
                out = String.valueOf(i);
            }

//          System.out.println(out);
        }
    }
}

```
こちらの処理速度が平均7ミリ秒でした。
見やすいのでこれが現時点の最終版

#速度を極めるコメントを計測してみた

```FizzBuzz4.java
import java.util.Date;

class FizzBuzz4{
	public static void main(String[] args){
		int num = Integer.parseInt(args[0]);
        for(int i = 1; i <= num; i++){
			String out;
            if (i % 5 == 0) {
                if (i % 3 == 0) {
                    out = "FizzBuzz";
                } else {
                    out = "Buzz";
                }
            } else {
                if (i % 3 == 0) {
                    out = "Fizz";
                } else {
                    out = String.valueOf(i);
                }
            }
			//System.out.println(out);
		}
	}
}
```

現状最終版にたいして10,000,000回の繰り返しで298.4ミリ秒対317.2ミリ秒と20ミリ弱かっております。
見通しという点がちょっとなので総合的決定版の座はゆるがずか。

ちなみに、２番目と３番目もそれぞれ標準出力なしの10,000,000回やってみました。

#まとめ

|ファイル名|実装概要|10000回|100000回|コード見通し|総合判定|
|:------|:------|:------:|:------:|:------:|:------:|
|FizzBuzz.java|見通し重視15の公倍数を判定にふくめる版|7ミリ秒|317ミリ秒|良|◎|
|FizzBuzz.java|速度重視条件２分岐版|6ミリ秒|298ミリ秒|可|○|
|FizzBuzz4.java|15の公倍数を判定に使わない版|17ミリ秒|373ミリ秒|可|○|
|FizzBuzz2.java|3項演算子版|32ミリ秒|1165ミリ秒|良|△|
|FizzBuzz3.java|最短１行版|27ミリ秒|1020ミリ秒|微妙|×|

計測方法:各実装でそれぞれ10回ずつ実行し最速の5個の平均をもとめた。

##現在のFizzBuzz決定版

1千万回の繰り返し処理で20ミリ秒の差が致命的になるプロダクトならFizzBuzz4.javaかもなのですが、
一般的にはifのネストは無いなら無い方がいい点と、出力を省いた数値なので、実際にはI/0のコストの前では小さい差になってしまうという点を総合した観点です。

```FizzBuzz.java
import java.util.Date;

class FizzBuzz{
    public static void main(String[] args){
        int num = Integer.parseInt(args[0]);
        for(int i = 1; i <= num; i++){
            String out;

            if(i % 15 == 0){
                out = "FizzBuzz";
            }
            else if(i % 3 ==  0){
                out = "Fizz";
            }
            else if(i % 5 == 0){
                out = "Buzz";
            }
            else {
                out = String.valueOf(i);
            }

            System.out.println(out);
        }
    }
}
```