Solutions for exercices about counting trapped water on islands












0














There are some exercises about islands and water. I have seen ready solutions on Java, but they are developed in procedural style in one-two methods. I tried to develop an object oriented solutions with code reuse. It is posted on GitHub, but the rules of this portal ask me to post the code here. I have never get code reviews before, so I would happy to see any suggestions to improve my code. Also sorry for my bad English.





Exercise 1.




There is a beach with a ground configuration like 
[ 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 ].
A wave come from a sea to the left of the beach.
Its height is 5, for example.
Then the wave come back to the sea.
In the beach's hollows we find trapped water.
If the wave is higher than beach it covers the full beach
and goes away to both directions.
Task: write a program for counting all trapped water
on the whole beach.





Exercise 2.




There is an island with a ground configuration like
[
[ 5, 3, 4, 5 ],
[ 6, 2, 1, 4 ],
[ 3, 1, 1, 4 ],
[ 8, 5, 4, 3 ]
]
A rain was many days.
It filled by water every hollow in the island.
Water can go away only to 4 directions:
north, south, west, east.
Task: write a program for counting
all trapped water in whole island.
For example, the answer for a given configuration is 7.





At first, I developed the common class for a single column of land with water on it:



package trappedwater;

import java.util.Arrays;

public class LithosphereSection {

/* Height is above mean sea level in each case */
public final int groundHeight;
private int waterHeight;

public LithosphereSection(int _groundHeight) {
this.groundHeight = _groundHeight;
this.waterHeight = 0;
}

public void setWaterHeight(int _waterHeight) {
this.waterHeight = _waterHeight;
}

public void extraWaterPourOff(LithosphereSection... neighborSections) {
if (hasPrecipiceForWater(neighborSections)) {
this.waterHeight = 0;
} else {
for (LithosphereSection neighbor : neighborSections) {
int support = Integer.max(neighbor.waterHeight, neighbor.groundHeight);
this.waterHeight = Integer.min(this.waterHeight, support);
}
}
}

private boolean hasPrecipiceForWater(LithosphereSection... neighborSections) {
return neighborSections == null
|| neighborSections.length == 0
|| Arrays.asList(neighborSections).contains(null);
}

public int getTrappedWater() {
int trappedWater = this.waterHeight - this.groundHeight;
return (trappedWater > 0) ? trappedWater : 0;
}
}




Then I solved the first exercise.



package trappedwater;

public class Beach {

private final LithosphereSection litSections;
private final int m; // alias to litSections.length

public Beach(int _groundScheme) {
this.m = _groundScheme.length;
this.litSections = new LithosphereSection[this.m];
for (int i = 0; i < this.m; i++) {
this.litSections[i] = new LithosphereSection(_groundScheme[i]);
}
}

public void takeWaveFromLeft(int _waveHeight) {
boolean waveStillMoves = true;
for (int i = 0; i < this.m; i++) {
if (waveStillMoves) {
if (_waveHeight > this.litSections[i].groundHeight) {
this.litSections[i].setWaterHeight(_waveHeight);
} else {
waveStillMoves = false;
}
}
}
}

public void extraWaterPourOff() {
// Pour water on boarders
this.litSections[0].extraWaterPourOff();
this.litSections[this.m - 1].extraWaterPourOff();

// Pour water to the left
for (int i = 1; i < this.m - 1; i++) {
this.litSections[i].extraWaterPourOff(this.litSections[i - 1]);
}

// Pour water to the right
for (int i = this.m - 2; i > 0; i--) {
this.litSections[i].extraWaterPourOff(this.litSections[i + 1]);
}
}

public int getTrappedWater() {
int sumWater = 0;
for (LithosphereSection litSection : this.litSections) {
sumWater += litSection.getTrappedWater();
}
return sumWater;
}

public void dry() {
for (int i = 0; i < this.m; i++) {
this.litSections[i].setWaterHeight(0);
}
}
}




And the second one



package trappedwater;

public class Island {

private final LithosphereSection litSections;
private final int n; // rows
private final int m; // columns
private int highestGround;

public Island(int _groundScheme) {
this.n = _groundScheme.length;
this.m = _groundScheme[0].length;

this.litSections = new LithosphereSection[this.n][this.m];
this.highestGround = _groundScheme[0][0];
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j] = new LithosphereSection(_groundScheme[i][j]);
this.highestGround = Integer.max(this.highestGround, _groundScheme[i][j]);
}
}
}

