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

昨夜は、今年最初のオフライリアルタイムどう書くでした。

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

今回は、続柄です!

すわツリーかと思いますが、バランスが良くごく浅いツリーなので、辿り方について悩まなくても解けるようです。

といっても、自分は時間内に筋道すら立てられませんでしたが……。

半数の人が時間内に解いて、他の人もほぼ完成していました。さすがです。

どうやって失敗したか

最初は、Personクラスなるものを作って、母、姉妹リスト、娘リストを持たせようとしていました。

class Person {
	protected int id;
	protected Person mother;
	protected List<Person> sisters = new ArrayList<>();
	protected List<Person> daughters = new ArrayList<>();

	public Person(final int n) {
		id = n;
	}

	public void setMother(final Person p) {
		mother = p;
	}

	public void setSisters(final List<Person> list) {
		sisters = list;
	}

	public void setDaughters(final List<Person> list) {
		daughters = list;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		Person other = (Person) obj;
		if (id != other.id) {
			return false;
		}
		return true;
	}
}

oh...

しかし、Personオブジェクトに値を正確に詰められるのであれば、それはもはや問題が解けたも同然ではないかということに気づいてやめました。気づくのに30分近くかかりました。その後は、自分と相手の関係性ごとに相対位置を方程式で表わせるはずだと考えて、1を足したり3で割ったり剰余に意味を求めたりしていました。で、タイムオーバーになりました。

解き直し

昨日出た解答のうち一番カンタンそうだと思ったのは、鍋谷さんが用意してくださった模範解答のうちの1つでした。

ロジックを思い出して、Javaで書いてみました。

差分は、カーチャン情報を保持するためのデータ構造くらいです。

import static org.junit.Assert.assertEquals;

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

import org.junit.Test;

/**
 * 問題: http://qiita.com/items/5e1c944541f09f0f9711
 * 鍋谷さんが解説してくださった模範解答のロジックをJavaで書きました。(自分の母の情報だけを持つVer.)
 */
public class KinshipOnlyMother {

	Map<Integer, Integer> mothers = new HashMap<>();

	public KinshipOnlyMother() {
		for (int i = 1; i < 41; i++) {
			mothers.put(i, (i + 1) / 3);
		}
	}

	protected String solve(String input) {
		int indexOf = input.indexOf('-');
		int in0 = Integer.parseInt(input.substring(0, indexOf));
		int in1 = Integer.parseInt(input.substring(indexOf + 2));

		if (in0 == in1) { // 相手が自分
			return "me"; // 本人
		} else if (mothers.get(in0) == in1) { // 相手が自分の母
			return "mo"; // 母
		} else if (mothers.get(in1) == in0) { // 自分が相手の母
			return "da"; // 娘
		} else if (mothers.get(in0) == mothers.get(in1)) { // 自分の母と相手の母が同じ
			return "si"; // 姉妹
		} else if (mothers.get(mothers.get(in0)) == mothers.get(in1)) { // 自分の祖母と相手の母が同じ
			return "au"; // おば
		} else if (mothers.get(mothers.get(in1)) == mothers.get(in0)) { // 相手の祖母と自分の母が同じ
			return "ni"; // 姪
		} else if (mothers.get(mothers.get(in0)) == mothers.get(mothers
				.get(in1))) { // 自分の祖母と相手の祖母が同じ
			return "co"; // いとこ
		}
		return "-";
	}
}

解き方に気づきさえすれば超カンタン、という良問だったみたいです。ぐぬぬ

鍋谷さん、皆さん、ありがとうございました。

(あとで、他の解答も書いてみるつもり)