0

I am studying various solutions for Number of Groups (or "islands") of 1's in a Matrix, and while the following clear & concise Java solution looks in the right direction, it also looks incomplete to me:

/*
 * Given a matrix of 0's and 1's, 
 * find the number of groups of 1's in the matrix.
 * 
 * A group of 1's is defined as all ADJACENT 1's 
 * vertically or horizontally but not diagonally.
*/

public class Islands {

    /**
     * main entry point
     */
    public static void main(String[] args) {
        int[][] A = new int[4][4];

        int totalNumGroups = 0; 
        int curCnt = 0;

        /*
         * Initialize 2-dimensional array with 1's and 0's (randomly!)
         * For testing/verification purpose only 
         */
        for(int x=0; x<A.length; x++) {
            for(int y=0; y<A[x].length; y++) {
                A[x][y] = (int) Math.round(Math.random());
                System.out.print(A[x][y] + " ");
            }
            System.out.println(" ");
        }

        /*
         * The crux of the solution: iterate through all (x,y):
         * If encountered a 1, 
         *  reset current count and 
         *  increase total number of groups by what clean_block returns.
         */
        for(int x=0; x<A.length; x++) {
            for(int y=0; y<A[x].length; y++) {
                if (A[x][y] == 1) {
                    curCnt = 0;  
                    totalNumGroups = totalNumGroups + cleanBlock(A, x,y, curCnt);    
                }
                // else (0), keep curCnt and totalNumGroups as are.
            }
        }

        System.out.println("\nTotal # of groups: " + totalNumGroups);
    }

    /*
     * Recursively clean found 1 and its adjacent 1's.
     */
    public static int cleanBlock(int[][] A, int x, int y, int cnt) { 
        A[x][y] = 0;
        if (inMatrix(x-1,y  ,A.length,A[0].length) == 1 && A[x-1][y] == 1) {
            cleanBlock(A, x-1,y  ,cnt); 
            cnt = 1;
            }
        if (inMatrix(x+1,y  ,A.length,A[0].length) == 1 && A[x+1][y] == 1) {
            cleanBlock(A, x+1,y  ,cnt); 
            cnt = 1;
            }
        if (inMatrix(x,y-1 ,A.length,A[0].length) == 1 && A[x][y-1] == 1) {
            cleanBlock(A, x,y-1  ,cnt); 
            cnt = 1;
            }
        if (inMatrix(x,y+1 ,A.length,A[0].length) == 1 && A[x][y+1] == 1) {
            cleanBlock(A, x,y+1  ,cnt); 
            cnt = 1;
            }

        return cnt;
    }

    public static int inMatrix(int x, int y, int lenX, int lenY) {
        if ( (x >= 0 && x <= (lenX-1)) && (y >= 0 && y <= (lenY-1)) )
            return 1;
        else
            return 0;
    }    
}