public void overfillByWater() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j].setWaterHeight(this.highestGround);
}
}
}

public void extraWaterPourOff() {
pourOffBoarders();
boolean countOfPuddlesChanges = true;
while (countOfPuddlesChanges) {
int countOfPuddlesBefore = getTrappedWater();
pourOffToNorthLeft();
pourOffToSouthRight();
countOfPuddlesChanges = (getTrappedWater() != countOfPuddlesBefore);
}
}

private void pourOffBoarders() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
boolean isBorder = (i == 0) || (i == this.n - 1) || (j == 0) || (j == this.m - 1);
if (isBorder) {
this.litSections[i][j].extraWaterPourOff();
}
}
}
}

private void pourOffToNorthLeft() {
for (int i = 1; i < this.n - 1; i++) {
for (int j = 1; j < this.m - 1; j++) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j - 1],
this.litSections[i - 1][j]
);
}
}
}

private void pourOffToSouthRight() {
for (int i = this.n - 2; i > 0; i--) {
for (int j = this.m - 2; j > 0; j--) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j + 1],
this.litSections[i + 1][j]
);
}
}
}

public int getTrappedWater() {
int sumWater = 0;
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
sumWater += this.litSections[i][j].getTrappedWater();
}
}
return sumWater;
}
}




Finally I made 3 classes with JUnit5 tests:



