How to recognize a square in a bitmap? - algorithm

I came across this interview question:
In a N x N bi-dimensional array of boolean elements, how do you determine if the values form a square?
For example:
true true true true
true false false true
true false false true
true true true true
form a square.
I figured that I have to start by checking if there is a square in the middle (if N is odd that is always true) and then recursively checking the values at the perimeter.
Is this the best way to do it or is there a better, faster, way to find out?

A squre could be determined by two points. Let's say the left-top point (x1,y1) and the right-bottom point (x2,y2). And, let's use 1 as true, and 0 as false.
Consider an array:
array = [None] * 5
array[0] = [1, 1, 1, 1, 0]
array[1] = [1, 0, 0, 1, 0]
array[2] = [1, 0, 0, 1, 0]
array[3] = [1, 1, 1, 1, 0]
array[4] = [1, 0, 0, 1, 0]
It's obviously that (0,0)(3,3) forms a square in this case. And we could find a property that:
A square is formed if and only if:
By adding the two row borders together, you will get a sequence of 2;
The length of the sequence is equal to the distance between to two row borders.
By adding the two column borders together, you will get a sequence of 2;
The length of the sequence is equal to the distance between to two column borders.
Exploiting the property above, you would get an algorithm:
row_segment = []
col_segment = []
for v1 in range(len(array)):
for v2 in range(v1+1, len(array)):
add_row = [array[v1][col]+array[v2][col] for col in range(len(array))]
add_col = [array[row][v1]+array[row][v2] for row in range(len(array))]
row_distance = v2-v1
row_sum = sum(add_row[:row_distance+1])
col_sum = sum(add_col[:row_distance+1])
for i in range(len(array)-row_distance):
j = i+row_distance
if row_sum == 2*(row_distance+1):
row_segment.append([v1, i, v2, j])
if col_sum == 2*(row_distance+1):
col_segment.append([i, v1, j, v2])
row_sum = row_sum - add_row[i] + add_row[j+1] if j+1 < len(array) else None
col_sum = col_sum - add_col[i] + add_col[j+1] if j+1 < len(array) else None
for i in row_segment:
if i in col_segment:
print "Square ({x1}, {y1}) ({x2}, {y2})".format(x1=i[0], y1=i[1], x2=i[2], y2=i[3])
Let's run some tests:
Test 1:
0 0 0 0 0
0 0 1 1 1
0 0 1 0 1
0 0 1 1 1
0 0 0 0 0
Square (1, 2) (3, 4)
Test 2:
0 0 0 0 0
1 1 1 1 1
1 0 1 0 1
1 1 1 0 1
0 0 1 1 1
Square (1, 0) (3, 2)
Test 3:
0 0 0 0 0
1 1 1 1 1
1 0 1 0 1
1 1 1 1 1
0 0 0 0 0
Square (1, 0) (3, 2)
Square (1, 2) (3, 4)
Test 4:
1 1 1 1 1
1 0 1 0 1
1 1 0 0 1
1 0 0 1 0
1 1 1 1 1
No squares found

Related

Algorithm to minimize vertical sum of binned rows

