From a886003adf9cad9525915da259bd9cd7aefcc128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=8E=E7=94=B0=20=E5=95=93=E4=BB=8B?= Date: Mon, 29 Aug 2022 10:06:14 +0900 Subject: [PATCH 1/2] =?UTF-8?q?B066=20=E8=89=B2=E3=81=AE=E3=83=91=E3=82=BA?= =?UTF-8?q?=E3=83=ABver1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- knoda/src/B066_ColorPuzzle.java | 180 +++++++++++++++++ knoda/test/B066_ColorPuzzleTest.java | 289 +++++++++++++++++++++++++++ 2 files changed, 469 insertions(+) create mode 100644 knoda/src/B066_ColorPuzzle.java create mode 100644 knoda/test/B066_ColorPuzzleTest.java diff --git a/knoda/src/B066_ColorPuzzle.java b/knoda/src/B066_ColorPuzzle.java new file mode 100644 index 0000000..aaa0b11 --- /dev/null +++ b/knoda/src/B066_ColorPuzzle.java @@ -0,0 +1,180 @@ +package hellojunit; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class B066_ColorPuzzle { + + public static void main(String[] args) { + final Scanner scan = new Scanner(System.in); + final int pieceNum = scan.nextInt(); + final int puzzleSize = scan.nextInt(); + final int pieceSize = scan.nextInt(); + + // パズルの完成形を入力する + final char[][] puzzle = new char[puzzleSize][puzzleSize]; + for (int i = 0; i < puzzleSize; i++) { + final String puzzleRow = scan.next(); + for (int j = 0; j < puzzleSize; j++) { + puzzle[i][j] = puzzleRow.charAt(j); + } + } + + // すべてのピースを入力する + final char[][][] pieceArray = new char[pieceNum][pieceSize][pieceSize]; + for (int pieceNo = 0; pieceNo < pieceNum; pieceNo++) { + for (int i = 0; i < pieceSize; i++) { + final String pieceRow = scan.next(); + for (int j = 0; j < pieceSize; j++) { + pieceArray[pieceNo][i][j] = pieceRow.charAt(j); + } + } + } + + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + // すべてのピースの配置情報を取得し、出力する + final List> pieceInfoList = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + for (final List pieceInfo : pieceInfoList) { + for (int i = 0; i < pieceInfo.size(); i++) { + if (i != pieceInfo.size() - 1) { + System.out.print(pieceInfo.get(i) + " "); + } else { + System.out.println(pieceInfo.get(i)); + } + } + } + scan.close(); + } +} + +class ColorPuzzle { + private final int pieceNum; + private final int puzzleSize; + private final int pieceSize; + private final int MAX_ANGLE_COUNT = 4; // ピースが回転する最大の数 + private final int NOT_MATCH = -1; // ピースがパズルの一部と等しくないときに返す値 + private final int NOT_FOUND = -1; // パズルに使用しないピースの情報 + + public ColorPuzzle(final int pieceNum, final int puzzleSize, final int pieceSize) { + this.pieceNum = pieceNum; + this.puzzleSize = puzzleSize; + this.pieceSize = pieceSize; + } + + /** + * すべてのピースの配置情報を取得するメソッド + * @param puzzle + * @param pieceArray + * @return pieceInfoList : すべてのピースの配置情報を格納したリスト + */ + public List> getPieceInfoList(final char[][] puzzle, final char[][][] pieceArray) { + List> pieceInfoList = new ArrayList>(); + for (int pieceNo = 0; pieceNo < pieceNum; pieceNo++) { + pieceInfoList = getFitPuzzle(puzzle, pieceArray, pieceNo, pieceInfoList); + } + return pieceInfoList; + } + + /** + * あるピースの配置情報を取得するメソッド + * @param puzzle + * @param pieceArray + * @param pieceNo : ピースの番号 + * @param pieceInfoList + * @return pieceInfoList + */ + private List> getFitPuzzle(final char[][] puzzle, final char[][][] pieceArray, + final int pieceNo, final List> pieceInfoList) { + boolean isFit = false; + final List pieceInfo = new ArrayList(); + for (int fitSpaceRow = 0; fitSpaceRow < puzzleSize / pieceSize; fitSpaceRow++) { + for (int fitSpaceColumn = 0; fitSpaceColumn < puzzleSize / pieceSize; fitSpaceColumn++) { + final char[][] piece = pieceArray[pieceNo]; + final int angleCount = getAngleCount(puzzle, piece, fitSpaceRow, fitSpaceColumn); + if (angleCount > NOT_MATCH) { + pieceInfo.add(fitSpaceRow * pieceSize + 1); // ピースの左上のマスのx座標 + pieceInfo.add(fitSpaceColumn * pieceSize + 1); // ピースの左上のマスのy座標 + pieceInfo.add(angleCount); // ピースを回転した回数 + pieceInfoList.add(pieceInfo); + isFit = true; + break; + } + } + if (isFit) { + break; + } + } + if (!isFit) { + pieceInfo.add(NOT_FOUND); // パズルに使用しないピースの情報 + pieceInfoList.add(pieceInfo); + } + return pieceInfoList; + } + + /** + * ピースが回転した回数を取得するメソッド + * @param puzzle + * @param piece + * @param fitSpaceRow : ピースを配置する大まかな場所(x座標) + * @param fitSpaceColumn : ピースを配置する大まかな場所(y座標) + * @return + */ + private int getAngleCount(final char[][] puzzle, char[][] piece, + final int fitSpaceRow, final int fitSpaceColumn) { + for (int count = 0; count < MAX_ANGLE_COUNT; count++) { + if (isMatch(puzzle, piece, fitSpaceRow, fitSpaceColumn)) { + return count; + } else { + piece = getAfterAnglePiece(piece); + } + } + return NOT_MATCH; + } + + /** + * ピースがパズルの一部と等しいか判定するメソッド + * @param puzzle + * @param piece + * @param fitSpaceRow + * @param fitSpaceColumn + * @return 等しい : true, 等しくない : false + */ + private boolean isMatch(final char[][] puzzle, final char[][] piece, + final int fitSpaceRow, final int fitSpaceColumn) { + final char[][] targetPiece = new char[pieceSize][pieceSize]; + int m = 0; + for (int i = pieceSize * fitSpaceRow; i < pieceSize * fitSpaceRow + pieceSize; i++) { + int n = 0; + for (int j = pieceSize * fitSpaceColumn; j < pieceSize * fitSpaceColumn + pieceSize; j++) { + targetPiece[m][n] = puzzle[i][j]; + n++; + } + m++; + } + + for (int i = 0; i < pieceSize; i++) { + for (int j = 0; j < pieceSize; j++) { + if (targetPiece[i][j] != piece[i][j]) { + return false; + } + } + } + return true; + } + + /** + * ピースを時計回りに90°回転するメソッド + * @param piece + * @return afterAnglePiece : 回転後のピース + */ + private char[][] getAfterAnglePiece(final char[][] piece) { + final char[][] afterAnglePiece = new char[pieceSize][pieceSize]; + for (int i = 0; i < pieceSize; i++) { + for (int j = 0; j < pieceSize; j++) { + afterAnglePiece[i][j] = piece[pieceSize - 1 - j][i]; + } + } + return afterAnglePiece; + } +} diff --git a/knoda/test/B066_ColorPuzzleTest.java b/knoda/test/B066_ColorPuzzleTest.java new file mode 100644 index 0000000..c233f87 --- /dev/null +++ b/knoda/test/B066_ColorPuzzleTest.java @@ -0,0 +1,289 @@ +package hellojunit; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; + +public class B066_ColorPuzzleTest { + + @Test + public void ピースが1つかつパズルのサイズが1x1かつピースのサイズが1x1のときにパズルが完成するテスト() { + final int pieceNum = 1; + final int puzzleSize = 1; + final int pieceSize = 1; + final char[][] puzzle = { + {'Y'} + }; + final char[][][] pieceArray = { + { + {'Y'} + } + }; + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + final List> actual = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + final List> expected = new ArrayList>(Arrays.asList( + new ArrayList(Arrays.asList(1, 1, 0)))); + assertThat(actual, is(expected)); + } + + @Test + public void ピースが1つかつパズルのサイズが1x1かつピースのサイズが1x1のときにパズルが完成しないテスト() { + final int pieceNum = 1; + final int puzzleSize = 1; + final int pieceSize = 1; + final char[][] puzzle = { + {'Y'} + }; + final char[][][] pieceArray = { + { + {'B'} + } + }; + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + final List> actual = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + final List> expected = new ArrayList>(Arrays.asList( + new ArrayList(Arrays.asList(-1)))); + assertThat(actual, is(expected)); + } + + @Test + public void ピースが1つかつパズルのサイズが100x100かつピースのサイズが100x100のときにパズルが完成するテスト() { + final int pieceNum = 1; + final int puzzleSize = 100; + final int pieceSize = 100; + final char[][] puzzle = new char[puzzleSize][puzzleSize]; + final char[][][] pieceArray = new char[pieceNum][pieceSize][pieceSize]; + + for (int i = 0; i < puzzleSize; i++) { + for (int j = 0; j < puzzleSize; j++) { + if (j < 50) { + puzzle[i][j] = 'Y'; + } else { + puzzle[i][j] = 'B'; + } + } + } + + for (int pieceNo = 0; pieceNo < pieceNum; pieceNo++) { + for (int i = 0; i < pieceSize; i++) { + for (int j = 0; j < pieceSize; j++) { + if (j < 50) { + pieceArray[pieceNo][i][j] = 'B'; + } else { + pieceArray[pieceNo][i][j] = 'Y'; + } + } + } + } + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + final List> actual = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + final List> expected = new ArrayList>(Arrays.asList( + new ArrayList(Arrays.asList(1, 1, 2)))); + assertThat(actual, is(expected)); + } + + @Test + public void ピースが1つかつパズルのサイズが100x100かつピースのサイズが100x100のときにパズルが完成しないテスト() { + final int pieceNum = 1; + final int puzzleSize = 100; + final int pieceSize = 100; + final char[][] puzzle = new char[puzzleSize][puzzleSize]; + final char[][][] pieceArray = new char[pieceNum][pieceSize][pieceSize]; + + for (int i = 0; i < puzzleSize; i++) { + for (int j = 0; j < puzzleSize; j++) { + if (j < 50) { + puzzle[i][j] = 'Y'; + } else { + puzzle[i][j] = 'B'; + } + } + } + + for (int pieceNo = 0; pieceNo < pieceNum; pieceNo++) { + for (int i = 0; i < pieceSize; i++) { + for (int j = 0; j < pieceSize; j++) { + pieceArray[pieceNo][i][j] = 'B'; + } + } + } + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + final List> actual = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + final List> expected = new ArrayList>(Arrays.asList( + new ArrayList(Arrays.asList(-1)))); + assertThat(actual, is(expected)); + } + + @Test + public void ピースが100かつパズルのサイズが100x100かつピースのサイズが100x100のときのテスト() { + final int pieceNum = 100; + final int puzzleSize = 100; + final int pieceSize = 100; + final char[][] puzzle = new char[puzzleSize][puzzleSize]; + final char[][][] pieceArray = new char[pieceNum][pieceSize][pieceSize]; + + for (int i = 0; i < puzzleSize; i++) { + for (int j = 0; j < puzzleSize; j++) { + if (i == 0 && j == puzzleSize - 1) { + puzzle[i][j] = 'Y'; + } else { + puzzle[i][j] = 'B'; + } + } + } + + for (int pieceNo = 0; pieceNo < pieceNum; pieceNo++) { + for (int i = 0; i < pieceSize; i++) { + for (int j = 0; j < pieceSize; j++) { + if (i == 0 && j == pieceNo) { + pieceArray[pieceNo][i][j] = 'Y'; + } else { + pieceArray[pieceNo][i][j] = 'B'; + } + } + } + } + + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + final List> actual = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + final List> expected = new ArrayList>(); + for (int pieceNo = 0; pieceNo < pieceNum; pieceNo++) { + if (pieceNo == 0) { + expected.add(new ArrayList(Arrays.asList(1, 1, 1))); + } else if (pieceNo == pieceNum - 1) { + expected.add(new ArrayList(Arrays.asList(1, 1, 0))); + } else { + expected.add(new ArrayList(Arrays.asList(-1))); + } + } + assertThat(actual, is(expected)); + } + + @Test + public void 基本テスト1() { + final int pieceNum = 4; + final int puzzleSize = 4; + final int pieceSize = 2; + final char[][] puzzle = { + {'Y', 'B', 'B', 'Y'}, + {'Y', 'Y', 'Y', 'B'}, + {'B', 'B', 'Y', 'B'}, + {'Y', 'B', 'Y', 'B'} + }; + final char[][][] pieceArray = { + { + {'B', 'Y'}, + {'B', 'B'} + }, + { + {'Y', 'B'}, + {'Y', 'B'} + }, + { + {'Y', 'B'}, + {'Y', 'Y'} + }, + { + {'B', 'Y'}, + {'Y', 'B'} + } + }; + + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + final List> actual = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + final List> expected = new ArrayList>(Arrays.asList( + new ArrayList(Arrays.asList(3, 1, 2)), + new ArrayList(Arrays.asList(3, 3, 0)), + new ArrayList(Arrays.asList(1, 1, 0)), + new ArrayList(Arrays.asList(1, 3, 0)))); + assertThat(actual, is(expected)); + } + + @Test + public void 基本テスト2() { + final int pieceNum = 10; + final int puzzleSize = 6; + final int pieceSize = 3; + final char[][] puzzle = { + {'Y', 'Y', 'Y', 'B', 'Y', 'B'}, + {'B', 'Y', 'Y', 'B', 'B', 'B'}, + {'B', 'Y', 'Y', 'B', 'B', 'B'}, + {'B', 'Y', 'Y', 'B', 'Y', 'B'}, + {'B', 'B', 'Y', 'Y', 'Y', 'Y'}, + {'Y', 'Y', 'Y', 'Y', 'Y', 'B'} + }; + final char[][][] pieceArray = { + { + {'Y', 'Y', 'B'}, + {'B', 'B', 'Y'}, + {'B', 'Y', 'B'} + }, + { + {'B', 'B', 'Y'}, + {'Y', 'B', 'B'}, + {'B', 'Y', 'B'} + }, + { + {'B', 'B', 'Y'}, + {'Y', 'B', 'B'}, + {'Y', 'Y', 'B'} + }, + { + {'B', 'B', 'B'}, + {'B', 'B', 'B'}, + {'B', 'Y', 'B'} + }, + { + {'B', 'Y', 'B'}, + {'B', 'Y', 'B'}, + {'Y', 'Y', 'B'} + }, + { + {'Y', 'Y', 'Y'}, + {'Y', 'Y', 'Y'}, + {'Y', 'B', 'Y'} + }, + { + {'Y', 'Y', 'Y'}, + {'Y', 'B', 'B'}, + {'Y', 'Y', 'B'} + }, + { + {'Y', 'Y', 'B'}, + {'Y', 'Y', 'B'}, + {'Y', 'Y', 'Y'} + }, + { + {'Y', 'Y', 'B'}, + {'Y', 'Y', 'Y'}, + {'B', 'Y', 'B'} + }, + { + {'B', 'B', 'B'}, + {'Y', 'Y', 'B'}, + {'B', 'Y', 'Y'} + } + }; + + final ColorPuzzle colorPuzzle = new ColorPuzzle(pieceNum, puzzleSize, pieceSize); + final List> actual = colorPuzzle.getPieceInfoList(puzzle, pieceArray); + final List> expected = new ArrayList>(Arrays.asList( + new ArrayList(Arrays.asList(-1)), + new ArrayList(Arrays.asList(-1)), + new ArrayList(Arrays.asList(-1)), + new ArrayList(Arrays.asList(1, 4, 2)), + new ArrayList(Arrays.asList(-1)), + new ArrayList(Arrays.asList(-1)), + new ArrayList(Arrays.asList(4, 1, 2)), + new ArrayList(Arrays.asList(1, 1, 2)), + new ArrayList(Arrays.asList(4, 4, 3)), + new ArrayList(Arrays.asList(-1)))); + assertThat(actual, is(expected)); + } + +} -- GitLab From 11152bd41e7edde85a8ea6c0f3f48178a56a9bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=8E=E7=94=B0=20=E5=95=93=E4=BB=8B?= Date: Mon, 29 Aug 2022 16:41:26 +0900 Subject: [PATCH 2/2] =?UTF-8?q?B066=20=E8=89=B2=E3=81=AE=E3=83=91=E3=82=BA?= =?UTF-8?q?=E3=83=ABver1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- knoda/src/B066_ColorPuzzle.java | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/knoda/src/B066_ColorPuzzle.java b/knoda/src/B066_ColorPuzzle.java index aaa0b11..4a0433b 100644 --- a/knoda/src/B066_ColorPuzzle.java +++ b/knoda/src/B066_ColorPuzzle.java @@ -52,7 +52,7 @@ class ColorPuzzle { private final int pieceNum; private final int puzzleSize; private final int pieceSize; - private final int MAX_ANGLE_COUNT = 4; // ピースが回転する最大の数 + private final int MAX_ANGLE_COUNT = 3; // ピースが回転する最大の数 private final int NOT_MATCH = -1; // ピースがパズルの一部と等しくないときに返す値 private final int NOT_FOUND = -1; // パズルに使用しないピースの情報 @@ -91,8 +91,8 @@ class ColorPuzzle { for (int fitSpaceRow = 0; fitSpaceRow < puzzleSize / pieceSize; fitSpaceRow++) { for (int fitSpaceColumn = 0; fitSpaceColumn < puzzleSize / pieceSize; fitSpaceColumn++) { final char[][] piece = pieceArray[pieceNo]; - final int angleCount = getAngleCount(puzzle, piece, fitSpaceRow, fitSpaceColumn); - if (angleCount > NOT_MATCH) { + final int angleCount = getRotateCount(puzzle, piece, fitSpaceRow, fitSpaceColumn); + if (angleCount != NOT_MATCH) { pieceInfo.add(fitSpaceRow * pieceSize + 1); // ピースの左上のマスのx座標 pieceInfo.add(fitSpaceColumn * pieceSize + 1); // ピースの左上のマスのy座標 pieceInfo.add(angleCount); // ピースを回転した回数 @@ -120,13 +120,13 @@ class ColorPuzzle { * @param fitSpaceColumn : ピースを配置する大まかな場所(y座標) * @return */ - private int getAngleCount(final char[][] puzzle, char[][] piece, + private int getRotateCount(final char[][] puzzle, char[][] piece, final int fitSpaceRow, final int fitSpaceColumn) { - for (int count = 0; count < MAX_ANGLE_COUNT; count++) { + for (int count = 0; count <= MAX_ANGLE_COUNT; count++) { if (isMatch(puzzle, piece, fitSpaceRow, fitSpaceColumn)) { return count; } else { - piece = getAfterAnglePiece(piece); + piece = getAfterRotatePiece(piece); } } return NOT_MATCH; @@ -166,15 +166,15 @@ class ColorPuzzle { /** * ピースを時計回りに90°回転するメソッド * @param piece - * @return afterAnglePiece : 回転後のピース + * @return afterRotatePiece : 回転後のピース */ - private char[][] getAfterAnglePiece(final char[][] piece) { - final char[][] afterAnglePiece = new char[pieceSize][pieceSize]; + private char[][] getAfterRotatePiece(final char[][] piece) { + final char[][] afterRotatePiece = new char[pieceSize][pieceSize]; for (int i = 0; i < pieceSize; i++) { for (int j = 0; j < pieceSize; j++) { - afterAnglePiece[i][j] = piece[pieceSize - 1 - j][i]; + afterRotatePiece[i][j] = piece[pieceSize - 1 - j][i]; } } - return afterAnglePiece; + return afterRotatePiece; } } -- GitLab