diff --git a/sitou/src/A083_SecretMessage.java b/sitou/src/A083_SecretMessage.java new file mode 100644 index 0000000000000000000000000000000000000000..460844d31a7e0cb7a99509a8e5b51dd9ef7567a5 --- /dev/null +++ b/sitou/src/A083_SecretMessage.java @@ -0,0 +1,106 @@ +package src; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class A083_SecretMessage { + + public static void main(String[] args) { + execute(); + } + + static void execute() { + final InputData inputData = input(); + final TreasureMap treasureMap = new TreasureMap(inputData); + final Result result = solve(treasureMap); + output(result); + } + + private static InputData input() { + final Scanner scan = new Scanner(System.in); + final int height = scan.nextInt(); + final int width = scan.nextInt(); + final String[] mapStatus = new String[height]; + + for (int i = 0; i < height; i++) { + mapStatus[i] = scan.next(); + } + + scan.close(); + return new InputData(height, width, mapStatus); + + } + + public static Result solve(TreasureMap treasureMap) { + treasureMap.get(0, 0); + + List allPaths = new ArrayList<>(); + findPaths(0, 0, "", treasureMap, allPaths); + + // 辞書順で早いものを探索 + String smallestPath = allPaths.get(0); + for (String p : allPaths) { + if (p.compareTo(smallestPath) < 0) { + smallestPath = p; + } + } + return new Result(smallestPath); + + } + + public enum Direction { + UP(0, -1), + DOWN(0, 1), + LEFT(-1, 0), + RIGHT(1, 0); + + private final int x; + private final int y; + + private Direction(final int x, final int y) { + this.x = x; + this.y = y; + } + + public final int getX() { + return x; + } + + public final int getY() { + return y; + } + } + + public static void findPaths(int x, int y, String path, + TreasureMap treasureMap, List allPaths) { + + // Map外や二度目に通る所のとき + if (x < 0 || y < 0 || x >= treasureMap.getHeight() || y >= treasureMap.getWidth() + || treasureMap.isVisited(x, y)) { + return; + } + + // ゴールのとき + if (x == treasureMap.getWorld().length - 1 && y == treasureMap.getWorld()[0].length - 1) { + allPaths.add(path + treasureMap.getWorld()[x][y]); + return; + } + + treasureMap.mark(x, y); + + path += treasureMap.getWorld()[x][y]; + + for (Direction direction : Direction.values()) { + findPaths(x + direction.getX(), y + direction.getY(), path, treasureMap, allPaths); + } + + treasureMap.erase(x, y); + + } + + private static void output(final Result result) { + System.out.println(result.getMessage()); + } + +} diff --git a/sitou/src/InputData.java b/sitou/src/InputData.java new file mode 100644 index 0000000000000000000000000000000000000000..fd402e34436f2382c6fb229523fb43d8c21f2c6c --- /dev/null +++ b/sitou/src/InputData.java @@ -0,0 +1,14 @@ +package src; + +public class InputData { + final int height; + final int width; + final String[] mapStatus; + + public InputData(final int height, final int width, final String[] mapStatus) { + this.height = height; + this.width = width; + this.mapStatus = mapStatus; + } + +} diff --git a/sitou/src/Result.java b/sitou/src/Result.java new file mode 100644 index 0000000000000000000000000000000000000000..8d026fdebf23b57846af3e6dcf438089079c282f --- /dev/null +++ b/sitou/src/Result.java @@ -0,0 +1,13 @@ +package src; + +public class Result { + final String message; + + Result(final String message) { + this.message = message; + } + + public final String getMessage() { + return message; + } +} diff --git a/sitou/src/TreasureMap.java b/sitou/src/TreasureMap.java new file mode 100644 index 0000000000000000000000000000000000000000..0e1fef040d19529457634c19f2602c72a7c9d303 --- /dev/null +++ b/sitou/src/TreasureMap.java @@ -0,0 +1,52 @@ +package src; + +public class TreasureMap { + final int height; + final int width; + final char[][] world; + final boolean[][] visited; + + public TreasureMap(InputData inputData) { + height = inputData.height; + width = inputData.width; + world = new char[getHeight()][getWidth()]; + visited = new boolean[getHeight()][getWidth()]; + + // scanした文字列を分解して1文字1マスで扱えるようにする + for (int i = 0; i < getHeight(); i++) { + String text = inputData.mapStatus[i]; + for (int j = 0; j < getWidth(); j++) { + getWorld()[i][j] = text.charAt(j); + } + } + } + + public void mark(final int x, final int y) { + visited[x][y] = true; + } + + public void erase(final int x, final int y) { + visited[x][y] = false; + } + + public final int getHeight() { + return height; + } + + public int getWidth() { + return width; + } + + public final char[][] getWorld() { + return world; + } + + public final boolean isVisited(final int x, final int y) { + return visited[x][y]; + } + + public final char get(final int x, final int y) { + return world[x][y]; + + } +} diff --git a/sitou/test/A083_Test.java b/sitou/test/A083_Test.java new file mode 100644 index 0000000000000000000000000000000000000000..c253510393cc44df73283770c821c2e1aaf37dd0 --- /dev/null +++ b/sitou/test/A083_Test.java @@ -0,0 +1,57 @@ +package test; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import org.junit.Test; +import src.A083_SecretMessage; +import src.InputData; +import src.Result; +import src.TreasureMap; + +public class A083_Test { + @Test + public void 正しく探索できるかテスト() { + + final String[] mapStatus = { + "hello", "paiza", "world" + }; + final InputData inputData = new InputData(3, 5, mapStatus); + TreasureMap treasureMap = new TreasureMap(inputData); + final Result result = A083_SecretMessage.solve(treasureMap); + String actual = result.getMessage(); + + final String expected = "heailload"; + + assertThat(actual, is(expected)); + } + + public void 辞書順で最も小さいメッセージを探索できるかテスト1() { + + final String[] mapStatus = { + "abc", "bcx", "cyz" + }; + final InputData inputData = new InputData(3, 3, mapStatus); + TreasureMap treasureMap = new TreasureMap(inputData); + final Result result = A083_SecretMessage.solve(treasureMap); + String actual = result.getMessage(); + + final String expected = "abcbcxz"; + + assertThat(actual, is(expected)); + } + + public void 辞書順で最も小さいメッセージを探索できるかテスト2() { + + final String[] mapStatus = { + "xabcd", "abcde", "bddea", "cdeab", "deabc", "eabcd" + }; + final InputData inputData = new InputData(6, 5, mapStatus); + TreasureMap treasureMap = new TreasureMap(inputData); + final Result result = A083_SecretMessage.solve(treasureMap); + String actual = result.getMessage(); + + final String expected = "xababcdcddbcdeabababcd"; + + assertThat(actual, is(expected)); + } +} diff --git a/sitou/test/TreasureMapTest.java b/sitou/test/TreasureMapTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cbaaedfce5bc365a1a01c4310933d82d0d0ec331 --- /dev/null +++ b/sitou/test/TreasureMapTest.java @@ -0,0 +1,75 @@ +package test; + +import static org.junit.Assert.*; +import org.junit.Test; +import src.InputData; +import src.TreasureMap; + +public class TreasureMapTest { + @Test + public void マスごとに正しく分割できるかテスト() { + + final String[] mapStatus = { + "hello", "paiza", "world" + }; + InputData input = new InputData(3, 5, mapStatus); + TreasureMap actual = new TreasureMap(input); + + final char[][] expected = { + { + 'h', 'e', 'l', 'l', 'o' + }, { + 'p', 'a', 'i', 'z', 'a' + }, { + 'w', 'o', 'r', 'l', 'd' + } + }; + + assertArrayEquals(actual.getWorld(), expected); + + } + + @Test + public void 秘境の大きさが最小の時に正しく分割できるかテスト() { + final String[] mapStatus = { + "a" + }; + InputData input = new InputData(1, 1, mapStatus); + TreasureMap actual = new TreasureMap(input); + + final char[][] expected = { + { + 'a' + } + }; + + assertArrayEquals(actual.getWorld(), expected); + } + + @Test + public void 秘境の大きさが最大の時に正しく分割できるかテスト() { + final String[] mapStatus = { + "abcde", "fghij", "klmno", "pqrst", "uvwxy", "zzzzz" + }; + InputData input = new InputData(6, 5, mapStatus); + TreasureMap actual = new TreasureMap(input); + + final char[][] expected = { + { + 'a', 'b', 'c', 'd', 'e' + }, { + 'f', 'g', 'h', 'i', 'j' + }, { + 'k', 'l', 'm', 'n', 'o' + }, { + 'p', 'q', 'r', 's', 't' + }, { + 'u', 'v', 'w', 'x', 'y' + }, { + 'z', 'z', 'z', 'z', 'z' + } + }; + + assertArrayEquals(actual.getWorld(), expected); + } +}