I have a problem that I am trying to find an algorithm for. I'd appreciate any suggestions.
I have n rows of length m. The rows have binary (0,1) values that have some expected sum. The 1's can be placed anywhere in its row as long as the sum is as expected. The goal is to minimize the vertical sum for each column in length m.
For example, if we have a 4 rows and 10 columns, where the expected sums are:
Row 1: 6
Row 2: 7
Row 3: 4
Row 4: 5
A potential solution could be:
1 1 1 1 1 1 0 0 0 0
1 1 1 0 0 0 1 1 1 1
1 0 0 1 1 1 0 0 0 0
0 1 0 0 0 0 1 1 1 1
Getting vertical sums of:
3 3 2 2 2 2 2 2 2 2
Opposed to the larger sums if we would just place all the ones in the beginning:
1 1 1 1 1 1 0 0 0 0
1 1 1 1 1 1 1 0 0 0
1 1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
With sums of:
4 4 4 4 3 2 1 0 0 0
So, I'm trying to spread out the load. My number of rows will get into the millions/billions, so I'm hoping for a linear algebra approach rather than iterative. Thanks!
def create_min_vert_matrix(num_r, num_c, arr_sum_rows):
res = []
curr = 0
for r in range(num_r):
row = [0]*num_c
while arr_sum_rows[r] > 0:
arr_sum_rows[r] -= 1
row[curr] = 1
curr = (curr+1)%num_c
res.append(row)
return res
A quick test:
create_min_vert_matrix(4, 10, [6,7,4,5])
[[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 0, 1, 1, 1, 1],
[0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 1, 1, 1]]
The function takes number of rows, num_r, number of columns, num_c, and an array that tells what the sum of the ones in each row has to be (arr_sum_rows).
The idea is if we distribute the one column-wise as evenly as possible, we are able to minimize the column sums. To make this happen, we keep track of the last column where we inserted a one, curr, and for each inserted one increment it. If it grows larger than the number of columns we set it to zero: curr = (curr+1)%num_c.
The algorithm runs in O(n*m) where n and m are the number of rows and columns of the matrix and O(1) extra space if we don't count the auxiliary space needed for the result (otherwise also O(n*m) extra space of course).

Find area of largest island (area not being returned correctly)

I am working on this GeeksForGeeks problem that is looking for the area of the largest connected "island" of 1's in a 2D grid (details in question). I have a solution that works in some, but not all cases. My general idea is this:
Iterate through, row by row, until you find a 1. Upon finding a 1, use the helper method to find the size of the island containing the 1. Return the biggest island found in steps 1 and 2.
To calculate the size of an island, I recursively search each connected element (there are 8 of them), and flip each 1 to 0 when it has been searched.
I know the following are true:
The islands are found in the right order
Each island is summed only once (as it should be)
Each 1 within an island is visited exactly once (again, as expected)
But for whatever reason, despite visiting all the 1's within an island, the sum of these islands are not properly returned. I'm looking for help to figure out why. I have tried examining each step of the process using print statements etc., But still cannot find out what's wrong.As an example, on this grid
0 0 1 0 1 0
0 0 0 0 0 1
0 0 0 0 1 1
0 1 0 0 0 0
0 0 0 0 0 0
0 1 1 0 0 0
0 1 0 0 0 1
1 1 1 0 0 0
1 0 1 0 0 0
my code returns 3, but it should return 8. Can anyone see my mistake? My code is attached below.
class Solution:
#Function to find unit area of the largest region of 1s.
def findMaxArea(self, grid):
curr_max = 0
for i in range(0, len(grid)):
for j in range(0, len(grid[i])):
if grid[i][j] == 0:
continue
else:
curr_island_size = self.helper(i, j, grid)
if curr_island_size > curr_max:
curr_max = curr_island_size
return curr_max
def helper(self, row, column, grid):
if row == -1 or column == -1:
return 0 # outside of grid
elif column >= len(grid[0]) or row >= len(grid):
return 0 # outside of grid
elif grid[row][column] == 0:
return 0
else:
grid[row][column] = 0
up_left = self.helper(row - 1, column - 1, grid)
mid_left = self.helper(row, column - 1, grid)
down_left = self.helper(row + 1, column - 1, grid)
up = self.helper(row - 1, column, grid)
down = self.helper(row + 1, column, grid)
up_right = self.helper(row - 1, column + 1, grid)
mid_right = self.helper(row, column + 1, grid)
down_right = self.helper(row + 1, column + 1, grid)
return 1 + sum([up_left, mid_left, up, down, up_right, mid_right, down_right])

Find maximum covered elements without block by obstacles in path

