FizzBuzzをJavaでやってみる
有名なFizzBuzz問題というのを解いたことがなかったのでやってみた。
1から100までの数をプリントするプログラムを書け。ただし3の倍数のときは数の代わりに「Fizz」と,5の倍数のときは「Buzz」とプリントし,3と5両方の倍数の場合には「FizzBuzz」とプリントすること。
ただ目的を達するだけではつまらないので、より汎用化した記述にしてみた。
public class FizzBuzzMaker { //このフィールドに対となる数値と文字列を格納しておく Map<Integer, String> table = new LinkedHashMap<Integer, String>(); void addRecord(Integer i, String s){ table.put(i, s); } //数値を文字列に変換する際はtableを見る String generateString(int i){ StringBuilder sb = new StringBuilder(); Set<Integer> keys = table.keySet(); for (Integer key : keys) { if(i % key == 0) sb.append(table.get(key)); } if(sb.length() == 0) sb.append(i); return sb.toString(); } public static void main(String[] args) { FizzBuzzMaker fizzBuzzMaker = new FizzBuzzMaker(); //数値と文字列を指定 fizzBuzzMaker.addRecord(3, "Fizz"); fizzBuzzMaker.addRecord(5, "Buzz"); for (int i = 1; i <= 100; i++) { System.out.println(fizzBizzMaker.generateString(i)); } } }
この問題には、3とか5の特定の数値に限らず一つ共通化できるロジックがある。それは指定した数値の倍数だった場合、指定した数値の対となる文字列を出力するという点。その部分を汎用化すると上のような記述になった。
オブジェクトのフィールド"table" に数値と対になる文字列を格納し、判定をする際はそのテーブルを見て文字列に変換する形になる。
こうしておけば、仮に「7の倍数が来たときに"Kazz" という文字列を表示する。3と7の倍数の場合は"FizzKazz", 5と7の倍数の場合は"BuzzKazz", 3と5と7の倍数の場合は"FizzBuzzKazz" を表示する」とかいう条件が増えても、レコードを一つ追加するだけで対応できる。
public static void main(String[] args) { FizzBuzzMaker fizzBuzzMaker = new FizzBuzzMaker(); fizzBuzzMaker.addRecord(3, "Fizz"); fizzBuzzMaker.addRecord(5, "Buzz"); fizzBuzzMaker.addRecord(7, "Kazz"); //追加 for (int i = 1; i <= 105; i++) { System.out.println(fizzBizzMaker.generateString(i)); } }
出力結果
1 2 Fizz 4 Buzz Fizz Kazz 8 Fizz Buzz 11 Fizz 13 Kazz FizzBuzz 16 17 Fizz 19 Buzz FizzKazz 22 23 Fizz Buzz 26 Fizz Kazz 29 FizzBuzz 31 32 Fizz 34 BuzzKazz Fizz 37 38 Fizz Buzz 41 FizzKazz 43 44 FizzBuzz 46 47 Fizz Kazz Buzz Fizz 52 53 Fizz Buzz Kazz Fizz 58 59 FizzBuzz 61 62 FizzKazz 64 Buzz Fizz 67 68 Fizz BuzzKazz 71 Fizz 73 74 FizzBuzz 76 Kazz Fizz 79 Buzz Fizz 82 83 FizzKazz Buzz 86 Fizz 88 89 FizzBuzz Kazz 92 Fizz 94 Buzz Fizz 97 Kazz Fizz Buzz 101 Fizz 103 104 FizzBuzzKazz
FizzBuzzKazzは105まで出てこなかった。。