package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class LithosphereSectionTest {

static LithosphereSection testLitSection;

@BeforeAll
static void setUpBeforeClass() throws Exception {
testLitSection = new LithosphereSection(5);
}

@BeforeEach
void setUp() throws Exception {
testLitSection.setWaterHeight(10);
}

@Test
void test01() {
assertEquals(5, testLitSection.getTrappedWater());
}

@Test
void test02() {
LithosphereSection litSection2 = new LithosphereSection(7);
LithosphereSection litSection3 = new LithosphereSection(8);
LithosphereSection litSection4 = new LithosphereSection(6);
litSection4.setWaterHeight(7);

testLitSection.extraWaterPourOff(litSection2, litSection3, litSection4);
assertEquals(2, testLitSection.getTrappedWater());
}

@Test
void test03() {
testLitSection.extraWaterPourOff();
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test04() {
LithosphereSection sections = null;
testLitSection.extraWaterPourOff(sections);
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test05() {
LithosphereSection litSection2 = null;
testLitSection.extraWaterPourOff(litSection2);
assertEquals(0, testLitSection.getTrappedWater());
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class BeachTest {

static Beach beach;

@BeforeAll
static void setUpBeforeClass() throws Exception {
int groundScheme = new int { 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 };
beach = new Beach(groundScheme);
}

private int run(int waveHeight) {
beach.dry();
beach.takeWaveFromLeft(waveHeight);
beach.extraWaterPourOff();
return beach.getTrappedWater();
}

@Test
void test() {
assertEquals(0, run(1));
assertEquals(0, run(2));
assertEquals(0, run(3));
assertEquals(1, run(4));
assertEquals(1, run(5));
assertEquals(6, run(6));
assertEquals(6, run(7));
assertEquals(8, run(8));
assertEquals(8, run(9));
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class IslandTest {

private int run(int _groundScheme) {
Island island = new Island(_groundScheme);
island.overfillByWater();
island.extraWaterPourOff();
return island.getTrappedWater();
}

@Test
void test01() {
int groundScheme = new int {
{ 5, 3, 4, 5 },
{ 6, 2, 1, 4 },
{ 3, 1, 1, 4 },
{ 8, 5, 4, 3 }
};
assertEquals(7, run(groundScheme));
}

@Test
void test02() {
int groundScheme = new int {
{ 8, 6, 8, 8 },
{ 8, 2, 2, 4 },
{ 8, 2, 2, 8 },
{ 8, 8, 8, 8 }
};
assertEquals(8, run(groundScheme));
}
}









share|improve this question









New contributor




AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • Tests help reviewers tremendously when reviewing your code. If you have them you should definitely provide them.
    – bruglesco
    39 mins ago
















0














There are some exercises about islands and water. I have seen ready solutions on Java, but they are developed in procedural style in one-two methods. I tried to develop an object oriented solutions with code reuse. It is posted on GitHub, but the rules of this portal ask me to post the code here. I have never get code reviews before, so I would happy to see any suggestions to improve my code. Also sorry for my bad English.





Exercise 1.




There is a beach with a ground configuration like 
[ 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 ].
A wave come from a sea to the left of the beach.
Its height is 5, for example.
Then the wave come back to the sea.
In the beach's hollows we find trapped water.
If the wave is higher than beach it covers the full beach
and goes away to both directions.
Task: write a program for counting all trapped water
on the whole beach.





Exercise 2.




There is an island with a ground configuration like
[
[ 5, 3, 4, 5 ],
[ 6, 2, 1, 4 ],
[ 3, 1, 1, 4 ],
[ 8, 5, 4, 3 ]
]
A rain was many days.
It filled by water every hollow in the island.
Water can go away only to 4 directions:
north, south, west, east.
Task: write a program for counting
all trapped water in whole island.
For example, the answer for a given configuration is 7.





At first, I developed the common class for a single column of land with water on it:



package trappedwater;

import java.util.Arrays;

public class LithosphereSection {

/* Height is above mean sea level in each case */
public final int groundHeight;
private int waterHeight;

public LithosphereSection(int _groundHeight) {
this.groundHeight = _groundHeight;
this.waterHeight = 0;
}

public void setWaterHeight(int _waterHeight) {
this.waterHeight = _waterHeight;
}

public void extraWaterPourOff(LithosphereSection... neighborSections) {
if (hasPrecipiceForWater(neighborSections)) {
this.waterHeight = 0;
} else {
for (LithosphereSection neighbor : neighborSections) {
int support = Integer.max(neighbor.waterHeight, neighbor.groundHeight);
this.waterHeight = Integer.min(this.waterHeight, support);
}
}
}

private boolean hasPrecipiceForWater(LithosphereSection... neighborSections) {
return neighborSections == null
|| neighborSections.length == 0
|| Arrays.asList(neighborSections).contains(null);
}

public int getTrappedWater() {
int trappedWater = this.waterHeight - this.groundHeight;
return (trappedWater > 0) ? trappedWater : 0;
}
}




Then I solved the first exercise.



package trappedwater;

public class Beach {

private final LithosphereSection litSections;
private final int m; // alias to litSections.length

public Beach(int _groundScheme) {
this.m = _groundScheme.length;
this.litSections = new LithosphereSection[this.m];
for (int i = 0; i < this.m; i++) {
this.litSections[i] = new LithosphereSection(_groundScheme[i]);
}
}

public void takeWaveFromLeft(int _waveHeight) {
boolean waveStillMoves = true;
for (int i = 0; i < this.m; i++) {
if (waveStillMoves) {
if (_waveHeight > this.litSections[i].groundHeight) {
this.litSections[i].setWaterHeight(_waveHeight);
} else {
waveStillMoves = false;
}
}
}
}

public void extraWaterPourOff() {
// Pour water on boarders
this.litSections[0].extraWaterPourOff();
this.litSections[this.m - 1].extraWaterPourOff();

// Pour water to the left
for (int i = 1; i < this.m - 1; i++) {
this.litSections[i].extraWaterPourOff(this.litSections[i - 1]);
}

// Pour water to the right
for (int i = this.m - 2; i > 0; i--) {
this.litSections[i].extraWaterPourOff(this.litSections[i + 1]);
}
}

public int getTrappedWater() {
int sumWater = 0;
for (LithosphereSection litSection : this.litSections) {
sumWater += litSection.getTrappedWater();
}
return sumWater;
}

public void dry() {
for (int i = 0; i < this.m; i++) {
this.litSections[i].setWaterHeight(0);
}
}
}




And the second one



package trappedwater;

public class Island {

private final LithosphereSection litSections;
private final int n; // rows
private final int m; // columns
private int highestGround;

public Island(int _groundScheme) {
this.n = _groundScheme.length;
this.m = _groundScheme[0].length;

this.litSections = new LithosphereSection[this.n][this.m];
this.highestGround = _groundScheme[0][0];
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j] = new LithosphereSection(_groundScheme[i][j]);
this.highestGround = Integer.max(this.highestGround, _groundScheme[i][j]);
}
}
}

public void overfillByWater() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j].setWaterHeight(this.highestGround);
}
}
}

public void extraWaterPourOff() {
pourOffBoarders();
boolean countOfPuddlesChanges = true;
while (countOfPuddlesChanges) {
int countOfPuddlesBefore = getTrappedWater();
pourOffToNorthLeft();
pourOffToSouthRight();
countOfPuddlesChanges = (getTrappedWater() != countOfPuddlesBefore);
}
}