Given MXN matrix where matrix elements are either "." or "*". Where . is representing road and * is representing block or wall. Person can move adjacent forward, down and diagonally, we need to find maximum "." covered by person without blocked by wall. Example(in image)
Can you please suggest me efficient algorithm to approach this problem?
You have to do this: https://en.wikipedia.org/wiki/Flood_fill
Take the biggest flood you can do.
You go through your matrix and find a '.'
Do a flood from that point. The amount of elements you flood the area you always compare it with the maximum you already found. To make this easy you can flood with a letter or a number or whatever you want but not with '.'. What you add instead of '.' consider it as a wall or a '*' so you don't try to flood that area again and again.
Continue to go through the matrix and try to find the next '.'. All the previous '.' where flooded so you won't consider the same area twice.
Redo 2 until you can't find any more '.'. The maximum will contain your answer.
When you have the answer you can go back in the Matrix and you already know the letter or number you flooded the area with the maximum result so you can print the biggest area.
Are you looking for the exact path or only the number of cases?
Edit: here a smallp Python script which creates a random matrix and count the number of cases in each zone defined by your "walls".
import numpy as np
matrix = np.random.randint(2, size=(10, 10))
print(matrix)
M, N = matrix.shape
walked = []
zonesCount = []
def pathCount(x, y):
if x < 0 or y < 0 or x >= M or y >= N:
return 0
if matrix[x, y] == 1: # I replaced * by 1 and . by 0 for easier generation
return 0
if (x, y) in walked:
return 0
walked.append((x, y))
count = 1
for i in [x - 1, x, x + 1]:
for j in [y - 1, y, y + 1]:
if (i, j) != (x, y):
count += pathCount(i, j)
return count
for x in range(M):
for y in range(N):
if not (x, y) in walked:
zonesCount.append(pathCount(x, y))
print('Max zone count :', max(zonesCount))
And here is the result:
[[0 0 1 0 0 0 1 0 1 0]
[1 0 1 0 0 0 1 0 1 1]
[0 1 0 0 1 0 0 1 1 1]
[0 0 1 0 0 0 1 1 0 1]
[1 0 1 1 1 1 0 1 1 0]
[1 0 1 1 1 1 0 1 1 0]
[0 0 0 1 1 1 0 0 0 0]
[1 0 0 1 1 0 0 1 1 0]
[0 1 0 1 0 0 1 0 1 1]
[0 1 1 0 0 0 1 0 1 0]]
Max zone count : 50

Octave model matrix

