Go For It!!


@PG_kuraさんのページで紹介されてたこれを解いてみたよ。



でもこれじゃ簡単すぎる。多分問題読み違ってる気がする。
それとも例題だからわざと簡単なの出したのか。
きっとメンバーになるとTopCoder真っ青なアレが出てくるのかな?

package goforit;

public class Rectangular {
	private final Surface	s0, s1, s2;

	public Rectangular(
		int x, int y, int z,
		int w, int h, int d) {
		if (w < 0 || h < 0 || d < 0) {
			throw new IllegalArgumentException();
		}
		s0 = new Surface(x, y, w, h);
		s1 = new Surface(z, y, d, h);
		s2 = new Surface(x, z, w, d);
	}

	public boolean isIntersection(Rectangular r) {
		// 三つの面が交差していれば直方体は交差している。
		return s0.isIntersection(r.s0) &&
			s1.isIntersection(r.s1) &&
			s2.isIntersection(r.s2);
	}

	// 面クラス
	private class Surface {
		final int	x, y, mx, my;

		private Surface(int x, int y, int a, int b) {
			this.x = x;
			this.y = y;
			mx = x + a;
			my = y + b;
		}

		// 面の交差判定
		public boolean isIntersection(Surface s) {
			// X軸とY軸について交差判定を行う。
			return isIntersection(x, mx, s.x, s.mx) && isIntersection(y, my, s.y, s.my);
		}

		// 線の交差判定
		private boolean isIntersection(int x, int mx, int _x, int _mx) {
			// 完全に内側入ったときはfalse
			return x <= _mx && _mx <= mx && x >= _x ||
				x <= _x && _x <= mx && mx <= _mx;
		}
	}
}

テストコード。

package goforit;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class RectangularTest {
	@Test(expected = IllegalArgumentException.class)
	public void コンストラクタの例外1() {
		new Rectangular(1, 1, 1, -1, 1, 1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void コンストラクタの例外2() {
		new Rectangular(1, 1, 1, 1, -1, 1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void コンストラクタの例外3() {
		new Rectangular(1, 1, 1, 1, 1, -1);
	}

	@Test()
	public void 交差() {
		assertTrue(new Rectangular(0, 0, 0, 2, 2, 2).isIntersection(new Rectangular(1, 1, 1, 2, 2, 2)));
	}

	@Test()
	public void 領域外() {
		assertFalse(new Rectangular(0, 0, 0, 1, 1, 1).isIntersection(new Rectangular(3, 3, 3, 1, 1, 1)));
	}

	@Test()
	public void 比較対象が完全に領域内に入る() {
		assertFalse(new Rectangular(0, 0, 0, 3, 3, 3).isIntersection(new Rectangular(1, 1, 1, 1, 1, 1)));
	}

	@Test()
	public void 比較対象の領域内に自身が入る() {
		assertFalse(new Rectangular(1, 1, 1, 1, 1, 1).isIntersection(new Rectangular(0, 0, 0, 3, 3, 3)));
	}

	@Test()
	public void 一面だけ領域内() {
		assertFalse(new Rectangular(0, 0, 0, 3, 3, 3).isIntersection(new Rectangular(0, 6, 6, 1, 1, 1)));
	}

	@Test()
	public void 二面だけ領域内() {
		assertFalse(new Rectangular(0, 0, 0, 3, 3, 3).isIntersection(new Rectangular(0, 0, 6, 1, 1, 1)));
	}
}

201112/31 16:48
プログラムのバグハケーン。
内側から直方体が生えてハンマーみたいな形になるパターンが漏れていたので修正。
正月になってないのに正月ボケとかマジ勘弁。

package goforit;

public class Rectangular {
	private final Surface	s0, s1, s2;

	public Rectangular(
		int x, int y, int z,
		int w, int h, int d) {
		if (w < 0 || h < 0 || d < 0) {
			throw new IllegalArgumentException();
		}
		s0 = new Surface(x, y, w, h);
		s1 = new Surface(z, y, d, h);
		s2 = new Surface(x, z, w, d);
	}

	public boolean isIntersection(Rectangular r) {
		return s0.isIntersection(r.s0) && s1.isIntersection(r.s1) && s2.isIntersection(r.s2)
			// 完全に内側に入り込んでいたときは交わっていないと判定する。
			&& !(s0.inArea(r.s0) && s1.inArea(r.s1) && s2.inArea(r.s2));
	}

	// 面クラス
	private class Surface {
		final int	x, y, mx, my;

		private Surface(int x, int y, int a, int b) {
			this.x = x;
			this.y = y;
			mx = x + a;
			my = y + b;
		}

		// 面の交差判定
		public boolean isIntersection(Surface s) {
			return isIntersection(x, mx, s.x, s.mx) && isIntersection(y, my, s.y, s.my);
		}

		// 面が内側に入る判定
		public boolean inArea(Surface s) {
			return inArea(x, mx, s.x, s.mx) && inArea(y, my, s.y, s.my);
		}

		// 線の交差判定
		private boolean isIntersection(int x, int mx, int _x, int _mx) {
			return x <= _mx && _mx <= mx || x <= _x && _x <= mx;
		}

		// 線が内側に入る判定
		private boolean inArea(int x, int mx, int _x, int _mx) {
			return x < _x && _mx < mx;
		}
	}
}
package goforit;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class RectangularTest {
	@Test(expected = IllegalArgumentException.class)
	public void コンストラクタの例外1() {
		new Rectangular(1, 1, 1, -1, 1, 1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void コンストラクタの例外2() {
		new Rectangular(1, 1, 1, 1, -1, 1);
	}

	@Test(expected = IllegalArgumentException.class)
	public void コンストラクタの例外3() {
		new Rectangular(1, 1, 1, 1, 1, -1);
	}

	@Test()
	public void 交差() {
		assertTrue(new Rectangular(0, 0, 0, 2, 2, 2).isIntersection(new Rectangular(1, 1, 1, 2, 2, 2)));
	}

	@Test()
	public void 領域外() {
		assertFalse(new Rectangular(0, 0, 0, 1, 1, 1).isIntersection(new Rectangular(3, 3, 3, 1, 1, 1)));
	}

	@Test()
	public void 比較対象が完全に領域内に入る() {
		assertFalse(new Rectangular(0, 0, 0, 3, 3, 3).isIntersection(new Rectangular(1, 1, 1, 1, 1, 1)));
	}

	@Test()
	public void 比較対象の領域内に自身が入る() {
		assertFalse(new Rectangular(1, 1, 1, 1, 1, 1).isIntersection(new Rectangular(0, 0, 0, 3, 3, 3)));
	}

	@Test()
	public void 一面だけ領域内() {
		assertFalse(new Rectangular(0, 0, 0, 3, 3, 3).isIntersection(new Rectangular(0, 6, 6, 1, 1, 1)));
	}

	@Test()
	public void 二面だけ領域内() {
		assertFalse(new Rectangular(0, 0, 0, 3, 3, 3).isIntersection(new Rectangular(0, 0, 6, 1, 1, 1)));
	}

	@Test()
	public void 内側から直方体が生える() {
		assertTrue(new Rectangular(0, 0, 0, 3, 3, 3).isIntersection(new Rectangular(1, 1, 1, 1, 3, 1)));
	}

}


さらに追記…トラックバック先とリンクも間違えてた件。
id:JunichiItoさん申し訳ないです…。