diff --git a/syamauchi/src/B134.java b/syamauchi/src/B134.java new file mode 100644 index 0000000000000000000000000000000000000000..3232c3a43221458212c5859ffa8f700235126650 --- /dev/null +++ b/syamauchi/src/B134.java @@ -0,0 +1,235 @@ +package src; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +/** + * B134種まきシミュレーション ドローンの高さと座標から畑に種をまく場所をカウントして表示する. + */ +public class B134 { + + private static final int RANGE = 2; + private static final int NO_SEED = 0; + private final int fieldHeight; + private final int fieldWidth; + + public B134(final int fieldHeight, final int fieldWidth) { + this.fieldHeight = fieldHeight; + this.fieldWidth = fieldWidth; + } + + /** + * 入力を受け取りカウント後の畑を表示. + */ + public static void main(final String[] args) { + final Scanner sc = new Scanner(System.in); + final int fieldHeight = sc.nextInt(); + final int fieldWidth = sc.nextInt(); + final int times = sc.nextInt(); + + final B134 seedingSimulation = new B134(fieldHeight, fieldWidth); + List> seededField = seedingSimulation.createField(); + for (int i = 0; i < times; i++) { + seededField = seedingSimulation + .seedingField(sc.nextInt(), sc.nextInt(), sc.nextInt(), seededField); + } + System.out.println(seedingSimulation.toStringField(seededField)); + sc.close(); + } + + /** + * 種まきされる前の畑の作成. 種まき前の畑はリスト内が0で埋まっている. + + * @return 種まき前の畑のリスト + */ + public List> createField() { + final List> fields = new ArrayList>(); + for (int i = 0; i < this.fieldHeight; i++) { + final List field = new ArrayList(); + for (int j = 0; j < this.fieldWidth; j++) { + + field.add(NO_SEED); + } + fields.add(field); + } + return fields; + } + + /** + * 引数に置いた畑のコピーを作成. + + * @param field コピーされる畑のリスト + * @return コピーした畑のリスト + */ + public List> cloneField(final List> field) { + final List> clone = new ArrayList>(); + for (int i = 0; i < this.fieldHeight; i++) { + clone.add(new ArrayList(field.get(i))); + } + return clone; + } + + /** + * 畑の範囲内であるかどうかの判定. + + * @param x 縦の座標 + * @param y 横の座標 + * @param field 畑のリスト + * + * @return 引数の座標は畑の中であればtrue、畑の外であればfalseを返す + * + */ + private boolean isField(final int x, final int y, final List> field) { + return field.get(0).size() > y && y >= 0 && field.size() > x && x >= 0; + } + + /** + * 畑を表示String型に変更する. + + * @param seedingField 種まき後の畑 + * @return String型の種まき後の畑 + */ + public String toStringField(final List> seedingField) { + final StringBuilder FieldText = new StringBuilder(); + for (int i = 0; i < this.fieldHeight; i++) { + for (int j = 0; j < this.fieldWidth; j++) { + if (j == this.fieldWidth - 1) { + FieldText + .append(seedingField.get(i).get(j) + + "\n"); + } else { + FieldText + .append(seedingField.get(i).get(j) + + " "); + } + } + } + return FieldText.toString(); + } + + /** + * 種まきをするメソッド. + + * @param droneHeight ドローンの高さ + * @param droneX ドローンの座標 + * @param droneY ドローンの座標 + * @param field 種まきを行う畑 + * + * @return 種まき後の畑を返す + */ + public List> seedingField(final int droneHeight, final int droneX, + final int droneY, final List> field) { + List> nowField = cloneField(field); + + final int position_x = droneX - 1; + final int position_y = droneY - 1; + /* + * 種まきされる場所はドローンの座標を中心として一辺が高さと同じ数になる場所のため ドローンの座標から(ドローンの高さ/2)マス目の座標 + */ + final int roundDownRadius = droneHeight / RANGE; + final int upper = position_y - roundDownRadius; + final int lower = position_y + roundDownRadius; + final int left = position_x - roundDownRadius; + final int right = position_x + roundDownRadius; + // ドローンの座標に種まきがされるとき + if (roundDownRadius == 0 && isField(position_y, position_x, nowField)) { + int seed = nowField.get(position_y).get(position_x); + seed++; + nowField.get(position_y).set(position_x, seed); + } else { + // 高さが3以上の時 + for (int x = left; x <= right; x++) { + nowField = seedingHorizontalways(position_y, x, roundDownRadius, nowField); + } + for (int y = upper; y <= lower; y++) { + + nowField = seedingVerticalways(y, position_x, roundDownRadius, nowField); + } + // 四隅は1回余分にカウントされるため1減らす + + nowField = decreaseCorner(upper, right, nowField); + nowField = decreaseCorner(lower, right, nowField); + nowField = decreaseCorner(upper, left, nowField); + nowField = decreaseCorner(lower, left, nowField); + } + + return nowField; + } + + /** + * 横方向の種まき. + + * @param py 縦の座標 + * @param px 横の座標 + * @param roundDownRadius ドローンの座標から種まきをする座標までの距離 + * + * @return 種まき後の畑のリスト + */ + private List> seedingHorizontalways(final int py, final int px, + final int roundDownRadius, + final List> field) { + int seed; + if (isField(py - roundDownRadius, px, field)) { + + seed = field.get(py - roundDownRadius).get(px); + seed++; + field.get(py - roundDownRadius).set(px, seed); + } + + if (isField(py + roundDownRadius, px, field)) { + + seed = field.get(py + roundDownRadius).get(px); + seed++; + field.get(py + roundDownRadius).set(px, seed); + } + return field; + } + + /** + * 縦方向の種まき. + + * @param py 縦の座標 + * @param px 横の座標 + * @param roundDownRadius ドローンの座標から種まきをする座標までの距離 + * + * @return 種まき後の畑のリスト + */ + private List> seedingVerticalways(final int py, final int px, + final int roundDownRadius, + final List> field) { + int seed; + if (isField(py, px - roundDownRadius, field)) { + seed = field.get(py).get(px - roundDownRadius); + seed++; + field.get(py).set(px - roundDownRadius, seed); + } + + if (isField(py, px + roundDownRadius, field)) { + seed = field.get(py).get(px + roundDownRadius); + seed++; + field.get(py).set(px + roundDownRadius, seed); + } + return field; + } + + /** + * 角のカウントをへらす. + + * @param py 縦の座標 + * @param px 横の座標 + * @param field 畑のリスト + * + * @return 余分にカウントしたものを抜いた畑のリスト + */ + private List> decreaseCorner(final int py, final int px, + final List> field) { + if (isField(py, px, field)) { + int seed = field.get(py).get(px); + seed--; + field.get(py).set(px, seed); + } + return field; + } + +} diff --git a/syamauchi/test/B134Test.java b/syamauchi/test/B134Test.java new file mode 100644 index 0000000000000000000000000000000000000000..44142929019bcc4f953fa6c887c7361a027eaff0 --- /dev/null +++ b/syamauchi/test/B134Test.java @@ -0,0 +1,83 @@ +package test; + +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; +import src.B134; + +/** + * B134種まきシミュレーションのテスト. + */ + +public class B134Test { + + @Test + public void 正しく種まきがされるテスト() { + + final B134 sut = new B134(4, 6); + List> actual = sut.createField(); + + actual = sut.seedingField(3, 3, 2, actual); + actual = sut.seedingField(1, 6, 1, actual); + actual = sut.seedingField(5, 6, 4, actual); + + final List> expected = new ArrayList>( + Arrays.asList( + new ArrayList(Arrays.asList(0, 1, 1, 1, 0, 1)), + new ArrayList(Arrays.asList(0, 1, 0, 2, 1, 1)), + new ArrayList(Arrays.asList(0, 1, 1, 2, 0, 0)), + new ArrayList(Arrays.asList(0, 0, 0, 1, 0, 0)))); + + assertThat(actual, is(expected)); + } + + // 畑の区画の範囲は1<=height,width<=100 + @Test + public void 畑の区画が最小の時に正しく種まきされるテスト() { + + final B134 sut = new B134(1, 1); + List> actual = sut.createField(); + actual = sut.seedingField(1, 1, 1, actual); + final List> expected = new ArrayList>( + Arrays.asList( + new ArrayList(Arrays.asList(1)))); + + assertThat(actual, is(expected)); + } + + @Test + public void 畑の区画が最大の時に正しく畑が作成されるテスト() { + + final B134 sut = new B134(100, 100); + List> actual = sut.createField(); + actual = sut.seedingField(1, 1, 1, actual); + final int expectedSize = 100; + final int expectedCount = 1; + + assertThat(actual.size(), is(expectedSize)); + assertThat(actual.get(0).size(), is(expectedSize)); + assertThat(actual.get(0).get(0), is(expectedCount)); + } + + @Test + public void 畑の区画が種まき後にshowFieldで正しく表示されるテスト() { + + final B134 sut = new B134(4, 6); + List> field = sut.createField(); + + field = sut.seedingField(3, 3, 2, field); + field = sut.seedingField(1, 6, 1, field); + field = sut.seedingField(5, 6, 4, field); + final String actual = sut.toStringField(field); + final String expected = + "0 1 1 1 0 1\n" + + "0 1 0 2 1 1\n" + + "0 1 1 2 0 0\n" + + "0 0 0 1 0 0\n"; + assertThat(actual, is(expected)); + } + +}