Is there a simple (non for loop) way to create a model matrix in Octave. In R i use model.matrix() to do this.
I have this array:
array = [1;2;3;2]
and i need (for regression reasons)
*(model = [1 0 0 0; 0 1 0 1; 0 0 1 0])* EDIT on my side
result is this model (colum 1 is for 1, column 2 for the two's etc.:
model = [1 0 0 ; 0 1 0 ; 0 0 1 ; 0 1 0]
I can do this with a for loop:
model = zeros(4,3);
for i=1:4
model(i,array(i)) = 1;
end
but it would be nice to do this in one step something like:
model = model.matrix(array)
i can than include it in a formula straight away
You need to turn your values into linear indices like so:
octave:1> array = [1 2 3 2];
octave:2> model = zeros ([numel(array) max(array)]);
octave:3> model(sub2ind (size (model), 1:numel(array), array)) = 1
model =
1 0 0
0 1 0
0 0 1
0 1 0
Because your matrix will be very sparse, a possible optimization is to create a sparse matrix instead.
octave:4> sp = sparse (1:numel(array), array, 1, numel (array), max (array))
sp =
Compressed Column Sparse (rows = 4, cols = 3, nnz = 4 [33%])
(1, 1) -> 1
(2, 2) -> 1
(4, 2) -> 1
(3, 3) -> 1
octave:5> full (sp)
ans =
1 0 0
0 1 0
0 0 1
0 1 0
This will take a lot less memory but many functions will be unable to handle them and convert them to a full matrix anyway. So whether this is worth is dependent on what you want to do next.

Finding minimum number of presses to shut down lamps

I tried to solve a programming problem but my I was unable to see an efficient algorithm. Situation is like this: We have a set of n lamps which can be on (1) or off (0) like this: 1110001011101. That byte string means that there are 13 lamps forming a circle where first three lamps are on, then 3 next off and so on and circle mean that the last lamp is next to the first one.
Then we have been given an integer m>0. It means that in any turn we can choose a lamp and then it and its m adjacent lamps changes their state s to 1-s. I.e. if m=2 and lamp states are 1110001011101 then applying the process to the first lamp we get the sequence 0000001011110.
Now the question is that if the string of length about 2200 and m about 110 are fixed, how one can develop an algorithm that shut downs all the lamps with minimum number of turns?
This problem is similar to the well-known "lights out" problem. http://en.wikipedia.org/wiki/Lights_Out_%28game%29 One way to approach it is by using linear algebra. It's easier to understand with smaller numbers, say length = 5 and m = 1.
First note that choosing a lamp and changing it (and its neighbors') state twice has no effect. Second note that the order in which lamps (and their neighbors) are switch doesn't matter. So a strategy is just a set of lamps. We'll represent lamps that are chosen to be part of the strategy by 1 and lamps that are not chosen by 0. We place the 1's and 0's in a column vector, e.g., (0 1 1 0 1)^T where T is for transpose (rows become columns). That strategy means toggle the lamp in position 1 (starting at position 0, of course) and its two neighbors; then the lamp in position 2 and its two neighbors, and finally the lamp in position 4 and its two neighbors.
The effect of a strategy can be calculated by matrix multiplication over the field GF(2). GF(2) has just 2 elements, 0 and 1, with ordinary rules of arithmetic except for the rule 1 + 1 = 0. Then the effect of the strategy above is the result of matrix multiplication by a matrix with the result of choosing lamp i in the i-th column, in other words by a "circulant matrix` as follows:
[ 1 1 0 0 1 ] [0] [0]
[ 1 1 1 0 0 ] [1] [0]
[ 0 1 1 1 0 ] [1] = [0]
[ 0 0 1 1 1 ] [0] [0]
[ 1 0 0 1 1 ] [1] [1]
The result of the strategy (0 1 1 0 1)^T is to toggle only the light in the last position. So if you start with only the light in the last position lit, and apply the strategy, all the lights will be off.
In this simple case, we represent the initial configuration by a column vector b. The solution strategy is then a column vector x satisfying the matrix equation Ax = b.
The question now becomes, for given b, 1) is there an x satisfying Ax=b? 2) Is the solution x unique? If not, which x has the least 1's? 3) How can it be calculated?
The answers to the above questions will depend on the numbers "length" and "m" for the particular problem at hand. In the length = 5, m = 1 problem considered above, the theory of linear algebra tells us that there is a unique solution for any b. We can get solutions for b of the form (0 0 ... 1 ... 0)^T, in other words one 1 and the rest zero, by "rotating" the solution (0 1 1 0 1)^T. We can represent any solution uniquely as a linear combination of those solutions, so the strategy/solution with the minimum number of 1's is the same as the unique solution for any given initial state.
On the other hand, with length = 6 and m = 1, all three strategies (100100)^T, (010010)^T, and (001001)^T map to outcome (111111)^T, so that there is not a unique solution in some cases; by the theory of linear algebra, it follows that there is no solution in some other cases.
In general, we can tell whether solutions exist and are unique using Gaussian elimination. In the 5x5 case above, add row 0 to rows 1 and 4;
[ 1 1 0 0 1 ] [1 0 0 0 0] [ 1 1 0 0 1 ] [1 0 0 0 0]
[ 1 1 1 0 0 ] [0 1 0 0 0] [ 0 0 1 0 1 ] [1 1 0 0 0]
[ 0 1 1 1 0 ] [0 0 1 0 0] -> [ 0 1 1 1 0 ] [0 0 1 0 0] ->
[ 0 0 1 1 1 ] [0 0 0 1 0] [ 0 0 1 1 1 ] [0 0 0 1 0]
[ 1 0 0 1 1 ] [0 0 0 0 1] [ 0 1 0 1 0 ] [1 0 0 0 1]
then swap rows 1 and 2; then add row 1 to row 0 and row 4,
[ 1 1 0 0 1 ] [1 0 0 0 0] [ 1 0 1 1 1 ] [1 0 1 0 0]
[ 0 1 1 1 0 ] [0 0 1 0 0] [ 0 1 1 1 0 ] [0 0 1 0 0]
[ 0 0 1 0 1 ] [1 1 0 0 0] -> [ 0 0 1 0 1 ] [1 1 0 0 0] ->
[ 0 0 1 1 1 ] [0 0 0 1 0] [ 0 0 1 1 1 ] [0 0 0 1 0]
[ 0 1 0 1 0 ] [1 0 0 0 1] [ 0 0 1 0 0 ] [1 0 1 0 1]
then add row 2 to rows 0, 1, 3, 4; then add row 3 to rows 1, 2;
[ 1 0 0 1 0 ] [0 1 1 0 0] [ 1 0 0 0 0 ] [1 0 1 1 0]
[ 0 1 0 1 1 ] [1 1 1 0 0] [ 0 1 0 0 1 ] [0 0 1 1 0]
[ 0 0 1 0 1 ] [1 1 0 0 0] -> [ 0 0 1 0 1 ] [1 1 0 0 0] ->
[ 0 0 0 1 0 ] [1 1 0 1 0] [ 0 0 0 1 0 ] [1 1 0 1 0]
[ 0 0 0 0 1 ] [0 1 1 0 1] [ 0 0 0 0 1 ] [0 1 1 0 1]
and finally add row 4 to rows 1, 2:
[ 1 0 0 0 0 ] [1 0 1 1 0]
[ 0 1 0 0 0 ] [0 1 0 1 1]
[ 0 0 1 0 0 ] [1 0 1 0 1]
[ 0 0 0 1 0 ] [1 1 0 1 0]
[ 0 0 0 0 1 ] [0 1 1 0 1]
You can read off the basis of solutions in the columns of the right matrix. For example, the solution we used above is in the last column of the right matrix.
You should try Gaussian elimination in the length = 6, m = 1 case discussed above to see what happens.
In the given case (length = 2200, m = 110), I suspect that solutions always exist and are unique because the number of lamps toggled in one move is 221, which is relatively prime to 2200, but I suggest you use Gaussian elimination to find an explicit strategy for any starting position b. How would you minimize the number of moves if there were not a unique strategy?
There's a general solution to flipping problems like this using linear algebra over Z/2Z (that is the field containing only the numbers 0 and 1).
Suppose there's N bulbs and N switches. Let M be an N by N matrix with a 1 in position i, j if pressing switch i toggles bulb j. Here your matrix will look like this for N=5, m=1:
1, 1, 0, 0, 1
1, 1, 1, 0, 0
0, 1, 1, 1, 0
0, 0, 1, 1, 1
1, 0, 0, 1, 1
Let x be a column vector of size N, where each entry is 0 or 1.
Then Mx (that is, the product of the matrix M and the vector x over Z/2Z) is a column vector of size N which is the result of pressing the switches corresponding to 1s in x. That's because in Z/2Z, multiplication is like "and" and addition is like "xor".
Let v be a column vector of size N, with v_i=1 if bulb i is initially lit. Then x solves the problem if it's a solution to the linear system Mx = v. It can be solved, for example, using gaussian elimination.
Well, your explanation doesn't make it clear if the lamps should be only turned off or "flipped" (i.e., 0's become 1's and 1's become 0's). Your example data just turns them off.
If that's the case, just set the 110 lamps to 0 - that would be quicker than querying their state before switching them off. Assuming your lamps are in an array called "lamps" and the starting lamp position is startPos:
// These first 2 lines added after Kolmar remark about adjacent lamps meaning lamps to the left and right.
startPos = startPos - m;
if (startPos < 0) startPos += lamps.length;
for (int i=0; i <= m + 1; i++){
if ((i + startPos) > lamps.length) startPos = 0;
lamps[i + startPos] = 0;
}
If you need to "flip" the lamp's state, change the last line of the loop to:
lamps[i + startPos] = 1-lamps[i + startPos];

Resources