How to detect connected components in a 2D array? - arrays

As mentioned the title above. I want to find out whether there are how many components in a 2D Array. Whereas, components are made by 1 numbers and there are only 0 and 1 number in the array.
I implemented this problem by using DFS (Deep First Search) algorithm with recursive calls and an array to mark cell visited.
However, I want to implement this problem with another way without using recursion, stack, queue, struct... Only using for/while function are allowed.
Example:
Array data:
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 1 1 1 0 1 1 0 1 0 0 0 0 0 1
0 0 1 0 1 0 1 1 0 1 0 1 1 1 0 1
0 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1
0 0 1 0 1 0 0 0 0 1 0 1 0 1 0 1
0 0 1 1 1 0 0 0 0 1 0 1 0 1 0 1
0 0 0 0 0 1 1 1 0 1 0 1 1 1 0 1
0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1
0 0 0 0 0 1 1 1 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0
0 1 0 0 0 1 0 0 0 0 1 0 0 1 0 0
0 1 0 1 1 1 1 1 0 0 1 1 1 1 0 0
0 1 0 1 0 1 0 1 0 0 1 1 1 1 0 0
0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
Array after determined components with specific labels.
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 2 2 2 0 3 3 0 1 0 0 0 0 0 1
0 0 2 0 2 0 3 3 0 1 0 4 4 4 0 1
0 0 2 0 2 0 0 0 0 1 0 4 0 4 0 1
0 0 2 0 2 0 0 0 0 1 0 4 0 4 0 1
0 0 2 2 2 0 0 0 0 1 0 4 0 4 0 1
0 0 0 0 0 5 5 5 0 1 0 4 4 4 0 1
0 0 0 0 0 5 0 5 0 1 0 0 0 0 0 1
0 0 0 0 0 5 5 5 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 6 6 6 6 6 0 0 0 0 7 7 7 7 0 0
0 6 0 0 0 6 0 0 0 0 7 0 0 7 0 0
0 6 0 6 6 6 6 6 0 0 7 7 7 7 0 0
0 6 0 6 0 6 0 6 0 0 7 7 7 7 0 0
0 6 6 6 6 6 6 6 0 0 0 0 0 0 0 0
0 6 6 6 6 6 6 6 0 0 0 0 0 0 0 0
Thank you in advance.

I guess you could iterate through the matrix, and check the neighbours for each cell, and copy the value of the neighbour if that is > 0 or set a new value if all the neighbours are 0. In pseudocode:
comp = 1
for i = 0 to n:
for j = 0 to n:
for nei : neighbours(i, j):
if nei > 0:
m[i,j] = nei
break
m[i,j] = comp
comp++
And neighbours are the 4 (or 2) adjacent neighbouring cells to (i, j)

Related

