LoginSignup
7
6

More than 5 years have passed since last update.

FizzBuzzを真面目にやってみた

Last updated at Posted at 2015-03-05

まずはとっさに書いたやつを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秒程度なので見やすさ重視なら上か真ん中が職業プログラマとしては良いかと。

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

最初のコードで

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

にして

10,000,000回処理させる

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

標準出力を無くして計測

とここで、計測時に差し込んだループ実行時間の出力以外。
標準出力をなくして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ミリ弱かっております。
見通しという点がちょっとなので総合的決定版の座はゆるがずか。

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

まとめ

ファイル名 実装概要 10000回 100000回 コード見通し 総合判定
FizzBuzz.java 見通し重視15の公倍数を判定にふくめる版 7ミリ秒 317ミリ秒
FizzBuzz.java 速度重視条件2分岐版 6ミリ秒 298ミリ秒
FizzBuzz4.java 15の公倍数を判定に使わない版 17ミリ秒 373ミリ秒
FizzBuzz2.java 3項演算子版 32ミリ秒 1165ミリ秒
FizzBuzz3.java 最短1行版 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);
        }
    }
}
7
6
8

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
7
6