穴の数を数えるだけの簡単なお仕事…

他人が書いたコードを見ると、自分がいかに効率的でないコードを書いているかすぐ分かってしまいますね。

久々にTopCoderをやってみました。
SRM503 Div2 の250点問題です。

与えられた整数に含まれる穴の数を答えてください、という趣旨の問題でした。

  • 3,5,7はとじている部分がないので、穴は0個
  • 0,4,6,9はとじている部分が一つあるので、穴は1個
  • 8はとじている部分が二つあるので、穴は2個

というルールです。
例えば、「5683」という整数が与えられたとします。
5は穴がありません。6は穴が一つあります。8は穴が二つあります。3は穴がありません。
よって、0+1+2+0=3
3を答えればいいわけです。
穴の数を数えるだけの簡単なお仕事ですね!

やりたいこともわかってるし、パパっとコードを書いちゃおうと思ったのですが、少し悩みました。
数字を一桁づつどうやって切りだそうかと。
結局こんな感じのコードを書きました。
言語はjavaです。

public class DigitHoles {

	public int numHoles(int number) {
		int answer = 0;
		int val;
		String str = Integer.toString(number);
		for (int i = 0; i < str.length(); i++) {
			val = str.charAt(i) - 48;
			if (val == 0 || val == 4 || val == 6 || val == 9) {
				answer++;
				continue;
			}
			if (val == 8)
				answer += 2;
		}
		return answer;
	}
}

一旦文字列に戻してから一つ一つ取り出せばいいじゃん!という安直な発想です(笑)
書いた直後は、一応テストもすんなり通ったので喜んでいたのですが、一旦文字列に戻してからまた数字に戻すのはいかがなものかと思い、他の方の回答も参考にしながら、どうするのが最も素直というか、すっきりしてるのかな?としばらく考えていたのですが…

public class DigitHoles {

	public int numHoles(int number) {
		int answer = 0;
		int val[] = { 1, 0, 0, 0, 1, 0, 1, 0, 2, 1 };
		while (number != 0) {
			answer += val[number % 10];
			number /= 10;
		}
		return answer;
	}
}

こんな感じでしょうか。一旦文字列に戻して…など、余計なことはしていません。
1の位の数字だけを取り出したかったら、10で割った余りを求めればいいんですね!
当たり前だろ!と言われてしまったら何も言えないのですが、思いつきませんでした…
前者と後者、どちらのコードがいいかなんて一目瞭然ですよね!