Enumを使って処理を分ける(c.f.第3回オフラインリアルタイムどう書くの参考問題)

第9回のどう書くの問題のおかげで気づきましたが、EnumのstaticメソッドのvalueOfはベンリですね!

文字を与えてEnumの値を取ってくるだけの基本的なメソッドです。なにをいまさらという感じですが……。

このメソッドを使えば、入力文字(char)による処理の振り分けがカンタンに書けます。

enum Foo {
	A {
		@Override
		void print() {
			System.out.println("Aです");
		}
	},
	B {
		@Override
		void print() {
			System.out.println("Bです");
		}
	},
	C {
		@Override
		void print() {
			System.out.println("Cです");
		}
	};
	abstract void print();
}

public class Main {
	public static void main(String[] args) {
		Foo.valueOf("A").print();
	}
}
Aです

こんな感じに。

なので、たとえば、第3回の参考問題なども楽勝になります。

野球のボールカウント・アウトカウントの遷移を計算する。(得点・ランナー・イニング の計算は不要)
ただし、ストライク・ボール・ファウル・ヒット・ピッチャーフライしかない。
細かいルールは下記の通り:

  • ストライクが3つになったらアウトが増え、ストライクとボールがゼロになる。
  • ボールが4つになったらフォアボールになり、ストライクとボールがゼロになる。アウトは増えない。
  • ヒットを打ったらストライクとボールがゼロになる。アウトは増えない。
  • ピッチャーフライを打ったらストライクとボールがゼロになり、アウトが増える。
  • アウトが3つになったら、アウト・ストライク・ボール全てゼロになる。
  • ファウルの場合、もともとストライクが1以下の場合はストライクが増え、ストライクが2の場合には変化なし。
  • 入力は "sbsfbhsshssbbffbbssbs" のように、ひとつながりの文字列として与えられる。
  • s, b, f, h, p がそれぞれ ストライク、ボール、ファウル、ヒット、ピッチャーフライ を意味する。

(後略)

オフラインリアルタイムどう書く第三回の参考問題

sbfhpの各文字に対応するメソッドを定義して直接呼び出したいなーと悩んでいましたが、この程度ならEnumでできるわけです。

上記のようなことをする必要はありませんでした……。

書き直したら、結構短くなりました。

enum Rule {
	s {
		@Override
		int[] play(int[] count) {
			count[1] += 1;
			if (count[1] == 3) {
				count[0] += 1;
				count[1] = 0;
			}
			return count;
		}
	},
	b {
		@Override
		int[] play(int[] count) {
			if ((count[2] += 1) == 4) {
				count[1] = 0;
				count[2] = 0;
			}
			return count;
		}
	},
	f {
		@Override
		int[] play(int[] count) {
			if (count[1] < 2) {
				count[1] += 1;
			}
			return count;
		}
	},
	h {
		@Override
		int[] play(int[] count) {
			count[1] = 0;
			count[2] = 0;
			return count;
		}
	},
	p {
		@Override
		int[] play(int[] count) {
			count[0] += 1;
			count[1] = 0;
			count[2] = 0;
			return count;
		}
	};
	abstract int[] play(int[] count);
}

/**
 * 問題: http://qiita.com/items/ebd8a56b41711ba459f9
 */
public class BallCountEx {
	public String solve(String input) {
		int[] count = new int[3]; // out, strike, ball
		char[] charArray = input.toCharArray();

		String result = "";
		for (char each : charArray) {
			Rule rule = Rule.valueOf(String.valueOf(each));
			count = rule.play(count);
			count = outCheck(count);
			for (int i : count) {
				result += i;
			}
			result += ",";
		}
		return result.substring(0, result.length() - 1);
	}

	private int[] outCheck(int[] count) {
		if (count[0] == 3) {
			count[0] = 0;
			count[1] = 0;
			count[2] = 0;
		}
		return count;
	}
}

めでたし、めでたし。