That is because it does not count a single 1 (surrounded by 0's) as a group. e.g. the output for this 4x4 matrix yields a single group only:

1 1 0 1  
1 0 0 0  
1 1 0 1  
1 0 0 0  

Total # of groups: 1

So, my question is: Is a single 1 surrounded by 0's considered a group?

Jay Souper
  • 2,576
  • 2
  • 14
  • 17
  • 1
    Not answering your question, but your code would be simpler if `inMatrix` returned a boolean: `inMatrix` wouldn't need a conditional, and you wouldn't need `== 1` in the `inMatrix(...) == 1` in `cleanBlock`. – Andy Turner Nov 27 '15 at 12:20
  • @AndyTurner I totally agree with you. This code BTW is not mine, I only added comments. The original code is in the link I provided in my original posting. It actually has several answers there but this one was easiest to grasp. – Jay Souper Nov 27 '15 at 12:24
  • with the specification of your link, http://www.careercup.com/question?id=14948781, the response is YES. – guillaume girod-vitouchkina Nov 27 '15 at 12:27
  • 1
    @guillaumegirod-vitouchkina I disagree. The question states "A group of 1's can be formed if a 1 is present either vertically or horizontally to the adjacent 1". These isolated 1s don't have a 1 present vertically or horizontally, so they "can't" form a group. I can't help but feel that it's just a poorly-worded question, though: faced with this type of question, I would consider them groups. – Andy Turner Nov 27 '15 at 12:28
  • 1
    you are right. it's ambiguious. you can decide to count (or not). It doesnt change really the goal (count connected sets of 1). Of course it changes a little the algorithm – guillaume girod-vitouchkina Nov 27 '15 at 12:34
  • 1
    @JaySouper FWIW, I think that Looper's answer is better and clearer. – Andy Turner Nov 27 '15 at 12:36
  • I just found [this additional reference](http://codercareer.blogspot.co.il/2013/02/no-41-group-of-1s-in-matrix.html) to the same problem. According to it, a single 1 surrounded by 0's **is** considered a group. Therefore, the output for the 4x4 matrix presented in my OP should have been 3 and the solution code I posted above is indeed incomplete. – Jay Souper Nov 27 '15 at 12:36
  • @AndyTurner I agree, Looper's answer is indeed better and clearer. It also answers the classic definition of the problem more correctly (i.e. counts single 1's as groups/islands). – Jay Souper Nov 27 '15 at 12:51

2 Answers2

1

It's correct because according to the problem:

A group of 1's can be formed if a 1 is present either vertically or horizontally to the adjacent 1

So in your case, a lonely 1 can't be counted as a group because there's no other 1 adjacent horizontally or vertically.

Sorin
  • 11,863
  • 22
  • 26
  • Thanks. Well, according to Looper's very elegant solution (same page in the original link) this isn't the case. Also according to this Code Career's [No. 41 - Group of 1s in a Matrix](http://codercareer.blogspot.co.il/2013/02/no-41-group-of-1s-in-matrix.html) single 1's count as groups/islands. – Jay Souper Nov 27 '15 at 13:36
  • 1
    That's a slightly different statement for a very similar problem. There's no rock-solid claim that it should be one or the other. It's more of how you read the statement. Your second link gives a clear example that you want to count single 1's, the first one (in the question) doesn't. You should always clarify things like this if you see them in an exam or interview. – Sorin Nov 27 '15 at 13:44
0
countgroup=1
countgroup_of_one_array=[]
def check_to_search(p_i,p_j,matrix):
    allow=True
    if p_j <0:
        allow=False
    if p_j >len(matrix[0])-1:
        allow=False
    if p_i<0:
        allow=False
    if p_i>len(matrix)-1:
        allow=False
    return allow



def looking_for1(p_i,p_j,matrix,countgroup):
    # global countgroup
    if matrix[p_i][p_j]==1:
        matrix[p_i][p_j]=0
        if check_to_search(p_i,p_j+1,matrix):
            if matrix[p_i][p_j+1] == 1:
                countgroup =countgroup+1
                countgroup = looking_for1(p_i,p_j+1,matrix,countgroup)
        if check_to_search(p_i,p_j-1,matrix):
            if matrix[p_i][p_j-1] == 1:
                countgroup =countgroup+1
                countgroup = looking_for1(p_i,p_j-1,matrix,countgroup)
        if check_to_search(p_i+1,p_j,matrix):
            if matrix[p_i+1][p_j] == 1:
                countgroup =countgroup+1
                countgroup = looking_for1(p_i+1,p_j,matrix,countgroup)
        if check_to_search(p_i-1,p_j,matrix):
            if matrix[p_i-1][p_j] == 1:
                countgroup =countgroup+1
                countgroup = looking_for1(p_i-1,p_j,matrix,countgroup)

    return countgroup


myarray=[[0,0,1,0,1],
         [1,1,0,1,0],
         [1,1,0,1,0],
         [0,0,0,0,0],
         [1,1,0,1,0]]

for i in range (0, len(myarray)):
    for j in range (0, len(myarray[i])):
        a= looking_for1(i,j,myarray,countgroup)
        if a >=2 :

            countgroup_of_one_array.append(a)

print("number of group of 1 is  : "+format(len(countgroup_of_one_array)) )
print((countgroup_of_one_array))

the answer : 3 [4,2,2]

parsa
  • 1