迷路探索のアルゴリズムを考えろという問題。
人生を書き換える者すらいた: 人材獲得作戦・4 試験問題ほか より。
このアルゴリズムは、やったことはなかったので、やってみました。
で、結果。Lv2 (最短性のチェックはせず、とにかく1本の到達経路を求めることまではできた) までしかできませんでした…orz
とにかく可能な限り G に近づくようにするようにやっていったので、実際には最短ルートがでるはずだとは思いますが、(間違っているかも)どちらにせよ Lv2 ですね…。
次の記事で、筆者曰くこの問題ができたから優秀な人材とは限らないけれど、できない人は”ほぼ確実に”優秀ではない、のではないかと。
このブログの自己紹介欄から「底辺プログラマ。」の一言が消えるのはまだまだ先か…。
以下コード。Java です。無駄に長い。
import java.awt.Point;
//2時間22分
public class MeiroSaitan {
char[][] chars = {
"**************************".toCharArray(),
"*S* * *".toCharArray(),
"* * * * ************* *".toCharArray(),
"* * * ************ *".toCharArray(),
"* * *".toCharArray(),
"************** ***********".toCharArray(),
"* *".toCharArray(),
"** ***********************".toCharArray(),
"* * G *".toCharArray(),
"* * *********** * *".toCharArray(),
"* * ******* * *".toCharArray(),
"* * *".toCharArray(),
"**************************".toCharArray()
};
Character[][] maps = new Character[13][26];
Point current = new Point(0, 0);
Point former = new Point(0, 0);
Point gPlace = new Point(0, 0);
public static void main(String[] args) {
new MeiroSaitan();
}
public MeiroSaitan() {
// S の位置を current に代入
for (int i = 0; i < chars.length; i++) {
for (int j = 0; j < chars[i].length; j++) {
maps[i][j] = new Character(chars[i][j]);
if (maps[i][j].equals('S')) {
current.x = j;
current.y = i;
former.x = j;
former.y = i;
}
if (maps[i][j].equals('G')) {
gPlace.x = j;
gPlace.y = i;
}
}
}
while (!maps[current.y][current.x].equals('G')) { // G に辿り着かない限り
former.x = current.x;
former.y = current.y;
if (whereIsG()[0] == S.RIGHT && whereIsG()[1] == S.DOWN) {
// 下がブロックでなければ
if (canMove(S.DOWN) && !hasGone(S.DOWN))
current.y = current.y + 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !hasGone(S.RIGHT))
current.x = current.x + 1;
// 左がブロックでなければ
else if (canMove(S.LEFT) && !hasGone(S.LEFT))
current.x = current.x - 1;
// 上がブロックでなければ
else if (canMove(S.UP) && !hasGone(S.UP))
current.y = current.y - 1;
//
// 下がブロックでなければ
else if (canMove(S.DOWN) && !isBadRoute(S.DOWN))
current.y = current.y + 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !isBadRoute(S.RIGHT))
current.x = current.x + 1;
// 左がブロックでなければ
else if (canMove(S.LEFT) && !isBadRoute(S.LEFT))
current.x = current.x - 1;
// 上がブロックでなければ
else if (canMove(S.UP) && !isBadRoute(S.UP))
current.y = current.y - 1;
//
else
System.out.println("I can't move!");
} else if (whereIsG()[0] == S.RIGHT && whereIsG()[1] == S.UP) {
// 上がブロックでなければ
if (canMove(S.UP) && !hasGone(S.UP))
current.y = current.y - 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !hasGone(S.RIGHT))
current.x = current.x + 1;
// 左がブロックでなければ
else if (canMove(S.LEFT) && !hasGone(S.LEFT))
current.x = current.x - 1;
// 下がブロックでなければ
else if (canMove(S.DOWN) && !hasGone(S.DOWN))
current.y = current.y + 1;
//
// 上がブロックでなければ
else if (canMove(S.UP) && !isBadRoute(S.UP))
current.y = current.y - 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !isBadRoute(S.RIGHT))
current.x = current.x + 1;
// 左がブロックでなければ
else if (canMove(S.LEFT) && !isBadRoute(S.LEFT))
current.x = current.x - 1;
// 下がブロックでなければ
else if (canMove(S.DOWN) && !isBadRoute(S.DOWN))
current.y = current.y + 1;
//
else
System.out.println("I can't move!");
} else if (whereIsG()[0] == S.LEFT && whereIsG()[1] == S.UP) {
// 左がブロックでなければ
if (canMove(S.LEFT) && !hasGone(S.LEFT))
current.x = current.x - 1;
// 上がブロックでなければ
else if (canMove(S.UP) && !hasGone(S.UP))
current.y = current.y - 1;
// 下がブロックでなければ
else if (canMove(S.DOWN) && !hasGone(S.DOWN))
current.y = current.y + 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !hasGone(S.RIGHT))
current.x = current.x + 1;
//
// 左がブロックでなければ
else if (canMove(S.LEFT) && !isBadRoute(S.LEFT))
current.x = current.x - 1;
// 上がブロックでなければ
else if (canMove(S.UP) && !isBadRoute(S.UP))
current.y = current.y - 1;
// 下がブロックでなければ
else if (canMove(S.DOWN) && !isBadRoute(S.DOWN))
current.y = current.y + 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !isBadRoute(S.RIGHT))
current.x = current.x + 1;
//
else
System.out.println("I can't move!");
} else if (whereIsG()[0] == S.LEFT && whereIsG()[1] == S.DOWN) {
// 左がブロックでなければ
if (canMove(S.LEFT) && !hasGone(S.LEFT))
current.x = current.x - 1;
// 下がブロックでなければ
else if (canMove(S.DOWN) && !hasGone(S.DOWN))
current.y = current.y + 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !hasGone(S.RIGHT))
current.x = current.x + 1;
// 上がブロックでなければ
else if (canMove(S.UP) && !hasGone(S.UP))
current.y = current.y - 1;
//
// 下がブロックでなければ
else if (canMove(S.DOWN) && !isBadRoute(S.DOWN))
current.y = current.y + 1;
// 右がブロックでなければ
else if (canMove(S.RIGHT) && !isBadRoute(S.RIGHT))
current.x = current.x + 1;
// 左がブロックでなければ
else if (canMove(S.LEFT) && !isBadRoute(S.LEFT))
current.x = current.x - 1;
// 上がブロックでなければ
else if (canMove(S.UP) && !isBadRoute(S.UP))
current.y = current.y - 1;
//
else
System.out.println("I can't move!");
}
if (hasGone(current.x, current.y) && !maps[current.y][current.x].equals('G')) {
maps[former.y][former.x] = 'x';
} else if (!maps[current.y][current.x].equals('G')){
maps[current.y][current.x] = '$';
}
// showCurrentState();
}
showCurrentState();
}
private boolean canMove(S s) {
switch (s) {
case UP:
if (maps[current.y - 1][current.x].equals('*')) {
return false;
} else {
return true;
}
case DOWN:
if (maps[current.y + 1][current.x].equals('*')) {
return false;
} else {
return true;
}
case RIGHT:
if (maps[current.y][current.x + 1].equals('*')) {
return false;
} else {
return true;
}
case LEFT:
if (maps[current.y][current.x - 1].equals('*')) {
return false;
} else {
return true;
}
}
return false;
}
private boolean hasGone(int x, int y) {
if (maps[y][x].equals('$') || maps[y][x].equals('x')) {
return true;
}
return false;
}
private boolean hasGone(S s) {
switch (s) {
case UP:
if (maps[current.y - 1][current.x].equals('x') || maps[current.y - 1][current.x].equals('$')) {
return true;
} else {
return false;
}
case DOWN:
if (maps[current.y + 1][current.x].equals('x') || maps[current.y + 1][current.x].equals('$')) {
return true;
} else {
return false;
}
case RIGHT:
if (maps[current.y][current.x + 1].equals('x') || maps[current.y][current.x + 1].equals('$')) {
return true;
} else {
return false;
}
case LEFT:
if (maps[current.y][current.x - 1].equals('x') || maps[current.y][current.x - 1].equals('$')) {
return true;
} else {
return false;
}
}
return false;
}
private boolean isBadRoute(S s) {
switch (s) {
case UP:
if (maps[current.y - 1][current.x].equals('x')) {
return true;
} else {
return false;
}
case DOWN:
if (maps[current.y + 1][current.x].equals('x')) {
return true;
} else {
return false;
}
case RIGHT:
if (maps[current.y][current.x + 1].equals('x')) {
return true;
} else {
return false;
}
case LEFT:
if (maps[current.y][current.x - 1].equals('x')) {
return true;
} else {
return false;
}
}
return false;
}
private void showCurrentState() {
System.out.println(former.x + ", " + former.y + " -> " + current.x + ", " + current.y);
for (int i = 0; i
< maps.length; i++) {
for (int j = 0; j
< maps[i].length; j++) {
System.out.print(maps[i][j]);
}
System.out.println();
}
System.out.println("----------");
}
private S[] whereIsG() {
S[] where = new S[2];
if (current.x < gPlace.x) {
where[0] = S.RIGHT;
} else {
where[0] = S.LEFT;
}
if (current.y < gPlace.y) {
where[1] = S.DOWN;
} else {
where[1] = S.UP;
}
return where;
}
enum S {
RIGHT, LEFT, UP, DOWN;
}
}