0
votes

my problem is: I have to make a code that takes a matrix 6x6 of 0's and 1's and check certain conditions in each position of the matrix to iterate through it, and create a matrix with the new values based on the conditions, that are based in the neighbor elements of the center value. The conditions are the following:

if the center value is 1 it has 3 options:

-If in the neighbor cells there is only one cell containing a number 1, or cero cells containing a number 1 the center value converts from 1 to 0.

-If the neighbor cells of the center value contains in total 4 or more 1's, it converts from 1 to 0.

-And if the neighbor cells contain in total 2 or 3 number 1's, it keeps being 1.

Now, if the center value is 0, it has 1 option:

-If the neighbor cells contain 3 1's in total (tops), it converts from 0 to 1.

-Else, it keeps being 0

The matrix is the following:

A = [0 1 0 1 1 0; 1 0 1 0 0 1; 1 1 0 1 1 1; 0 0 1 0 0 0; 0 1 0 0 0 1; 1 1 1 0 0 1]

So for example, the number 1 in the position A(5,2) should become 0, because it has 4 1's surrounding it, and another example, the zero in A(4,6) should become 1, because it has 3 1's surrounding it.

I made 2 loops using 1 for the rows and another for the columns to iterate through each value of the matrix, but in the conditional I don't know how to check the values of the surrounding cells or neighbor cells

I'm new to Matlab, if you can help me it would be great! Thanks.

Edit: added code the code I've made until now.

[f,c]=size(A)
for i=1:f
       for j=1:c
            if A(i,:)==1

              if A(i+1,j+1)==1 && A(i+1,j-1)==1 && A(i-1,j-1)==1
                  A(i,:)=1;
              end 

          elseif A(i,:)==0

              if A(i+1,j+1)==1 && A(i+1,j-1)==1 && A(i-1,j-1)==1
                  A(i,:)=1;

              end
          end
     end
 end

I tried to set the conditions to the (i-1,j-1),(i+1,j+1),(i+1,j),(i,j+1),(i-1,j),(i,j-1) but I think that will not work because I'm checking coditions as a group not counting the total numbers of 1 in the neighbors

Edit 2: been thinking how to solve it and I thought that I could make a variable that counts the quantity of 1's in the surroundings of the center value, but it gives me an error that it exceeds the dimensions of the matrix in line 50, even after I made considerations for the first column, row and last column, row.

This is the complete code:

[f,c] = size(gen0);
nrogen = input('Introduzca el número de generaciones de bacterias que quiera crecer: ');

if isempty(nrogen) || ~isnumeric(nrogen) || ~isscalar(nrogen) || round(nrogen)~=nrogen || nrogen < 0
    disp('Número no pertinente, intente de nuevo');
    return
end

nac = 0;
mue = 0;
neigh = 0;

for k=1:nrogen
    for i=1:f
        for j=1:c
            if i>1 && i<6
                if gen0(i+1,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i+1,j)==1
                    neigh=neigh+1;
                end

                if gen0(i-1,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i-1,j)==1
                    neigh=neigh+1;
                end

            elseif i==1 

                if gen0(i+1,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j+1)==1
                    neigh=neigh+1;
                end

                if gen0(i+1,j)==1
                    neigh=neigh+1;
                end

            elseif i==6

                if gen0(i-1,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i,j-1)==1
                    neigh=neigh+1;
                end

                if gen0(i-1,j)==1
                    neigh=neigh+1;
                end


                if gen0(i,:)==1
                    if neigh==2 || neigh==3
                        gen0(i,:)=1;
                    elseif neigh==1 || neigh==0
                        gen0(i,:)=0;
                    end
                end
            end
        end
        disp(gen0);
    end

    if gen0(i,:)==1
        if neigh==2 || neigh==3
            gen0(i,:)=1;
        elseif neigh==1 || neigh==0 || neigh>3
            gen0(i,:)=0;
        end
    end
end
2
Can you show us the loops (all code you have)? It's better to learn from your mistakes than to just copy the right answer.ViG
@ViG added the code. It's all I have, I'm new to programming in general so I'm getting a little frustrated with this problem. Thanks for answering!Daniel Arocha
@ViG been thinking how to make it myself! Check the post, thanksDaniel Arocha