find all 256 cases of 2 numbers in array of 8 length [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
How can I find all combination of 2 numbers {0,1} in array of 8 length in c,
example
arr[]={0,0,0,0,0,0,0,0}
arr[]={0,0,0,0,0,0,0,1}
arr[]={0,0,0,1,1,0,0,1}
an so on
You can generate all combinations fairly easily using a recursive procedure:
arr = [0,0,0,0,0,0,0,0]
Generate(position)
if position > 8 then
print arr
else
arr[position] = 0
Generate(position+1)
arr[position] = 1
Generate(position+1)
Generate(1)
This will go down 8 levels in the call stack and then print the array [0, 0, 0, 0, 0, 0, 0, 0]. Then it will return to the 7th level, and go down again, printing [0, 0, 0, 0, 0, 0, 0, 1]. It will repeat this process, toggling each of the higher-order bits in turn until all 256 possibilities are generated. Instead of printing the arrays, you could save the arrays as you go.
Another possibility is to just create the 256 8-bit arrays and use an iterative procedure to toggle the elements in such a way as to guarantee you cover all your bases. An example with 4-bit strings:
0 0 0 0 0 0 0 0
0 0 0 0 => toggle bits in 4th position => 0 0 0 1
0 0 0 0 in blocks of size 1 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
0 0 0 1 => toggle bits in 3rd position => 0 0 0 1
0 0 0 0 in blocks of size 2 0 0 1 0
0 0 0 1 0 0 1 1
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 1 0 0 1 1
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 1 0 0 1 1
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 1 0 0 1 1
0 0 0 0 0 0 0 0
0 0 0 1 => toggle bits in 2nd position => 0 0 0 1
0 0 1 0 in blocks of size 4 0 0 1 0
0 0 1 1 0 0 1 1
0 0 0 0 0 1 0 0
0 0 0 1 0 1 0 1
0 0 1 0 0 1 1 0
0 0 1 1 0 1 1 1
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 1
0 0 1 0 0 0 1 0
0 0 1 1 0 0 1 1
0 0 0 0 0 1 0 0
0 0 0 1 0 1 0 1
0 0 1 0 0 1 1 0
0 0 1 1 0 1 1 1
0 0 0 0 0 0 0 0
0 0 0 1 => toggle bits in 1st position => 0 0 0 1
0 0 1 0 in blocks of size 8 0 0 1 0
0 0 1 1 0 0 1 1
0 1 0 0 0 1 0 0
0 1 0 1 0 1 0 1
0 1 1 0 0 1 1 0
0 1 1 1 0 1 1 1
0 0 0 0 1 0 0 0
0 0 0 1 1 0 0 1
0 0 1 0 1 0 1 0
0 0 1 1 1 0 1 1
0 1 0 0 1 1 0 0
0 1 0 1 1 1 0 1
0 1 1 0 1 1 1 0
0 1 1 1 1 1 1 1

How to find elements in an array based on a search from another array

Imagine that i have two arrays:
a = [1 1 1 1 5 5 5 5 5 5 8 8;
1 1 1 3 5 5 5 5 5 8 8 8;
1 1 3 3 3 5 5 5 8 8 8 8;
1 3 3 3 3 3 5 8 8 8 8 8;
4 4 4 9 9 0 3 3 8 8 8 8;
4 4 4 9 0 0 3 3 3 3 8 8;
4 4 9 9 0 0 0 0 0 0 1 1;
4 9 9 9 0 0 0 0 0 0 1 1;
9 9 9 9 9 0 0 0 7 7 7 7];
b = [4 5 7];
I want ans like this :
ans =
0 0 0 0 1 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0 0 0
0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1
The function ismember does exactly that:
ismember(a, b)
ans =
9×12 logical array
0 0 0 0 1 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0 0 0
0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1
Not sure if this is the most efficient but this should work:
c = zeros(size(a));
for i = 1:numel(a)
if ismember(a(i), b(:))
c(i) = 1
end
end
Testing on some smaller arrays:
octave:1> a = [1 1 5 5 8 8;1 5 1 3 5 8]
a =
1 1 5 5 8 8
1 5 1 3 5 8
octave:2> b = [5 8]
b =
5 8
octave:3> c = zeros(size(a));
for i = 1:numel(a)
if ismember(a(i), b(:))
c(i) = 1
end
end
c =
0 0 0 0 0 0
0 1 0 0 0 0
.
.
.
c =
0 0 1 1 1 1
0 1 0 0 1 0
c =
0 0 1 1 1 1
0 1 0 0 1 1

2 dimensional array with seats by using class

I wanted to create an array by using class at the same time which it must be produced as below:
Airline A Airline B Airline C
1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0
----------- ----------- -----------
2 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0
3 0 0 0 0 0 3 0 0 0 0 0 3 0 0 0 0 0
4 0 0 0 0 0 4 0 0 0 0 0 4 0 0 0 0 0
5 0 0 0 0 0 5 0 0 0 0 0 5 0 0 0 0 0
How can I create this?

Data frame column value with range condition [duplicate]

This question already has answers here:
R add new column with predefined pattern
(2 answers)
Closed 8 years ago.
I want to create the columns below wherein I can specify the range to apply the value 1 to one column and the rest 0. I know this has been asked and answered perfectly here before but I can't find that particular one right now.
time1 time2 time3 time4 time5
1 1 0 0 0 0
2 1 0 0 0 0
3 1 0 0 0 0
4 1 0 0 0 0
5 1 0 0 0 0
6 0 1 0 0 0
7 0 1 0 0 0
8 0 1 0 0 0
9 0 1 0 0 0
10 0 1 0 0 0
11 0 0 1 0 0
12 0 0 1 0 0
13 0 0 1 0 0
14 0 0 1 0 0
15 0 0 1 0 0
16 0 0 0 1 0
17 0 0 0 1 0
18 0 0 0 1 0
19 0 0 0 1 0
20 0 0 0 1 0
21 0 0 0 0 1
22 0 0 0 0 1
23 0 0 0 0 1
24 0 0 0 0 1
25 0 0 0 0 1
I can't recall how this was generated but the answer included an n option to specify the intervals per column.
You could do
cols <- 4
diag(cols)[rep(1:cols, each=cols), ]
[,1] [,2] [,3] [,4]
[1,] 1 0 0 0
[2,] 1 0 0 0
[3,] 1 0 0 0
[4,] 1 0 0 0
[5,] 0 1 0 0
[6,] 0 1 0 0
[7,] 0 1 0 0
[8,] 0 1 0 0
[9,] 0 0 1 0
[10,] 0 0 1 0
[11,] 0 0 1 0
[12,] 0 0 1 0
[13,] 0 0 0 1
[14,] 0 0 0 1
[15,] 0 0 0 1
[16,] 0 0 0 1
I finally found the exact question: "R add new column with predefined pattern" and the solution I was looking for is:
range <- 5
cols <- 5
y <- gl(cols, range)
mat <- model.matrix(~y-1) # -1 is for remove the intercept
colnames(mat) <- paste0('var', 1:cols)
mat
It provides a dataframe ready to be included in other dataframes (via merge(old, new)) and specifying a name for the columns.
The output is:
var1 var2 var3 var4 var5
1 1 0 0 0 0
2 1 0 0 0 0
3 1 0 0 0 0
4 1 0 0 0 0
5 1 0 0 0 0
6 0 1 0 0 0
7 0 1 0 0 0
8 0 1 0 0 0
9 0 1 0 0 0
10 0 1 0 0 0
11 0 0 1 0 0
12 0 0 1 0 0
13 0 0 1 0 0
14 0 0 1 0 0
15 0 0 1 0 0
16 0 0 0 1 0
17 0 0 0 1 0
18 0 0 0 1 0
19 0 0 0 1 0
20 0 0 0 1 0
21 0 0 0 0 1
22 0 0 0 0 1
23 0 0 0 0 1
24 0 0 0 0 1
25 0 0 0 0 1

matlab using cell2mat and reshape data to other form

I have cell array
Columns 1 through 6
[8x8 uint8] [8x8 uint8] [8x8 uint8] [8x8 uint8] [8x8 uint8] [8x8 uint8]
Columns 7 through 8
[8x8 uint8] [8x8 uint8]
if I use cell2mat function, I get this
Columns 1 through 18
0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 1 0 0
0 1 1 1 0 0 1 1 1 1 0 0 0 1 0 1 1 0
0 1 1 1 0 1 0 1 1 0 1 1 0 1 0 1 0 1
0 1 1 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1
0 1 1 1 1 0 0 1 1 0 0 0 1 1 0 1 0 0
0 1 1 0 1 1 1 1 1 0 1 1 0 0 0 1 0 0
0 1 1 0 1 1 0 1 1 1 1 1 0 1 0 1 0 1
0 1 1 0 0 1 0 0 1 1 0 0 1 1 0 1 1 1
Columns 19 through 36
1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0
1 1 0 1 1 0 0 0 0 1 1 1 0 1 0 0 0 0
0 0 0 0 1 0 0 1 0 1 1 0 1 0 0 1 0 0
1 1 0 1 1 1 0 0 0 1 1 0 0 1 0 1 1 1
1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 1 0
0 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 1 0
0 0 0 0 1 0 0 0 0 1 1 1 0 1 0 1 1 1
Now I want matrix with 8 columns.
What I want is this
0 1 0 1 0 0 1 0
0 1 1 1 0 0 1 1
0 1 1 1 0 1 0 1
0 1 1 0 0 1 0 0
0 1 1 1 1 0 0 1
0 1 1 0 1 1 1 1
0 1 1 0 1 1 0 1
0 1 1 0 0 1 0 0
0 0 1 0 0 0 0 1
1 1 0 0 0 1 0 1
1 0 1 1 0 1 0 1
1 0 1 0 0 0 0 0
1 0 0 0 1 1 0 1
1 0 1 1 0 0 0 1
1 1 1 1 0 1 0 1
1 1 0 0 1 1 0 1
.
.
.
.
.
If I got your question correctly, you simply need to transpose the cell array before transforming it. See the following example (I edited the actual output to compress the display a bit):
> a
a =
{
[1,1] =
1 0 0
0 1 0
0 0 1
[1,2] =
2 0 0
0 2 0
0 0 2
[1,3] =
3 0 0
0 3 0
0 0 3
}
> cell2mat(a)
ans =
1 0 0 2 0 0 3 0 0
0 1 0 0 2 0 0 3 0
0 0 1 0 0 2 0 0 3
> cell2mat(a')
ans =
1 0 0
0 1 0
0 0 1
2 0 0
0 2 0
0 0 2
3 0 0
0 3 0
0 0 3
Note that using reshape brings another ordering:
> reshape(cell2mat(a), 9,3)
ans =
1 2 3
0 0 0
0 0 0
0 0 0
1 2 3
0 0 0
0 0 0
0 0 0
1 2 3
Just transposing your cell array and then passing it to cell2mat will probably be enough.
Another (less preferred, loops are generally not welcome in MATLAB) solution is to loop over your cell array and use matrix concatenation. If your cell array has name ca, this will do the thing:
imat = []; for i = 1:numel(ca); imat = [imat; ca{i}]; end
The answer will be in imat.
You can use the reshape function.
tmp = cell2mat(...);
res = reshape(tmp, numel(tmp)/8, 8);

Resources