【Java】FizzBuzzを色々な方法で書いてみる

【Java】FizzBuzzを色々な方法で書いてみる

Javaでプログラムのアルゴリズム問題で有名なFizzBuzzを書いてみます。ノーマルな実装方法と、応用として拡張性を意識した実装方法を紹介します。

FizzBuzzとは

FizzBuzzプログラムは、プログラミングを始めたばかりの人に出されることが多いアルゴリズムの問題です。初級者にとってはアルゴリズムの登竜門ですね。

私も、大学の頃C言語の授業で出された記憶があります。プログラミングを勉強している人は知っている人が多いのではないでしょうか。

FizzBuzzのルール
  • 1から100までの数字を画面に表示する
  • 3の倍数のときは数字の代わりに「Fizz」と表示する
  • 5の倍数のときは数字の代わりに「Buzz」と表示する
  • 15の倍数のときは数字の代わりに「FizzBuzz」と表示する

今回は100まで表示させると出力結果が長くなってしまうので、20まで出力させてみます。

ノーマルな解答例

色々と解答方法があるかと思いますが、一番ノーマルな書き方で実装してみます。

FizzBuzzTest1.java
 1public class FizzBuzzTest1 {
 2  public static void main(String[] args) {
 3    for (int num = 1; num <= 20; num++) {
 4      // 15で割り切れる時FizzBuzzと出力する
 5      if (num % 15 == 0) {
 6        System.out.println("FizzBuzz");
 7      }
 8      // 3で割り切れる時Fizzと出力する
 9      else if (num % 3 == 0) {
10        System.out.println("Fizz");
11      }
12      // 5で割り切れる時Buzzと出力する
13      else if (num % 5 == 0) {
14        System.out.println("Buzz");
15      }
16      // それ以外はそのまま出力する
17      else {
18        System.out.println(num);
19      }
20    }
21  }
22}

実行結果が以下になります。

出力結果
 11
 22   
 3Fizz
 44   
 5Buzz
 6Fizz
 77   
 88   
 9Fizz
10Buzz
1111  
12Fizz
1313  
1414
15FizzBuzz
1616
1717
18Fizz
1919
20Buzz

このアルゴリズムではif文%演算子を使って倍数の判定ができるかがポイントになります。その他、注意する点として倍数の判定の順番があります。最初に15の倍数判定をしないと、3もしくは5の倍数判定に通ってしまうため、ルールを満たさない結果が返ってきます。

拡張性を考えて実装してみる

上記の解答例だとノーマル過ぎて味気がありませんので、応用例としてルールの追加・変更に強いような実装方法を考えてみましょう。

例えば、条件を追加したり異なる条件にしたい時、上のコードではif文を適宜書き換えていけば実現できますが、いちいちif文の条件式を追加変更するのは少し面倒です。

コードの書き換えが簡単になるような実装にしてみます。

FizzBuzzTest2.java
 1import java.util.Collections;
 2import java.util.Map;
 3import java.util.TreeMap;
 4
 5public class FizzBuzzTest2 {
 6  public static void main(String[] args) {
 7    // 条件(倍数と文字列)の指定
 8    Map<Integer, String> fizzbuzzMap = new TreeMap<>(Collections.reverseOrder());
 9    fizzbuzzMap.put(3, "fizz");
10    fizzbuzzMap.put(5, "buzz");
11    fizzbuzzMap.put(15, "buzzfizz");
12    // 表示を行う
13    for (int num = 1; num <= 20; num++) {
14      System.out.println(getString(num, fizzbuzzMap));
15    }
16  }
17
18  // 倍数判定を行うメソッド
19  private static String getString(int num, Map<Integer, String> fizzbuzzMap) {
20    String str = String.valueOf(num);
21    for (int key : fizzbuzzMap.keySet()) {
22      if (num % key == 0) {
23        return fizzbuzzMap.get(key);
24      }
25    }
26    return str;
27  }
28}

実行結果が以下になります。

出力結果
 11
 22   
 3Fizz
 44   
 5Buzz
 6Fizz
 77   
 88   
 9Fizz
10Buzz
1111  
12Fizz
1313  
1414
15FizzBuzz
1616
1717
18Fizz
1919
20Buzz

このコードではgetStringメソッドで倍数判定を行い、引数のTreeMapに倍数と表示したい文字列を格納しています。Collections.reverseOrder()を指定することで、TreeMapを自動でキーの降順に並び替えられます。ここでキーの降順に並び替えているのは、数字の大きい順に倍数判定を行わないと正しい判定がされないからです(15の判定時に3の倍数判定がされて「Fizz」が戻ってくるなど)。

条件を変えたい時はputメソッドの所を好きな物に書き換えるだけで良いので、最初のコードよりかはルール変更に強い実装にすることができました。


色々と実装方法はありますので、皆さんも気軽に挑戦してみましょう。以上で記事を終わりにします。

参考文献