private void pourOffBoarders() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
boolean isBorder = (i == 0) || (i == this.n - 1) || (j == 0) || (j == this.m - 1);
if (isBorder) {
this.litSections[i][j].extraWaterPourOff();
}
}
}
}

private void pourOffToNorthLeft() {
for (int i = 1; i < this.n - 1; i++) {
for (int j = 1; j < this.m - 1; j++) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j - 1],
this.litSections[i - 1][j]
);
}
}
}

private void pourOffToSouthRight() {
for (int i = this.n - 2; i > 0; i--) {
for (int j = this.m - 2; j > 0; j--) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j + 1],
this.litSections[i + 1][j]
);
}
}
}

public int getTrappedWater() {
int sumWater = 0;
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
sumWater += this.litSections[i][j].getTrappedWater();
}
}
return sumWater;
}
}




Finally I made 3 classes with JUnit5 tests:



package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class LithosphereSectionTest {

static LithosphereSection testLitSection;

@BeforeAll
static void setUpBeforeClass() throws Exception {
testLitSection = new LithosphereSection(5);
}

@BeforeEach
void setUp() throws Exception {
testLitSection.setWaterHeight(10);
}

@Test
void test01() {
assertEquals(5, testLitSection.getTrappedWater());
}

@Test
void test02() {
LithosphereSection litSection2 = new LithosphereSection(7);
LithosphereSection litSection3 = new LithosphereSection(8);
LithosphereSection litSection4 = new LithosphereSection(6);
litSection4.setWaterHeight(7);

testLitSection.extraWaterPourOff(litSection2, litSection3, litSection4);
assertEquals(2, testLitSection.getTrappedWater());
}

@Test
void test03() {
testLitSection.extraWaterPourOff();
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test04() {
LithosphereSection sections = null;
testLitSection.extraWaterPourOff(sections);
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test05() {
LithosphereSection litSection2 = null;
testLitSection.extraWaterPourOff(litSection2);
assertEquals(0, testLitSection.getTrappedWater());
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class BeachTest {

static Beach beach;

@BeforeAll
static void setUpBeforeClass() throws Exception {
int groundScheme = new int { 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 };
beach = new Beach(groundScheme);
}

private int run(int waveHeight) {
beach.dry();
beach.takeWaveFromLeft(waveHeight);
beach.extraWaterPourOff();
return beach.getTrappedWater();
}

@Test
void test() {
assertEquals(0, run(1));
assertEquals(0, run(2));
assertEquals(0, run(3));
assertEquals(1, run(4));
assertEquals(1, run(5));
assertEquals(6, run(6));
assertEquals(6, run(7));
assertEquals(8, run(8));
assertEquals(8, run(9));
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class IslandTest {

private int run(int _groundScheme) {
Island island = new Island(_groundScheme);
island.overfillByWater();
island.extraWaterPourOff();
return island.getTrappedWater();
}

@Test
void test01() {
int groundScheme = new int {
{ 5, 3, 4, 5 },
{ 6, 2, 1, 4 },
{ 3, 1, 1, 4 },
{ 8, 5, 4, 3 }
};
assertEquals(7, run(groundScheme));
}

@Test
void test02() {
int groundScheme = new int {
{ 8, 6, 8, 8 },
{ 8, 2, 2, 4 },
{ 8, 2, 2, 8 },
{ 8, 8, 8, 8 }
};
assertEquals(8, run(groundScheme));
}
}









share|improve this question









New contributor




AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • Tests help reviewers tremendously when reviewing your code. If you have them you should definitely provide them.
    – bruglesco
    39 mins ago














0












0








0







There are some exercises about islands and water. I have seen ready solutions on Java, but they are developed in procedural style in one-two methods. I tried to develop an object oriented solutions with code reuse. It is posted on GitHub, but the rules of this portal ask me to post the code here. I have never get code reviews before, so I would happy to see any suggestions to improve my code. Also sorry for my bad English.





Exercise 1.




There is a beach with a ground configuration like 
[ 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 ].
A wave come from a sea to the left of the beach.
Its height is 5, for example.
Then the wave come back to the sea.
In the beach's hollows we find trapped water.
If the wave is higher than beach it covers the full beach
and goes away to both directions.
Task: write a program for counting all trapped water
on the whole beach.





Exercise 2.




There is an island with a ground configuration like
[
[ 5, 3, 4, 5 ],
[ 6, 2, 1, 4 ],
[ 3, 1, 1, 4 ],
[ 8, 5, 4, 3 ]
]
A rain was many days.
It filled by water every hollow in the island.
Water can go away only to 4 directions:
north, south, west, east.
Task: write a program for counting
all trapped water in whole island.
For example, the answer for a given configuration is 7.





At first, I developed the common class for a single column of land with water on it:



package trappedwater;

import java.util.Arrays;

public class LithosphereSection {

/* Height is above mean sea level in each case */
public final int groundHeight;
private int waterHeight;

public LithosphereSection(int _groundHeight) {
this.groundHeight = _groundHeight;
this.waterHeight = 0;
}

public void setWaterHeight(int _waterHeight) {
this.waterHeight = _waterHeight;
}

public void extraWaterPourOff(LithosphereSection... neighborSections) {
if (hasPrecipiceForWater(neighborSections)) {
this.waterHeight = 0;
} else {
for (LithosphereSection neighbor : neighborSections) {
int support = Integer.max(neighbor.waterHeight, neighbor.groundHeight);
this.waterHeight = Integer.min(this.waterHeight, support);
}
}
}

private boolean hasPrecipiceForWater(LithosphereSection... neighborSections) {
return neighborSections == null
|| neighborSections.length == 0
|| Arrays.asList(neighborSections).contains(null);
}

public int getTrappedWater() {
int trappedWater = this.waterHeight - this.groundHeight;
return (trappedWater > 0) ? trappedWater : 0;
}
}




Then I solved the first exercise.



package trappedwater;

public class Beach {

private final LithosphereSection litSections;
private final int m; // alias to litSections.length

public Beach(int _groundScheme) {
this.m = _groundScheme.length;
this.litSections = new LithosphereSection[this.m];
for (int i = 0; i < this.m; i++) {
this.litSections[i] = new LithosphereSection(_groundScheme[i]);
}
}

public void takeWaveFromLeft(int _waveHeight) {
boolean waveStillMoves = true;
for (int i = 0; i < this.m; i++) {
if (waveStillMoves) {
if (_waveHeight > this.litSections[i].groundHeight) {
this.litSections[i].setWaterHeight(_waveHeight);
} else {
waveStillMoves = false;
}
}
}
}

public void extraWaterPourOff() {
// Pour water on boarders
this.litSections[0].extraWaterPourOff();
this.litSections[this.m - 1].extraWaterPourOff();

// Pour water to the left
for (int i = 1; i < this.m - 1; i++) {
this.litSections[i].extraWaterPourOff(this.litSections[i - 1]);
}

// Pour water to the right
for (int i = this.m - 2; i > 0; i--) {
this.litSections[i].extraWaterPourOff(this.litSections[i + 1]);
}
}

public int getTrappedWater() {
int sumWater = 0;
for (LithosphereSection litSection : this.litSections) {
sumWater += litSection.getTrappedWater();
}
return sumWater;
}

public void dry() {
for (int i = 0; i < this.m; i++) {
this.litSections[i].setWaterHeight(0);
}
}
}




And the second one



package trappedwater;

public class Island {

private final LithosphereSection litSections;
private final int n; // rows
private final int m; // columns
private int highestGround;

public Island(int _groundScheme) {
this.n = _groundScheme.length;
this.m = _groundScheme[0].length;

this.litSections = new LithosphereSection[this.n][this.m];
this.highestGround = _groundScheme[0][0];
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j] = new LithosphereSection(_groundScheme[i][j]);
this.highestGround = Integer.max(this.highestGround, _groundScheme[i][j]);
}
}
}

public void overfillByWater() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j].setWaterHeight(this.highestGround);
}
}
}

