Skip to content
81 changes: 77 additions & 4 deletions src/Fire.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Fire {
/**
* Returns how long it takes for all vulnerable trees to be set on fire if a
Expand Down Expand Up @@ -35,9 +40,77 @@ public class Fire {
* @param matchC The column the match is lit at
* @return the time at which the final tree to be incinerated starts burning
*/
public static int timeToBurn(char[][] forest, int matchR, int matchC) {
// HINT: when adding to your BFS queue, you can include more information than
// just a location. What other information might be useful?
return -1;
public static int timeToBurn(char[][] forest, int matchR, int matchC)
{
if (forest[matchR][matchC] == '.') throw new IllegalArgumentException("The match isn't lit at a tree.");

boolean[][] visited = new boolean[forest.length][forest[0].length];
Queue<int[]> queue = new LinkedList<>();
queue.add(new int[]{matchR, matchC});
int count = -1;

while (!queue.isEmpty())
{
int[] current = queue.poll();
int curR = current[0];
int curC = current[1];

if (curR == -1)
{
count++;
continue;
}

if (visited[curR][curC]) continue;

visited[curR][curC] = true;

queue.addAll(neighborTrees(forest, curR, curC, queue));

}

return count;
}

public static List<int[]> neighborTrees(char[][] forest, int spreadR, int spreadC, Queue<int[]> queue)
{
int[][] directions = {
{-1, 0}, // North
{1, 0}, // South
{0, 1}, // East
{0, -1} // West
};

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

int check = 0;
for (int[] findBurnTurn : queue)
{
if (findBurnTurn[0] == -1) check++;
}

if (check == 0) possibleMoves.add(new int[]{-1, 0});
else check = 0;

for (int[] direction : directions)
{
int changeR = direction[0];
int changeC = direction[1];

int newR = spreadR + changeR;
int newC = spreadC + changeC;

if (newR >= 0 &&
newR < forest.length &&
newC >= 0 &&
newC < forest[newR].length &&
forest[newR][newC] != '.')
{
possibleMoves.add(new int[]{newR, newC});
}
}

return possibleMoves;
}

}
140 changes: 140 additions & 0 deletions src/FireTest.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

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

import org.junit.jupiter.api.Test;

Expand All @@ -20,4 +29,135 @@ public void testTimeToBurnExample() {

assertEquals(expected, actual);
}

// Match set not on a tree
@Test
public void testTimeToBurn_BadArgument()
{
char[][] forest = {
{'.', '.', '.'},
{'.', '.', '.'},
{'.', '.', '.'}
};

int spreadR = 1;
int spreadC = 1;

Exception exception = assertThrows(IllegalArgumentException.class, () -> {
Fire.timeToBurn(forest, spreadR, spreadC);
});

assertEquals("The match isn't lit at a tree.", exception.getMessage());

}

// Whole forest burns down
@Test
public void testTimeToBurn_EverythingGoes()
{
char[][] forest = {
{'t', 't', 't'},
{'t', 't', 't'},
{'t', 't', 't'}
};

int spreadR = 1;
int spreadC = 1;

int expected = 2;
int actual = Fire.timeToBurn(forest, spreadR, spreadC);

assertEquals(expected, actual);

}

// Neighbors on All Sides
@Test
public void testNeighborTrees_AllSides()
{
char[][] forest = {
{'t', 't', 't'},
{'t', 't', 't'},
{'t', 't', 't'}
};

int spreadR = 1;
int spreadC = 1;

int[] startingLocation = {spreadR, spreadC};
Queue<int[]> queue = new LinkedList<>();
queue.add(startingLocation);

List<int[]> neighbors = Fire.neighborTrees(forest, spreadR, spreadC, queue);
Set<String> neighborsSet = toSet(neighbors);

assertTrue(neighborsSet.contains("0,1"));
assertTrue(neighborsSet.contains("1,0"));
assertTrue(neighborsSet.contains("1,2"));
assertTrue(neighborsSet.contains("2,1"));

}

// No Neighbors
@Test
public void testNeighborTrees_NoSides()
{
char[][] forest = {
{'.', '.', '.'},
{'.', 't', '.'},
{'.', '.', '.'}
};

int spreadR = 1;
int spreadC = 1;

int[] startingLocation = {spreadR, spreadC};
Queue<int[]> queue = new LinkedList<>();
queue.add(startingLocation);

List<int[]> neighbors = Fire.neighborTrees(forest, spreadR, spreadC, queue);
Set<String> neighborsSet = toSet(neighbors);

assertTrue(neighborsSet.contains("-1,0"));
assertFalse(neighborsSet.contains("0,1"));
assertFalse(neighborsSet.contains("1,0"));
assertFalse(neighborsSet.contains("1,2"));
assertFalse(neighborsSet.contains("2,1"));

}

// Corner Neighbors
@Test
public void testNeighborTrees_CornerTrees()
{
char[][] forest = {
{'t', 't', '.'},
{'t', '.', '.'},
{'.', '.', '.'}
};

int spreadR = 0;
int spreadC = 0;

int[] startingLocation = {spreadR, spreadC};
Queue<int[]> queue = new LinkedList<>();
queue.add(startingLocation);

List<int[]> neighbors = Fire.neighborTrees(forest, spreadR, spreadC, queue);
Set<String> neighborSet = toSet(neighbors);

assertTrue(neighborSet.contains("0,1"));
assertTrue(neighborSet.contains("1,0"));

}



private Set<String> toSet(List<int[]> list)
{
Set<String> set = new HashSet<>();
for (int[] arr : list) set.add(arr[0] + "," + arr[1]);
return set;
}

}