2 Answers

2
votes

Nested loops is a sensible option. However, what you are doing is basically an image filter, something that is already implemented by the function imfilter, so Why not to take advantage of that and simplify your life? What you want to do can be accomplished with:

%Creating the filter that adds up all neighbors
filter=ones(3,3);
filter(2,2)=0;
%Apply the filter to compute the sum of all neighboring elements
onesCount=imfilter(A,filter);
%Creating the rules in arrays that contains result for a given count of ones (+1)
%ones count 0 1 2 3 4 5 6 7 8 9
onesRule = [0 0 1 1 0 0 0 0 0 0];
zeroRule = [0 0 0 1 0 0 0 0 0 0];
%Initializing output matrix
out=zeros(size(A));
%Assigning values to the cells with ones
outForOnes=onesRule(onesCount+1);
out(A==1)=outForOnes(A==1);
%Assigning values to the cells with zeros 
%(if you want you can skip this step initializing out=outForZeros)
outForZeros=zeroRule(onesCount+1);
out(A==0)=outForZeros(A==0);

Otherwise, if you want to keep the nested loops, instead of dealing with the exceptions of index out of bounds, I would suggest to pad A with zeros all around. So if A size is n by m (6 by 6 in this case) you do:

B=zeros(n+2,m+2);
B(2:end-1,2:end-1)=A;
A=B;

And then you loop i and j between 2:n+1 and 2:m+1

1
votes

In my opinion, using two nested loops in this case is a good approach. Retrieving the surrounding values of a matrix element is always tricky, but it can be accomplished with some efforts. Here is the solution I propose you:

A = [
  0 1 0 1 1 0;
  1 0 1 0 0 1;
  1 1 0 1 1 1;
  0 0 1 0 0 0;
  0 1 0 0 0 1;
  1 1 1 0 0 1
];

A_rows = size(A,1);
A_cols = size(A,2);

for i = 1:A_rows
    for j = 1:A_cols
        % Retrieve the current center...
        value = A(i,j);

        % Retrieve the neighboring column and row offsets...
        c = bsxfun(@plus,j,[-1  0  1 -1  1 -1  0  1]);
        r = bsxfun(@plus,i,[-1 -1 -1  0  0  1  1  1]);

        % Filter the invalid positions...
        idx = (c > 0) & (c <= A_cols) & (r > 0) & (r <= A_rows);

        % Transform the valid positions into linear indices...
        idx = (((idx .* c) - 1) .* A_rows) + (idx .* r);
        idx = reshape(idx.',1,numel(idx));

        % Filter the invalid linear indices...
        idx = idx(idx > 0);

        % Find the center neighbors and their sum...
        neighbors = A(idx);
        neighbors_sum = sum(neighbors);

        % Apply the transformation criterions to A...
        if (value == 0)
            if (neighbors_sum == 3)
                A(i,j) = 1;
            end
        else
            if (neighbors_sum <= 1) || (neighbors_sum >= 3)
                A(i,j) = 0;
            end
        end
    end
end

The final output for the given example is:

A =
     0     1     1     0     0     0
     0     0     0     1     0     1
     0     0     1     0     0     0
     0     1     0     0     0     0
     0     0     1     0     0     0
     0     1     1     0     0     0

I just have a few doubts about the whole process you described.

The first one concerns the criterions to apply when the center value is equal to 1. Two of them seem to be contradictory:

-If the neighbor cells of the center value contains in total 3 or more 1's, it converts from 1 to 0.

-And if the neighbor cells contain in total 2 or 3 number 1's, it keeps being 1.

When the neighbors sum is equal to 3... which condition should be applied? The first one or the second one?

The second one concerns the original matrix A. Should it be updated inside the loop? I mean, in the current code, the values of A change when certain conditions are met... but this also means that the conditions are influenced by the outcome of the previous iterations. Maybe your goal is to keep A static while updating a clone of it instead?

Anyway, both issues are easy to deal with and you should be able to adapt my code to your needs without any problem.