public void extraWaterPourOff() {
pourOffBoarders();
boolean countOfPuddlesChanges = true;
while (countOfPuddlesChanges) {
int countOfPuddlesBefore = getTrappedWater();
pourOffToNorthLeft();
pourOffToSouthRight();
countOfPuddlesChanges = (getTrappedWater() != countOfPuddlesBefore);
}
}

private void pourOffBoarders() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
boolean isBorder = (i == 0) || (i == this.n - 1) || (j == 0) || (j == this.m - 1);
if (isBorder) {
this.litSections[i][j].extraWaterPourOff();
}
}
}
}

private void pourOffToNorthLeft() {
for (int i = 1; i < this.n - 1; i++) {
for (int j = 1; j < this.m - 1; j++) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j - 1],
this.litSections[i - 1][j]
);
}
}
}

private void pourOffToSouthRight() {
for (int i = this.n - 2; i > 0; i--) {
for (int j = this.m - 2; j > 0; j--) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j + 1],
this.litSections[i + 1][j]
);
}
}
}

public int getTrappedWater() {
int sumWater = 0;
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
sumWater += this.litSections[i][j].getTrappedWater();
}
}
return sumWater;
}
}




Finally I made 3 classes with JUnit5 tests:



package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class LithosphereSectionTest {

static LithosphereSection testLitSection;

@BeforeAll
static void setUpBeforeClass() throws Exception {
testLitSection = new LithosphereSection(5);
}

@BeforeEach
void setUp() throws Exception {
testLitSection.setWaterHeight(10);
}

@Test
void test01() {
assertEquals(5, testLitSection.getTrappedWater());
}

@Test
void test02() {
LithosphereSection litSection2 = new LithosphereSection(7);
LithosphereSection litSection3 = new LithosphereSection(8);
LithosphereSection litSection4 = new LithosphereSection(6);
litSection4.setWaterHeight(7);

testLitSection.extraWaterPourOff(litSection2, litSection3, litSection4);
assertEquals(2, testLitSection.getTrappedWater());
}

@Test
void test03() {
testLitSection.extraWaterPourOff();
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test04() {
LithosphereSection sections = null;
testLitSection.extraWaterPourOff(sections);
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test05() {
LithosphereSection litSection2 = null;
testLitSection.extraWaterPourOff(litSection2);
assertEquals(0, testLitSection.getTrappedWater());
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class BeachTest {

static Beach beach;

@BeforeAll
static void setUpBeforeClass() throws Exception {
int groundScheme = new int { 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 };
beach = new Beach(groundScheme);
}

private int run(int waveHeight) {
beach.dry();
beach.takeWaveFromLeft(waveHeight);
beach.extraWaterPourOff();
return beach.getTrappedWater();
}

@Test
void test() {
assertEquals(0, run(1));
assertEquals(0, run(2));
assertEquals(0, run(3));
assertEquals(1, run(4));
assertEquals(1, run(5));
assertEquals(6, run(6));
assertEquals(6, run(7));
assertEquals(8, run(8));
assertEquals(8, run(9));
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class IslandTest {

private int run(int _groundScheme) {
Island island = new Island(_groundScheme);
island.overfillByWater();
island.extraWaterPourOff();
return island.getTrappedWater();
}

@Test
void test01() {
int groundScheme = new int {
{ 5, 3, 4, 5 },
{ 6, 2, 1, 4 },
{ 3, 1, 1, 4 },
{ 8, 5, 4, 3 }
};
assertEquals(7, run(groundScheme));
}

@Test
void test02() {
int groundScheme = new int {
{ 8, 6, 8, 8 },
{ 8, 2, 2, 4 },
{ 8, 2, 2, 8 },
{ 8, 8, 8, 8 }
};
assertEquals(8, run(groundScheme));
}
}









share|improve this question









New contributor




AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











There are some exercises about islands and water. I have seen ready solutions on Java, but they are developed in procedural style in one-two methods. I tried to develop an object oriented solutions with code reuse. It is posted on GitHub, but the rules of this portal ask me to post the code here. I have never get code reviews before, so I would happy to see any suggestions to improve my code. Also sorry for my bad English.





Exercise 1.




There is a beach with a ground configuration like 
[ 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 ].
A wave come from a sea to the left of the beach.
Its height is 5, for example.
Then the wave come back to the sea.
In the beach's hollows we find trapped water.
If the wave is higher than beach it covers the full beach
and goes away to both directions.
Task: write a program for counting all trapped water
on the whole beach.





Exercise 2.




There is an island with a ground configuration like
[
[ 5, 3, 4, 5 ],
[ 6, 2, 1, 4 ],
[ 3, 1, 1, 4 ],
[ 8, 5, 4, 3 ]
]
A rain was many days.
It filled by water every hollow in the island.
Water can go away only to 4 directions:
north, south, west, east.
Task: write a program for counting
all trapped water in whole island.
For example, the answer for a given configuration is 7.





At first, I developed the common class for a single column of land with water on it:



package trappedwater;

import java.util.Arrays;

public class LithosphereSection {

/* Height is above mean sea level in each case */
public final int groundHeight;
private int waterHeight;

public LithosphereSection(int _groundHeight) {
this.groundHeight = _groundHeight;
this.waterHeight = 0;
}

public void setWaterHeight(int _waterHeight) {
this.waterHeight = _waterHeight;
}

public void extraWaterPourOff(LithosphereSection... neighborSections) {
if (hasPrecipiceForWater(neighborSections)) {
this.waterHeight = 0;
} else {
for (LithosphereSection neighbor : neighborSections) {
int support = Integer.max(neighbor.waterHeight, neighbor.groundHeight);
this.waterHeight = Integer.min(this.waterHeight, support);
}
}
}

private boolean hasPrecipiceForWater(LithosphereSection... neighborSections) {
return neighborSections == null
|| neighborSections.length == 0
|| Arrays.asList(neighborSections).contains(null);
}

public int getTrappedWater() {
int trappedWater = this.waterHeight - this.groundHeight;
return (trappedWater > 0) ? trappedWater : 0;
}
}




Then I solved the first exercise.



package trappedwater;

public class Beach {

private final LithosphereSection litSections;
private final int m; // alias to litSections.length

public Beach(int _groundScheme) {
this.m = _groundScheme.length;
this.litSections = new LithosphereSection[this.m];
for (int i = 0; i < this.m; i++) {
this.litSections[i] = new LithosphereSection(_groundScheme[i]);
}
}

public void takeWaveFromLeft(int _waveHeight) {
boolean waveStillMoves = true;
for (int i = 0; i < this.m; i++) {
if (waveStillMoves) {
if (_waveHeight > this.litSections[i].groundHeight) {
this.litSections[i].setWaterHeight(_waveHeight);
} else {
waveStillMoves = false;
}
}
}
}

public void extraWaterPourOff() {
// Pour water on boarders
this.litSections[0].extraWaterPourOff();
this.litSections[this.m - 1].extraWaterPourOff();

// Pour water to the left
for (int i = 1; i < this.m - 1; i++) {
this.litSections[i].extraWaterPourOff(this.litSections[i - 1]);
}

// Pour water to the right
for (int i = this.m - 2; i > 0; i--) {
this.litSections[i].extraWaterPourOff(this.litSections[i + 1]);
}
}

public int getTrappedWater() {
int sumWater = 0;
for (LithosphereSection litSection : this.litSections) {
sumWater += litSection.getTrappedWater();
}
return sumWater;
}

public void dry() {
for (int i = 0; i < this.m; i++) {
this.litSections[i].setWaterHeight(0);
}
}
}




And the second one



package trappedwater;

public class Island {

private final LithosphereSection litSections;
private final int n; // rows
private final int m; // columns
private int highestGround;

public Island(int _groundScheme) {
this.n = _groundScheme.length;
this.m = _groundScheme[0].length;

this.litSections = new LithosphereSection[this.n][this.m];
this.highestGround = _groundScheme[0][0];
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j] = new LithosphereSection(_groundScheme[i][j]);
this.highestGround = Integer.max(this.highestGround, _groundScheme[i][j]);
}
}
}

public void overfillByWater() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
this.litSections[i][j].setWaterHeight(this.highestGround);
}
}
}

public void extraWaterPourOff() {
pourOffBoarders();
boolean countOfPuddlesChanges = true;
while (countOfPuddlesChanges) {
int countOfPuddlesBefore = getTrappedWater();
pourOffToNorthLeft();
pourOffToSouthRight();
countOfPuddlesChanges = (getTrappedWater() != countOfPuddlesBefore);
}
}

private void pourOffBoarders() {
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
boolean isBorder = (i == 0) || (i == this.n - 1) || (j == 0) || (j == this.m - 1);
if (isBorder) {
this.litSections[i][j].extraWaterPourOff();
}
}
}
}

