Let me describe my problem with an example. Suppose we have matrix A:
A =
1 0 1
1 1 1
0 1 1
and matrix B:
B =
1 1
1 1
How do i write function C = func(A, B) to check if B exists in A or not?
If it exists in A, the function returns C = [0 0 0; 0 1 1; 0 1 1], and if it does not, the function returns C = [0 0 0; 0 0 0; 0 0 0];.
Edit:
It should be mentioned that if A is m-by-n, and B is p-by-q, then m > p and p > q always.
Thanks in advance.
The most efficient requires the signal processing toolbox. Then you can simply use xcorr2(). Following your example, the following should work:
C = xcorr2 (A, B);
[Row, Col] = find (C == max (C(:)));
%% these are not the coordinates for the center of the best match, you will
%% have to find where those really are
%% The best way to understand this is to strip the "padding"
row_shift = (size (B, 1) - 1)/2;
col_shift = (size (B, 2) - 1)/2;
C = C(1+row_shift:end-row_shift, 1+col_shift:end-col_shift)
[Row, Col] = find (C == max (C(:)));
if (B == A(Row-row_shift:Row+row_shift, Col-col_shift:Col+col_shift))
disp ("B shows up in A");
endif
The code above looks a bit convoluted because I'm trying to cover inputs of any size (still only odd sized) but should work.
If you don't have this toolbox, I think you can use the Octave code for it which should require only small adjustments. Basically, the only three lines that matter follow (note that the code is under GPL):
[ma,na] = size(a);
[mb,nb] = size(b);
c = conv2 (a, conj (b (mb:-1:1, nb:-1:1)));
In Octave, if you are using at least the signal package 1.2.0, xcorr2 can also take an extra option "coeff" which calculates the normalized cross correlation. This will have a value of 1 when the match is perfect, so you can simplify this with:
C = xcorr2 (A, B, "coeff");
if (any (C(:) == 1)
display ("B shows up in A");
endif
I would do a loop to check resized sub-matrix of A. My code stops after B is found once but it could be updated to count the number of found occurrences.
A = [1 0 1; 1 1 1; 0 1 1; 0 0 0];
B = [1 1; 1 1];
[m n] = size(A);
[p q] = size(B);
found = 0;
x = 0;
while ~found && (x+p-1 < m)
y = 0;
x = x + 1;
while ~found && (y+q-1 < n)
y = y + 1;
A(x:x+p-1,y:y+q-1)
found = isequal(A(x:x+p-1,y:y+q-1),B);
end
end
fprintf('Found Matrix B in A(%d:%d, %d:%d)\n',x,x+p-1,y,y+q-1);
Maybe there is some vectored way, but this is a straight forward function which just slides across A and checks for B:
function ret=searchmat(A,B)
ret=zeros(size(A));
for k=0:size(A,1)-size(B,1)
for l=0:size(A,2)-size(B,2)
if isequal(A(1+k:size(B,1)+k,1+l:size(B,2)+l),B)
ret(1+k:size(B,1)+k,1+l:size(B,2)+l)=1; % or B as you wish
end
end
end
end
If B is discovered more than once, it's also marked with ones. If you want to quit after the first match, you can just put in a return statement in the if clause.
Related
I am trying to get M. To do this, it is necessary for Matlab to relate column 1 of A to column 1 of π΅^πand build a matrix M with 1 and 0 depending on whether in position π΄[π,π] and π΅^π[π,π] are equal to 1
A = [1 0 1; 0 1 1; 0 0 1 ];
B = [0 0 1 ; 0 1 0; 1 1 1];
for i = 1:3
for j =1:3
if A(i,j) == BT(i,j) && A(i,j)==1;
Z(i,j) = 1
end
end
end
When you use "if A(i,j) == BT(i,j) && A(i,j)==;" you are comparing individual elements. Instead you want to be comparing columns:
A(:, i) and BT(:, j).
Precisely, you want
for i = 1:3
for j = 1:3
M(i,j) = any( A(:,i) & BT(:,j) );
end
end
OR
You are comparing the columns of BT and the columns of A.
That is to say, the rows of B and the columns of A. You want to see if there are any occasions when both of the elements are 1. Thus you can compare the products of the terms in the rows of B and columns of A.
i.e. M = logical(B * A) should also give you the desired output.
NOTE that the data in B are different in your image examples and in your code.
I am sending a matrix to my function modifikuj, where I want to replace the elements of the matrix with:
1 if element is a prime number
0 if element is a composite number
0.5 if element is 1
I dont understand why it is not working. I just started with MATLAB, and I created this function:
function B = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j))
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
With
A = [1,2;3,4];
D = modifikuj(A);
D should be:
D=[0.5, 1; 1 0];
In MATLAB you'll find you can often avoid loops, and there's plenty of built in functions to ease your path. Unless this is a coding exercise where you have to use a prescribed method, I'd do the following one-liner to get your desired result:
D = isprime( A ) + 0.5*( A == 1 );
This relies on two simple tests:
isprime( A ) % 1 if prime, 0 if not prime
A == 1 % 1 if == 1, 0 otherwise
Multiplying the 2nd test by 0.5 gives your desired condition for when the value is 1, since it will also return 0 for the isprime test.
You are not returning anything from the function. The return value is supposed to be 'B' according to your code but this is not set. Change it to A.
You are looping k until A(i,j) which is always divisible by itself, loop to A(i,j)-1
With the code below I get [0.5,1;1,0].
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
prost=1;
if (A(i,j) == 1)
A(i,j) = 0.5;
else
for k = 2:(A(i,j)-1)
if(mod(A(i,j),k) == 0)
prost=0;
end
end
if(prost==1)
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
In addition to #EuanSmith's answer. You can also use the in built matlab function in order to determine if a number is prime or not.
The following code will give you the desired output:
A = [1,2;3,4];
A(A==1) = 0.5; %replace 1 number with 0.5
A(isprime(A)) = 1; %replace prime number with 1
A(~ismember(A,[0.5,1])) = 0; %replace composite number with 0
I've made the assumption that the matrice contains only integer.
If you only want to learn, you can also preserve the for loop with some improvement since the function mod can take more than 1 divisor as input:
function A = modifikuj(A)
[n,m] = size(A);
for i = 1:n
for j = 1:m
k = A(i,j);
if (k == 1)
A(i,j) = 0.5;
else
if all(mod(k,2:k-1)) %check each modulo at the same time.
A(i,j)=1;
else
A(i,j)=0;
end
end
end
end
And you can still improve the prime detection:
2 is the only even number to test.
number bigger than A(i,j)/2 are useless
so instead of all(mod(k,2:k-1)) you can use all(mod(k,[2,3:2:k/2]))
Note also that the function isprime is a way more efficient primality test since it use the probabilistic Miller-Rabin algorithme.
I am trying to solve this problem:
Write a function called cancel_middle that takes A, an n-by-m
matrix, as an input where both n and m are odd numbers and k, a positive
odd integer that is smaller than both m and n (the function does not have to
check the input). The function returns the input matrix with its center k-by-k
matrix zeroed out.
Check out the following run:
>> cancel_middle(ones(5),3)
ans =
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
My code works only when k=3. How can I generalize it for all odd values of k? Here's what I have so far:
function test(n,m,k)
A = ones(n,m);
B = zeros(k);
A((end+1)/2,(end+1)/2)=B((end+1)/2,(end+1)/2);
A(((end+1)/2)-1,((end+1)/2)-1)= B(1,1);
A(((end+1)/2)-1,((end+1)/2))= B(1,2);
A(((end+1)/2)-1,((end+1)/2)+1)= B(1,3);
A(((end+1)/2),((end+1)/2)-1)= B(2,1);
A(((end+1)/2),((end+1)/2)+1)= B(2,3);
A(((end+1)/2)+1,((end+1)/2)-1)= B(3,1);
A(((end+1)/2)+1,((end+1)/2))= B(3,2);
A((end+1)/2+1,(end+1)/2+1)=B(3,3)
end
You can simplify your code. Please have a look at
Matrix Indexing in MATLAB. "one or both of the row and column subscripts can be vectors", i.e. you can define a submatrix. Then you simply need to do the indexing correct: as you have odd numbers just subtract m-k and n-k and you have the number of elements left from your old matrix A. If you divide it by 2 you get the padding on the left/right, top/bottom. And another +1/-1 because of Matlab indexing.
% Generate test data
n = 13;
m = 11;
A = reshape( 1:m*n, n, m )
k = 3;
% Do the calculations
start_row = (n-k)/2 + 1
start_col = (m-k)/2 + 1
A( start_row:start_row+k-1, start_col:start_col+k-1 ) = zeros( k )
function b = cancel_middle(a,k)
[n,m] = size(a);
start_row = (n-k)/2 + 1;
start_column = (m-k)/2 + 1;
end_row = (n-k)/2 + k;
end_column = (m-k)/2 + k;
a(start_row:end_row,start_column:end_column) = 0;
b = a;
end
I have made a function in an m file called cancel_middle and it basically converts the central k by k matrix as a zero matrix with the same dimensions i.e. k by k.
the rest of the matrix remains the same. It is a general function and you'll need to give 2 inputs i.e the matrix you want to convert and the order of submatrix, which is k.
I am looking for a simple way to get all combinations of an binary matrix. I tried already the function perms() but did not get a proper result.
I have for example an matrix N x N filled up with 1 and -1. With N=2 there would be 2^4 possible combinations of 1 and -1 like
(1 1) (1 1) (-1 -1)
M(1) = (1 1) , M(2) = (1 -1) , M(3) = ( 1 1) and so on...
When I use perms() I don't get for example the first matrix.
How can I fix that?
You can represent all numbers between 0 and 2^(N^2)-1 as binary numbers, and then reshape:
N = 2;
v = (1:2^(N^2))-1;
A = dec2bin(v)' - '0'; %'// Or use: decimalToBinaryVector(v)';
A(A==0) = -1;
A = reshape(A,N,N,2^(N^2));
A simple hack is as follows:
v = [1 -1 1 -1];
P = perms(v);
for ii = 1:size(P,1)
A = reshape(P(ii,:),2,2)
end
which results in:
A =
-1 -1
1 1
...
Still there are some identical matrices in the result which should be removed.
I think that I found an solution to my problem
L = 2;
N = L^2;
v = cell(N,1);
for k = 1:N
v{k} = linspace(-1,1,2);
end
ne=numel(v);
x=cell(ne,1);
[x{1:ne,1}]=ndgrid(v{end:-1:1});
p=reshape(cat(ne+1,x{:}),[],ne);
F = cell(length(p),1);
for k=1:length(p)
F{k} = reshape(p(k,:),L,L);
end
If I have a matrix and I want to apply a function to each row of the matrix. This function has three possible outputs, either x = 0, x = 1, or x > 0. There's a couple things I'm running into trouble with...
1) The cases that output x = 1 or x > 0 are different and I'm not sure how to differentiate between the two when writing my script.
2) My function isn't counting correctly? I think this might be a problem with how I have my loop set up?
This is what I've come up with. Logically, I feel like this should work (except for the hiccup w/ the first problem I've stated)
[m n] = size(matrix);
a = 0; b = 0; c = 0;
for i = 1 : m
x(i) = function(matrix(m,:));
if x > 0
a = a + 1;
end
if x == 0
b = b + 1;
end
if x == 1
c = c + 1;
end
end
First you probably have an error in line 4. It probably should be i instead of m.
x(i) = function(matrix(i,:));
You can calculate a, b and c out of the loop:
a = sum(x>0);
b = sum(x==0);
c = sum(x==1);
If you want to distinguish x==1 and x>0 then may be with sum(xor(x==1,x>0)).
Also you may have problem with precision error when comparing double values with 0 and 1.