Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 114 additions & 4 deletions src/ExplorerSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,119 @@ public class ExplorerSearch {
* @return the number of spaces the explorer can reach
*/
public static int reachableArea(int[][] island) {
// Implement your method here!
// Please also make more test cases
// I STRONGLY RECOMMEND testing some helpers you might make too
return -1;
// Implement your method here!\


if (island == null || island.length == 0 || island[0].length == 0) {
return 0;
}


int[] startPos = locateExplorer(island);
if (startPos == null) {
return 0;
}


boolean[][] explored = new boolean[island.length][island[0].length];

return exploreIsland(island, startPos, explored);
}

/**
* Recursively explores the island and counts reachable spaces.
* @param island the 2D array of the island
* @param pos current position [row, col]
* @param explored tracks visited cells
* @return number of reachable spaces from this position
*/
public static int exploreIsland(int[][] island, int[] pos, boolean[][] explored) {
int row = pos[0];
int col = pos[1];


if (explored[row][col]) {

return 0;
}


explored[row][col] = true;


int reachable = 1;


List<int[]> nextMoves = getValidMoves(island, pos, explored);


for (int[] next : nextMoves) {

reachable += exploreIsland(island, next, explored);
}

return reachable;
}

/**
* Finds the explorer's starting position (marked '0').
* @param island the 2D array of the island
* @return array [row, col] of the start, or null if not found
*/
public static int[] locateExplorer(int[][] island) {

for (int row = 0; row < island.length; row++) {
for (int col = 0; col < island[row].length; col++) {
if (island[row][col] == 0) {
return new int[] {row, col};
}
}
}
return null;
}

/**
* Determines all valid moves from the current position.
* @param island the 2D array of the island
* @param pos current position [row, col]
* @param explored tracks visited cells
* @return list of valid neighboring positions
*/
static List<int[]> getValidMoves(int[][] island, int[] pos, boolean[][] explored) {

List<int[]> validMoves = new ArrayList<>();

int row = pos[0];
int col = pos[1];


int[][] directions = {
{-1, 0},
{1, 0},
{0, -1},
{0, 1}
};


for (int[] dir : directions) {

int nextRow = row + dir[0];
int nextCol = col + dir[1];


if (nextRow >= 0 && nextRow < island.length &&

nextCol >= 0 && nextCol < island[0].length &&

(island[nextRow][nextCol] == 0 || island[nextRow][nextCol] == 1) &&
!explored[nextRow][nextCol]) {

validMoves.add(new int[] {nextRow, nextCol});
}
}

return validMoves;
}
}


164 changes: 164 additions & 0 deletions src/ExplorerSearchTest.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import static org.junit.Assert.*;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.Test;

public class ExplorerSearchTest {
Expand All @@ -17,4 +22,163 @@ public void testReachableArea_someUnreachable() {

// Add more tests here!
// Come up with varied cases

@Test
public void testReachableArea_allReachable() {
int[][] island = {
{1,1,1},
{1,0,1},
{1,1,1}
};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(9, actual);
}


@Test
public void testReachableArea_blockedStart() {
int[][] island = {
{2,2,2},
{2,0,2},
{2,2,2}
};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(1, actual); // Only start is reachable
}


@Test
public void testReachableArea_singleCell() {
int[][] island = {{0}};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(1, actual);
}


@Test
public void testReachableArea_nullIsland() {
int[][] island = null;
int actual = ExplorerSearch.reachableArea(island);
assertEquals(0, actual);
}


@Test
public void testReachableArea_emptyIsland() {
int[][] island = {};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(0, actual);
}

@Test
public void testReachableArea_noExplorer() {
int[][] island = {
{1,1,1},
{1,1,1},
{1,1,1}
};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(0, actual);
}

@Test
public void testReachableArea_topLeftStart() {
int[][] island = {
{0,1,1,3},
{1,2,1,3},
{3,1,1,2}
};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(7, actual);
}


@Test
public void testReachableArea_narrowStrip() {
int[][] island = {
{2, 3, 0, 1, 1, 2, 3}
};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(3, actual); // Narrow 1x7 strip, 3 cells reachable
}

@Test
public void testReachableArea_disconnectedRegions() {
int[][] island = {
{0,1,1,2,1,1},
{1,1,2,3,1,1},
{2,3,3,1,1,1},
{1,1,1,2,1,1}
};
int actual = ExplorerSearch.reachableArea(island);
assertEquals(5, actual); // Only top-left region reachable, 6 cells
}

@Test
public void testLocateExplorer_topLeft() {
int[][] island = {
{0,1,1,3},
{1,2,1,3},
{3,1,1,2}
};
int[] expected = {0, 0};
assertArrayEquals(expected, ExplorerSearch.locateExplorer(island));
}

@Test
public void testLocateExplorer_middle() {
int[][] island = {
{1,1,1,3},
{1,2,0,3},
{3,1,1,2}
};
int[] expected = {1, 2};
assertArrayEquals(expected, ExplorerSearch.locateExplorer(island));
}

@Test
public void testLocateExplorer_noExplorer() {
int[][] island = {
{1,1,1,3},
{1,2,1,3},
{3,1,1,2}
};
assertArrayEquals(null, ExplorerSearch.locateExplorer(island));
}

@Test
public void testGetValidMoves_allDirections() {
int[][] island = {
{1,1,1},
{1,0,1},
{1,1,1}
};
int[] pos = {1, 1};
boolean[][] explored = new boolean[3][3];
List<int[]> moves = ExplorerSearch.getValidMoves(island, pos, explored);
Set<String> movesStrings = toSet(moves);
assertEquals(4, movesStrings.size());
assertTrue(movesStrings.contains("0,1"));
assertTrue(movesStrings.contains("2,1"));
assertTrue(movesStrings.contains("1,0"));
assertTrue(movesStrings.contains("1,2"));
}

// Helper to convert move list to string set
private Set<String> toSet(List<int[]> moves) {

Set<String> set = new HashSet<>();

for (int[] move : moves) {
set.add(move[0] + "," + move[1]);
}
return set;
}







}