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さん申し訳ないです…。