3

My professor gave us an assignment where I need to search around a given point in a grid for all other spots that makes up a group (in this example I need to find the number of spots that in a "L" shape within the problem).

So the grid is 10x10, and my professor has given us a spot to start with. My professor gave us an idea which is to check the neighboring spots, and add it to a set, if the spot is newly found (which will be in the set) then recursively call that method.

private Spot findSpots(Set<Spot> spots, Set<Spot> activeSpots, Spot initial) {
    Spot newSpot = null;


    Set<Spot> activeSet = new HashSet<Spot>();
    checkAround(activeSet, new Spot(initial.i - 1, initial.j));
    checkAround(activeSet, new Spot(initial.i + 1, initial.j));
    checkAround(activeSet, new Spot(initial.i, initial.j - 1));
    checkAround(activeSet, new Spot(initial.i, initial.j + 1));


    for (Spot spot : activeSet) {
        newSpot = findSpots(spots, activeSpots, spot);
        if (grid[newSpot.i][newSpot.j] == true)
            spots.add(newSpot);
    }

    return newSpot;
 }
 private boolean checkAround(Set<Spot> spots, Spot spot) {
    if (!spots.contains(spot)) {
        spots.add(spot);
        return true;
    }
    return false;
 }

I know I need a boundary condition (or else I will get stackoverflow exceptions), but I need help in the logic.

Kendrick Lamar
  • 781
  • 2
  • 8
  • 18
  • 1
    Putting more thought into your variable names might make the code a bit easier to read and modify, even something like "initialSpots" would make it a lot less confusing when you're trying to reason over all these various spots structures – dahui Nov 05 '16 at 22:58
  • 1
    I renamed some of the variables to make it easy for others to read. – Kendrick Lamar Nov 05 '16 at 23:01
  • 1
    Maybe add a boolean member variable or function to your Spot class, "searched" or "hasBeenSearched", set it to true when you've already called the function on this spot, and then you can prevent the function from being called on a Spot if Spot.hasBeenSearched – dahui Nov 05 '16 at 23:07

2 Answers2

3

I know I need a boundary condition [...]

You said it yourself. One key word is boundary. You need to check if a spot is legal in the grid, and stop exploring if not.

Another stop condition is if the spot is already visited.

If you implement these two stop conditions, and if you perform these checks before making further recursive calls, you will find a solution without overflowing the stack.

Something like this:

private int countSpots(Set<Spot> visited, Spot spot) {
    if (!isValid(spot) || visited.contains(spot)) {
        return 0;
    }

    visited.add(spot);

    int count = 1;
    count += countSpots(visited, new Spot(spot.x - 1, spot.y));
    count += countSpots(visited, new Spot(spot.x + 1, spot.y));
    count += countSpots(visited, new Spot(spot.x, spot.y + 1));
    count += countSpots(visited, new Spot(spot.x, spot.y - 1));
    return count;
}

Btw the algorithm you're using is a variant of flood fill, see more info and tips and hints in the wikipedia page.

janos
  • 120,954
  • 29
  • 226
  • 236
  • You sir have helped me out, because of the fact that you told me what type of algo it was, I managed to change the code and finish it. – Kendrick Lamar Nov 05 '16 at 23:41
1

The way I did it was:

  • I added the boundary conditions for the grid
  • I had two sets which one contains all the spots I visited, the other contains the spots I need
  • return if the spot is already in both of those
  • add the spots to the proper set
  • recursively call all around the spot
Kendrick Lamar
  • 781
  • 2
  • 8
  • 18