private void pourOffToNorthLeft() {
for (int i = 1; i < this.n - 1; i++) {
for (int j = 1; j < this.m - 1; j++) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j - 1],
this.litSections[i - 1][j]
);
}
}
}

private void pourOffToSouthRight() {
for (int i = this.n - 2; i > 0; i--) {
for (int j = this.m - 2; j > 0; j--) {
this.litSections[i][j].extraWaterPourOff(
this.litSections[i][j + 1],
this.litSections[i + 1][j]
);
}
}
}

public int getTrappedWater() {
int sumWater = 0;
for (int i = 0; i < this.n; i++) {
for (int j = 0; j < this.m; j++) {
sumWater += this.litSections[i][j].getTrappedWater();
}
}
return sumWater;
}
}




Finally I made 3 classes with JUnit5 tests:



package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class LithosphereSectionTest {

static LithosphereSection testLitSection;

@BeforeAll
static void setUpBeforeClass() throws Exception {
testLitSection = new LithosphereSection(5);
}

@BeforeEach
void setUp() throws Exception {
testLitSection.setWaterHeight(10);
}

@Test
void test01() {
assertEquals(5, testLitSection.getTrappedWater());
}

@Test
void test02() {
LithosphereSection litSection2 = new LithosphereSection(7);
LithosphereSection litSection3 = new LithosphereSection(8);
LithosphereSection litSection4 = new LithosphereSection(6);
litSection4.setWaterHeight(7);

testLitSection.extraWaterPourOff(litSection2, litSection3, litSection4);
assertEquals(2, testLitSection.getTrappedWater());
}

@Test
void test03() {
testLitSection.extraWaterPourOff();
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test04() {
LithosphereSection sections = null;
testLitSection.extraWaterPourOff(sections);
assertEquals(0, testLitSection.getTrappedWater());
}

@Test
void test05() {
LithosphereSection litSection2 = null;
testLitSection.extraWaterPourOff(litSection2);
assertEquals(0, testLitSection.getTrappedWater());
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

class BeachTest {

static Beach beach;

@BeforeAll
static void setUpBeforeClass() throws Exception {
int groundScheme = new int { 1, 2, 3, 2, 3, 4, 5, 1, 4, 6, 7, 6, 7, 2, 3, 1 };
beach = new Beach(groundScheme);
}

private int run(int waveHeight) {
beach.dry();
beach.takeWaveFromLeft(waveHeight);
beach.extraWaterPourOff();
return beach.getTrappedWater();
}

@Test
void test() {
assertEquals(0, run(1));
assertEquals(0, run(2));
assertEquals(0, run(3));
assertEquals(1, run(4));
assertEquals(1, run(5));
assertEquals(6, run(6));
assertEquals(6, run(7));
assertEquals(8, run(8));
assertEquals(8, run(9));
}
}




package trappedwater;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class IslandTest {

private int run(int _groundScheme) {
Island island = new Island(_groundScheme);
island.overfillByWater();
island.extraWaterPourOff();
return island.getTrappedWater();
}

@Test
void test01() {
int groundScheme = new int {
{ 5, 3, 4, 5 },
{ 6, 2, 1, 4 },
{ 3, 1, 1, 4 },
{ 8, 5, 4, 3 }
};
assertEquals(7, run(groundScheme));
}

@Test
void test02() {
int groundScheme = new int {
{ 8, 6, 8, 8 },
{ 8, 2, 2, 4 },
{ 8, 2, 2, 8 },
{ 8, 8, 8, 8 }
};
assertEquals(8, run(groundScheme));
}
}






java






share|improve this question









New contributor




AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 27 mins ago





















New contributor




AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 1 hour ago









AMURWOLF

12




12




New contributor




AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






AMURWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • Tests help reviewers tremendously when reviewing your code. If you have them you should definitely provide them.
    – bruglesco
    39 mins ago


















  • Tests help reviewers tremendously when reviewing your code. If you have them you should definitely provide them.
    – bruglesco
    39 mins ago
















Tests help reviewers tremendously when reviewing your code. If you have them you should definitely provide them.
– bruglesco
39 mins ago




Tests help reviewers tremendously when reviewing your code. If you have them you should definitely provide them.
– bruglesco
39 mins ago















active

oldest

votes











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






AMURWOLF is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210647%2fsolutions-for-exercices-about-counting-trapped-water-on-islands%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes








AMURWOLF is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















AMURWOLF is a new contributor. Be nice, and check out our Code of Conduct.













AMURWOLF is a new contributor. Be nice, and check out our Code of Conduct.












AMURWOLF is a new contributor. Be nice, and check out our Code of Conduct.
















Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210647%2fsolutions-for-exercices-about-counting-trapped-water-on-islands%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Morgemoulin

Scott Moir

Souastre