「第10回 オフラインリアルタイムどう書く」へなちょこ解答(Java)

オフラインリアルタイムどう書くとは
鍋谷さんが出してくださるお題を、参加者が好きなプログラミング言語で解いて楽しむ会です。

先週の金曜日は第10回オフラインリアルタイムどう書くでした。もう10回なんですね。ということは、あと少しで第1回から1年たつんですね。

今回は、「ハニカム歩き」です!

サンプルデータのアニメーションが凝ってますね。

珍しく時間内に解けたのでヤッターという感じでしたが、頭より腕力を使いました。。。それに、いつものEnum戦法になってしまいました。

(マスの並びに法則性を見出そうとした形跡)

(ムリでした……)

自分の解答

発表時にアドバイスいただいた点をちょこっと直しました。

enum Masu {
	A("BCDEFG"), B("HICAGS"), C("IJKDAB"), D("CKLMEA"), E("ADMNOF"), F("GAEOPQ"), G(
			"SBAFQR"), H("TUIBSk"), I("UVJCBH"), J("VWXKCI"), K("JXYLDC"), L(
			"KYZaMD"), M("DLabNE"), N("EMbcdO"), O("FENdeP"), P("QFOefg"), Q(
			"RGFPgh"), R("jSGQhi"), S("kHBGRj"), T("!!UHk!"), U("!!VIHT"), V(
			"!!WJIU"), W("!!!XJV"), X("W!!YKJ"), Y("X!!ZLK"), Z("Y!!!aL"), a(
			"LZ!!bM"), b("Ma!!cN"), c("Nb!!!d"), d("ONc!!e"), e("POd!!f"), f(
			"gPe!!!"), g("hQPf!!"), h("iRQg!!"), i("!jRh!!"), j("!kSRi!"), k(
			"!THSj!");

	private String dest;

	Masu(String s) {
		dest = s;
	}

	public char getDest(int n) {
		return dest.charAt(n);
	}
}

/**
 * 問題: http://nabetani.sakura.ne.jp/hena/ord10haniwa/
 */
public class Haniwa {
	public String solve(final String input) {
		int[] dests = getDests(input);

		String result = "A";
		Masu start = Masu.valueOf(result);
		for (int each : dests) {
			char dest = start.getDest(each);
			result += dest;
			if (dest == '!') {
				continue;
			}
			start = Masu.valueOf(String.valueOf(dest));
		}
		return result;
	}

	private int[] getDests(final String input) {
		int[] result = new int[input.length()];
		for (int i = 0; i < input.length(); i++) {
			result[i] = Integer.valueOf(String.valueOf(input.charAt(i)));
		}
		return result;
	}
}

修正点

その1

enumのMasuに、移動方向のマス名をchar配列で持たせていたが、文字列にした方が読みやすいと教えてもらったので、変更した。それにともない、enumのgetDestメソッドを、配列の添え字アクセスから文字列のindexアクセスに変更した。

その2

ハニカムの外側を「z」文字で表わしていたのを「!」文字に変更した。「!」は、アルファベットのアイ大文字、エル小文字、数字の1に似ているため、コード若干見づらくなるというデメリットがあるが、一方で戻り値にマスの名前を+=で足しこむときに「!」をそのまま使えるというメリットがある。「!」マスもそれ以外も同じように扱えるようになった。

その3

Stringをいったんchar配列にしてからint配列にしていたが、char配列を経由しなくてよいことに気づいたので直した。

そんなとこ。

皆さんの解答

ハニカムmapをプログラムで作っている解答が印象的でした。それやりたい! しかし、どう書いたらいいのかまだいまいち判ってないです。

発表中のメモからいくつかピックアップします。

イシダさん
  • 配列move_tableで、各方向への移動距離を持つ実装
  • memcpyはこわいから、構造体に配列を入れると代入が使えて幸せ(鍋谷さん)
  • 番兵法を使うと、行き止まり判定の分岐がすっきりする(kei_qさん)
kei_qさん
  • list !! 0 でリストの要素を取ってきちゃダメという話
  • dropを使えば、失敗してもIO例外が飛んだりはしない
Ochakaiさん
  • (ループの終了条件)nullターミネータがくるまでループを回すとよい(鍋谷さん)
  • C99のsizeofは不思議な挙動 is 何
hirataraさん
  • letとwhereの違いの話(kei_qさん)
  • 取ってきたいものを先に書くか、手続きから書くか

そんな感じでした。今回も楽しかったです。鍋谷さん、参加者の皆さん、ありがとうございました。