Given a 2d array with Boolean islands where 1 is land and 0 is water. Lets say I want only the island to which I point with a coordinate. How would I transfer it to a new array where everything beyond the borders of that island is water.
Here is a simple example.
I am given this 2d array
1 0 0 1 1 0
0 1 0 0 0 1
1 1 1 0 0 0
0 1 0 1 0 1
1 1 1 1 1 0
and the coordinate [1][2] (that would be the 2nd column 3rd row)
Then the final result in the new array should be something like
0 0 0 0 0 0
0 1 0 0 0 0
1 1 1 0 0 0
0 1 0 1 0 0
1 1 1 1 1 0
The pixels can only be connected either up, down, left or right to each other (no diagonals)
Related
There is a grid, the edges of which are always wall.
The internal area of the grid is also divided by walls into several sub-areas, like this
1 = Wall,
0 = Empty.
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 1 0 0 0 0 0 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 1 0 1 1 1 1 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
I need to find the smallest empty sub-area.
How do i do it?
Telescope's suggestion is correct. Here's a slightly more detailed illustration of how you might approach this.
Given an M x N grid, you will loop over the (M - 2)(N - 2) subgrid ignoring the outer walls. When looking at a given grid cell:
if the grid cell is 0, you have not seen this area yet; begin a flood fill here that counts the number of adjacent 0s and changes them to 2 to mark them as having been seen already in some enclosed area, to avoid having to re-flood this area again later
if a grid cell is 1, it's an interior wall and should be skipped
if the grid cell is 2, you have seen this area already and can skip it
At the end, you'll have counted the area of each distinct enclosed section and can choose the biggest, smallest, or whichever you need to know.
This algorithm will visit each cell at most a few times (worst case is a 1 surrounded by 0s which the flood fill will bump into up to four times, and the wall will be checked once during the subgrid scan). Therefore, the time complexity is O(MN). The algorithm uses the grid itself to keep track of what it has done so far, so no extra memory is used; if the grid must not be modified in place, an extra O(MN) memory can be allocated for a working copy.
I'm not quite sure how to describe what I mean, so let me try to explain by example (bear with me).
When you simply increment an integer you get a binary sequence like so (let's assume 8 bits for this question):
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 0
0 0 0 0 0 1 0 1
0 0 0 0 0 1 1 0
0 0 0 0 0 1 1 1
0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 1
0 0 0 0 1 0 1 0
0 0 0 0 1 0 1 1
0 0 0 0 1 1 0 0
0 0 0 0 1 1 0 1
0 0 0 0 1 1 1 0
0 0 0 0 1 1 1 1
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 1
0 0 0 1 0 0 1 0
0 0 0 1 0 0 1 1
0 0 0 1 0 1 0 0
0 0 0 1 0 1 0 1
0 0 0 1 0 1 1 0
0 0 0 1 0 1 1 1
0 0 0 1 1 0 0 0
0 0 0 1 1 0 0 1
0 0 0 1 1 0 1 0
0 0 0 1 1 0 1 1
0 0 0 1 1 1 0 0
0 0 0 1 1 1 0 1
0 0 0 1 1 1 1 0
0 0 0 1 1 1 1 1
[ ... etc ... ]
One way to visualize this is that each column represents a "clock". Each clock/column is half the frequency of its right neighbor.
So the right-most clock has one 0 followed by one 1, etc. The next clock has two 0s followed by two 1s, etc and so on...
I'm interested in a sequence of binary strings in which each clock is an integer division of its neighbor.
So the right-most clock is still one 0, one 1, the next clock is still two 0s, two 1s, but the third clock is three 0s and three 1s, etc.
Instead of /1 /2 /4 /8 /16 ... it's now /1 /2 /3 /4 /5 ....
The sequence now looks like this:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 1 1 1
0 0 0 0 1 1 0 0
0 0 0 1 1 1 0 1
0 0 1 1 1 0 1 0
0 1 1 1 1 0 1 1
1 1 1 1 0 0 0 0
1 1 1 1 0 1 0 1
1 1 1 0 0 1 1 0
1 1 1 0 0 1 1 1
1 1 0 0 1 0 0 0
1 1 0 0 1 0 0 1
1 0 0 0 1 0 1 0
1 0 0 1 1 1 1 1
0 0 0 1 0 1 0 0
0 0 0 1 0 1 0 1
0 0 1 1 0 0 1 0
0 0 1 1 0 0 1 1
[ ... etc ... ]
Question: Is there an operation/algorithm which can give me the value at i given the value at i-1?
In other words, let's say I'm at the 4th step (0 0 0 0 0 1 1 1). Is there some operation I can perform on this number to get the value at the 5th step (0 0 0 0 1 1 0 0), and similarly for any other step?
In the divide-by-2 case you simply increment the number (i++) but in the divide-by-N case I can't seem to figure out a similar way to go from one to the next. Am I missing something obvious?
I've tried translating the sequencing into decimal but that pattern is 0, 1, 2, 7, 12, 29, 58, etc which doesn't stand out to me as anything obvious.
The brute-force way that I'm doing it now is that I have an array of counters (one for each column/clock) and I independently reset each count when the respective column's "period" is reached (so 2 for the first column, 3 for the next, etc). But that feels ugly.
I'd love to do this directly on the number without requiring an array of counters. Is this even possible? Is this a known sequence? I'm not even sure what to Google to be honest. I'd appreciate any kind of leads on this. I'm happy to go down the rabbit hole with some guidance.
UPDATE
As per #borrible's observation, there are more than one values for i-1 for a given i so it turns out the solution to my original question is ambiguous. So I will expand my question to allow i as an input (in addition to the i-1th value.
Without knowing i you are only going be able to generate the successor to a given sequence if that sequence uniquely implies i (modulo the number of bit sequences). If this is not the case the successor to a given sequence is ambiguous.
Lets consider the first few sequences for 3 bits:
0 0 0
0 0 1
0 1 0
1 1 1
1 0 0
1 0 1
0 1 0
0 1 1
Note that 0 1 0 is succeeded by both 1 1 1 and 0 1 1; i.e. it is ambiguous. Given 0 1 0 but not i you cannot deduce the next sequence. You can see a similar ambiguity in 4 bit sequences for 0 1 1 1 etc...
In other words, without knowing i, your problem is not generally solvable.
This sequence can be considered as a set of state machines, each with 2,4,6,...,16 states. The least common multiple of 2,4,6,...,16, i.e. the length of the sequence, is 1680. Eight bits only lets us represent 256 values, so even if we were allowed to select the state encoding (which we aren't!), we wouldn't be able to uniquely identify all possible states.
If we know the index i (or, as the sequence length is 1680, it is sufficient to know the index modulo 1680), digit j is given by (i mod (2 * j)) / j.
So I have this matrix A, which is made of 1 and zeros, I have about 10 to 14 white spots of many pixels, but I want only 1 white pixel/centers coordinate for every cluster of white, how do I calculate how many cluster there are and their centers.
Try to imagine the matrix A as the night sky with white starts in black sky and how to I count the stars and the stars centers, plus the star are made of cluster of white pixels.
also the clusters are not all exactly the same size.
Here is some code using bwlabel and/or regioprops, which are used to identify connected components in a matrix and a buch of other properties, respectively. I think it suits your problem quite well; however you might want to adapt my code a bit as its more of a starting point.
clear
clc
%// Create dummy matrix.
BW = logical ([ 1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 0 0 0]);
%// Identify clusters.
L = bwlabel(BW,4)
Matrix L looks like this:
L =
1 1 1 0 3 3 3 0
1 1 1 0 3 3 3 0
1 1 1 0 3 3 3 0
0 0 0 0 0 0 0 0
0 0 0 0 0 4 4 0
2 2 2 2 0 4 4 0
2 2 2 2 0 4 4 0
2 2 2 2 0 0 0 0
Here you have many ways to locate the center of the clusters. The first one uses the output of bwlabel to find each cluster and calculate the coordinates in a loop. It works and its didactic but it's a bit long and not so efficient. The 2nd method, as mentioned by #nkjt, uses regionprops which does exactly what you want using the 'Centroid' property. So here are the 2 methods:
Method 1: a bit complicated
So bwlabel identified 4 clusters, which makes sense. Now we need to identify the center of each of those clusters. My method could probably be simplified; but I'm a bit out of time so fell free to modify it as you see fit.
%// Get number of clusters
NumClusters = numel(unique(L)) -1;
Centers = zeros(NumClusters,2);
CenterLinIdices = zeros(NumClusters,1);
for k = 1:NumClusters
%// Find indices for elements forming each cluster.
[r, c] = find(L==k);
%// Sort the elements to know hot many rows and columns the cluster is spanning.
[~,y] = sort(r);
c = c(y);
r = r(y);
NumRow = numel(unique(r));
NumCol = numel(unique(c));
%// Calculate the approximate center of the cluster.
CenterCoord = [r(1)+floor(NumRow/2) c(1)+floor(NumCol/2)];
%// Actually this array is not used here but you might want to keep it for future reference.
Centers(k,:) = [CenterCoord(1) CenterCoord(2)];
%// Convert the subscripts indices to linear indices for easy reference.
CenterLinIdices(k) = sub2ind(size(BW),CenterCoord(1),CenterCoord(2));
end
%// Create output matrix full of 0s, except at the center of the clusters.
BW2 = false(size(BW));
BW2(CenterLinIdices) = 1
BW2 =
0 0 0 0 0 0 0 0
0 1 0 0 0 1 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
Method 2 Using regionprops and the 'Centroid' property.
Once you have matrix L, apply regionprops and concatenate the output to get an array containing the coordinates directly. Much simpler!
%// Create dummy matrix.
BW = logical ([ 1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0
0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 1 1 0
1 1 1 1 0 0 0 0]);
%// Identify clusters.
L = bwlabel(BW,4)
s = regionprops(L,'Centroid');
CentroidCoord = vertcat(s.Centroid)
which gives this:
CentroidCoord =
2.0000 2.0000
2.5000 7.0000
6.0000 2.0000
6.5000 6.0000
Which is much simpler and gives the same output once you use floor.
Hope that helps!
I want to store a binary matrix into a database.
Matrix example:
0 1 0 0 1 1 0 1
0 1 0 0 0 1 0 0
0 1 1 0 0 1 1 1
0 1 0 0 1 1 0 0
0 1 0 0 0 1 0 0
0 1 1 0 0 1 0 0
0 1 0 1 0 0 0 0
0 1 0 0 1 1 1 0
Which is the best way to do that?
OBS: I don't understand much of db.
Thanks.
you can store it as varchar(n^2). If you don't need to work on it in the DB, you can also store each line in the matrix as it's value- for example, your first line will be 77.
or if you know the number of digits in any line and colomn you can save it in one decimal(11135377233198751900) or hexadecimal(9A88CE9888C8A09C) number
I have an array:
1 1 1 0 0
1 2 2 0 0
1 2 3 0 0
0 0 0 0 0
0 0 0 0 0
I want to make it
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
It is like rotating 1/4 piece of pie 270 degrees to fill out the remaining parts of the pie to make a full circle. Essentially mirroring the entire corner in all directions. I don't want to use any in built matlab features if possible - just some vector tricks if possible. Thanks.
EDIT:
This is embedded within an matrix of zeros of arbitrary size. I want it to work in both the above example and say this example:
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0 0 0 0 0
0 0 1 2 2 0 0 0 0 0 0 0 0 0
0 0 1 2 3 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
Ideally, I want to have a vector say [1,2,3.. N] which can be rotated circularly about the highest value in the array (N) centered about some point xc,yc in the grid. Or if this isn't possible, take an base array [1 1 1, 1 2 2, 1 2 3] and rotate it such that 3 is in the centre and you fill a circle as in the 2nd matrix above.
EDIT:
I found rot90(M,k) rotates matrix M k times but this produces:
Mrot = M + rot90(M,1) + rot90(M,2) + rot90(M,3)
Mrot =
1 1 2 1 1
1 2 4 2 1
2 4 12 4 2
1 2 4 2 1
1 1 2 1 1
This stacks it in the x,y directions which isn't correct.
Assuming the corner you want to replicate is symmetric about the diagonal (as in your example), then you can do this in one indexing step. Given a matrix M containing your sample 5-by-5 matrix, here's how to do it:
>> index = [1 2 3 2 1];
>> M = M(index, index)
M =
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1