Hatena::ブログ(Diary)

※ただし体調がよければ

世の中分からないことだらけ。ツッコミ大歓迎です。

2010年02月25日

Google DevFest 2010のクイズ(1)

Google DevFest 2010の参加者選別のために出題されたクイズ(その1)。

数字を漢数字に変換するアプリケーションを作ってください。

http://[あなたのアプリケーションのURL]?n=[数字] にアクセスすると、 text/plain でその数字を漢数字に変換した結果を返すウェブサーバを作ってください。ただし、漢字はすべて以下の表の通りにアルファベットに変換して出力してください。

  • 零 → N
  • 一 → B
  • 二 → G
  • 三 → S
  • 四 → Q
  • 五 → P
  • 六 → Y
  • 七 → R
  • 八 → K
  • 九 → M
  • 十 → A
  • 百 → J
  • 千 → Z
  • 万 → H
  • 億 → L
  • 兆 → F

注意:

  • 「千万」「千億」「千兆」の前に「一」がつかないようにしてください。
  • 入力は負でない整数で、大きさは高々9999兆9999億9999万9999までです。
  • 標準のポート番号80番のみ扱えます。

これはJavaで書いた。

package com.appspot.devfestquizkanji;

import java.util.HashMap;
import java.util.Map;

public class ToKanjiNumConverter {

	static {
		char[] kanjis = "零一二三四五六七八九十百千万億兆".toCharArray();
		char[] alpha = "NBGSQPYRKMAJZHLF".toCharArray();
		assert kanjis.length == alpha.length;
		Map<Character, Character> kToA = new HashMap<Character, Character>();
		for (int i = 0; i < kanjis.length; i++)
			kToA.put(kanjis[i], alpha[i]);
		kanjiToAlpha = kToA;
	}

	private ToKanjiNumConverter() {
	}

	private static final Map<Character, Character> kanjiToAlpha;

	private static final String[] manUnit = { "", "万", "億", "兆" };
	private static final String[] senUnit = { "", "十", "百", "千" };
	private static final String[] numKanji = { "", "一", "二", "三", "四", "五", "六", "七", "八", "九" };

	public static String toKanjiNum(long num) {
		if (num == 0)
			return "零";

		return manUnit(num, 0).toString();
	}

	private static StringBuilder manUnit(long num, int unitNo) {
		StringBuilder sen = sen((int)(num % 10000), 0);
		String unit = manUnit[unitNo];

		if (sen.toString().isEmpty())
			unit = "";

		long next = num / 10000;
		if (0 < next) {
			return manUnit(next, unitNo + 1).append(sen).append(unit);
		} else {
			return new StringBuilder().append(sen).append(unit);
		}
	}

	private static StringBuilder sen(int num, int unitNo) {
		String digit = numKanji[num % 10];
		String unit = senUnit[unitNo];

		if (digit.isEmpty())
			unit = "";

		// "一百"→"百"
		if (digit.equals("一") && !unit.isEmpty())
			digit = "";

		int next = num / 10;
		if (0 < next) {
			return sen(next, unitNo + 1).append(digit).append(unit);
		} else {
			return new StringBuilder().append(digit).append(unit);
		}
	}
	
	public static String toAlphaReps(String kanji) {
		StringBuilder sb = new StringBuilder();
		for (char k : kanji.toCharArray()) {
			sb.append(kanjiToAlpha.get(k));
		}
		return sb.toString();
	}
}

メソッド呼び出し時に単位の配列の添字をパラメータで受け渡すんじゃなくて、本当は単位のリストを受け渡したかった。