views:

178

answers:

1

I have an 2 dimensional array that is full of 1s and 0s such as

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

You can see there is a square in th array. I am trying to make a function that will make a rectangle or list of rectangles based on the square. So the example would return a rectangle like

rect.x = 2
rect.y = 1
rect.width = 7
rect.height = 5

This is the code i have now but it just doe not return anything

Dim rects As New List(Of Rectangle)
    For imgWidth As Integer = 0 To bow.GetUpperBound(0)
        For imgHeight As Integer = 0 To bow.GetUpperBound(1)
            If bow(imgWidth, imgHeight) = 1 Then

                If bow(imgWidth + 1, imgHeight) = 1 And 
                   bow(imgWidth + 2, imgHeight) = 1 And 
                   bow(imgWidth, imgHeight + 1) = 1 And 
                   bow(imgWidth, imgHeight + 2) = 1 Then

                    Dim r As New Rectangle

                    With r
                        .X = imgWidth
                        .Y = imgHeight
                    End With

                    For rectWidth As Integer = imgWidth To bow.GetUpperBound(0)
                        If bow(rectWidth, imgHeight) = 0 Then
                            r.Width = bow(rectWidth - 1, imgHeight)
                        End If
                    Next

                    For rectHeight As Integer = imgHeight To bow.GetUpperBound(1)
                        If bow(imgWidth, rectHeight) = 0 Then
                            r.Height = bow(rectHeight - 1, imgHeight)
                        End If
                    Next

                    rects.Add(r)
                End If
            End If
        Next
    Next

Also the array must be able to have more than one square.

+3  A: 

This is how I would do it:

def rectangles(grid):
  rows = len(grid)
  cols = len(grid[0])

  hor_ones = [[0]] * rows
  for r in range(rows):
    for c in range(cols):
      hor_ones[r].append(hor_ones[r][c] + grid[r][c])

  ver_ones = [[0]] * cols
  for c in range(cols):
    for r in range(rows):
      ver_ones[c].append(ver_ones[c][r] + grid[r][c])

  ret = []
  for r1 in range(rows):
    for c1 in range(cols):
      for r2 in range(r1+1, rows):
        for c2 in range(c1+1, cols):
          if all_ones(hor_ones[r1], c1, c2) and all_ones(hor_ones[r2], c1, c2) and all_ones(ver_ones[c1], r1, r2) and all_ones(ver_ones[c2], r1, r2):
            ret.append((r1, c2, r2, c2))
  return ret

def all_ones(ones, x, y):
  return ones[y+1] - ones[x] == y - x + 1

Note that:

  • hor_ones[r][c] is the number of ones in row r in the first c columns.
  • ver_ones[c][r] is the number of ones in column c in the first r rows.

Therefore, the number of ones in row r and between columns c1 and c2 (inclusive) is:

hor_ones[r][c2+1] - hor_ones[r][c1]

EDIT

Here's my solution in Java, maybe it is easier for you to understand and implement in VB.NET:

public static List<Rectangle> findRectangles(int[][] grid) {
    int rows = grid.length;
    int cols = grid[0].length;

    int[][] horOnes = new int[rows][cols+1];
    for (int r = 0; r < rows; r++)
        for (int c = 0; c < cols; c++)
            horOnes[r][c+1] = horOnes[r][c] + grid[r][c];

    int[][] verOnes = new int[cols][rows+1];
    for (int c = 0; c < cols; c++)
        for (int r = 0; r < rows; r++)
            verOnes[c][r+1] = verOnes[c][r] + grid[r][c];

    List<Rectangle> ret = new ArrayList<Rectangle>();
    for (int r1 = 0; r1 < rows; r1++)
        for (int c1 = 0; c1 < cols; c1++)
            for (int r2 = r1+1; r2 < rows; r2++)
                for (int c2 = c1+1; c2 < cols; c2++)
                    if (allOnes(horOnes[r1], c1, c2) && allOnes(horOnes[r2], c1, c2) && allOnes(verOnes[c1], r1, r2) && allOnes(verOnes[c2], r1, r2))
                        ret.add(new Rectangle(r1, c1, r2, c2));
    return ret;
}

private static boolean allOnes(int[] ones, int x, int y) {
    return ones[y+1] - ones[x] == y - x + 1;
}
Sheldon L. Cooper
Is that VB.NET 2018?
GSerg
Thanks so much but can anyone translate that to vb.net.
giodamelio
I really have no clue what to do with it.
giodamelio
What language is that?
giodamelio
@giodamelio: it's Python.
Sheldon L. Cooper
@Sheldon L. Cooper - Great work! Unfortunately, the constructor for a Rectangle takes width and height - not right and bottom, so you need to fix your instantiation. Additionally, your horOnes and verOnes do not reset to zero - see my answer for the fix.
Nescio
@Nescio: "Rectangle" is a class I defined but omitted in my response for brevity. In Java the arrays of `int` get initialized with zeroes. I tested my code with a couple of cases and it worked.
Sheldon L. Cooper
@Sheldon L. Cooper - Ok, I assumed you were using the standard Java Rectangle. Regardless, I believe if you print out the results of your verOnes, or horOnes, you'll see that it extends incorrectly to the right and bottom, thereby creating additional rectangles.
Nescio
@giodmaelio It's python which is a much better language to learn with than VB. to quote [Dijkstra](http://en.wikipedia.org/wiki/Edsger_Wybe_Dijkstra), "...the teaching of BASIC should be rated as a criminal offence: it mutilates the mind beyond recovery." You'll note that the person that solved your problem is not a VB programmer.
aaronasterling
@Nescio: Could you provide an small input grid that will make my code fail?
Sheldon L. Cooper
@Sheldon L. Cooper Sure - see my answer
Nescio
@Sheldon L. Cooper Basically, you only want to add one, if the grid contains 1, otherwise the count should reset to zero.
Nescio
@Nescio: My program works with your case. It outputs: [(0,0,8,9), (2,2,6,7)].
Sheldon L. Cooper
@Nescio: You seem to be confusing the definition of `hor_ones` and `ver_ones`. You don't have to reset the count to zero. Please re-read my definition.
Sheldon L. Cooper
@Sheldon L. Cooper - You are correct, sorry for my confusion.
Nescio
I am having trouble translating the Java to vb.net. In the last round of loops where the if statement is you use horOnes as a 1d array when it is really a 2d array.
giodamelio
@giodamelio: You can change it to: `if (allOnes(horOnes, r1, c1, c2) }`
Sheldon L. Cooper
thank you all it worked!!!
giodamelio
@AaronMcSmooth If you think Basic is so bad, what language do you suggest i learn?
giodamelio
@giodamelio. I would recommend [Python](http://www.python.org) to start with.
aaronasterling
thanks for the advice
giodamelio