Matlab - arranging numbers - arrays

I have vectors m, x, y & I want m1, x1, y1 as commented below:
% given
m = [-4 -3 -2 2 3 4];
x = [2 5 6 7 9 1];
y = [10 23 34 54 27 32];
% required
% m1 = [2 3 4]; % only +ve value from m
% x1 = [13 14 3]; % adding numbers(in x) corres. to -ve & +ve value in m & putting below 2, 3, 4 respectively
% y1 = [88 50 42]; % adding numbers(in y) corres. to -ve & +ve value in m & putting below 2, 3, 4 respectively
m1 = m(m > 0) % this gives me m1 as required
Any hint for x1, y1 will be very helpful.

Assuming m is built as [vectorNegativeReversed, vectorPositiveOriginal] the solution can be quite straightforward:
p = numel(m)/2;
m1 = m(p+1:end)
x1 = x(p+1:end) + x(p:-1:1)
y1 = y(p+1:end) + y(p:-1:1)

What about some flippy action:
m = [-4 -3 -2 2 3 4];
x = [2 5 6 7 9 1];
y = [10 23 34 54 27 32];
idx = find( (m > 0) );
xdi = find( ~(m > 0) );
m1 = m(idx)
x1 = fliplr( x(xdi) ) + x(idx)
y1 = fliplr( y(xdi) ) + y(idx)
returning:
m1 =
2 3 4
x1 =
13 14 3
y1 =
88 50 42

Related

How many iterations of the while loop must be made in order to locate it?

Im having some trouble trying to find out why the correct answer to this question is 4. Could anyone be kind enough to briefly explain why? Thanks in advanced! Here's the question:
Consider the array a with values as shown:
4, 7, 19, 25, 36, 37, 50, 100, 101, 205, 220, 271, 306, 321
where 4 is a [0] and 321 is a [13] . Suppose that the search method is called with
first = 0 and last = 13 to locate the key 205. How many iterations of the while loop must be made in order to locate it?
My guess is that you have to use a binary search here, as the items are sorted.
Given this array
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]
4, 7, 19, 25, 36, 37, 50, 100, 101, 205, 220, 271, 306, 321
You initialize with:
left and right indexes: l = 0, r = 14 (= length of array)
Then you need these iterations:
m = (l + r) / 2 = (0 + 14) / 2 = 7
[m = 7] = 100 is < 205 ==> l = 7 + 1
m = (l + r) / 2 = (8 + 14) / 2 = 11
[m = 11] = 271 is > 205 ==> r = 11 - 1
m = (l + r) / 2 = (8 + 10) / 2 = 9
[m = 9] = 205 is = 205 ==> result = [9]
= 3 iterations!
However, a slight change to the algorithm can change the number of iterations. If you take r = N-1 instead of N as initial value then you get:
m = (l + r) / 2 = (0 + 13) / 2 = 6 (integer division)
[m = 6] = 50 is < 205 ==> l = 6 + 1
m = (l + r) / 2 = (7 + 13) / 2 = 10
[m = 10] = 220 is > 205 ==> r = 10 - 1
m = (l + r) / 2 = (7 + 9) / 2 = 8
[m = 8] = 101 is < 205 ==> l = 8 + 1
m = (l + r) / 2 = (9 + 9) / 2 = 9
[m = 9] = 205 is = 205 ==> result = [9]
= 4 iterations!
So the result depends on implementation details. Both variants are correct. Take care to choose the appropriate loop condition (I think l < r for the first and l <= r for the second algorithm.
Just go from the last index.
You start with index 13, which the first iteration you go to index 12, on the 4th iteration you are on index 9, which equals to 205.

Vectorize 2d convolution on matlab

I got this Code for computing two dimensional convolution for two given arrays.
[r,c] = size(x);
[m,n] = size(y);
h = rot90(y, 2);
center = floor((size(h)+1)/2);
Rep = zeros(r + m*2-2, c + n*2-2);
return
for x1 = m : m+r-1
for y1 = n : n+r-1
Rep(x1,y1) = x(x1-m+1, y1-n+1);
end
end
B = zeros(r+m-1,n+c-1);
for x1 = 1 : r+m-1
for y1 = 1 : n+c-1
for i = 1 : m
for j = 1 : n
B(x1, y1) = B(x1, y1) + (Rep(x1+i-1, y1+j-1) * h(i, j));
end
end
end
end
How can i vectorize it , so no for loops exist ?
Thanks in advance.
Here's what I came up with:
%// generate test matrices
x = randi(12, 4, 5)
y = [2 2 2;
2 0 2;
2 2 2]
[r,c] = size(x);
%[m,n] = size(y); %// didn't use this
h = rot90(y, 2);
center = floor((size(h)+1)/2);
Rep = zeros(size(x)+size(h)-1); %// create image of zeros big enough to pad x
Rep(center(1):center(1)+r-1, center(2):center(2)+c-1) = x; %// and copy x into the middle
%// all of this can be compressed onto one line, if desired
%// I'm just breaking it out into steps for clarity
CRep = im2col(Rep, size(h), 'sliding'); %// 'sliding' is the default, but just to be explicit
k = h(:); %// turn h into a column vector
BRow = bsxfun(#times, CRep, k); %// multiply k times each column of CRep
B = reshape(sum(BRow), r, c) %// take the sum of each column and reshape to match x
T = conv2(Rep, h, 'valid') %// take the convolution using conv2 to check
assert(isequal(B, T), 'Result did not match conv2.');
Here are the results of a sample run:
x =
11 12 11 2 8
5 9 2 3 2
7 9 3 4 8
7 10 8 5 4
y =
2 2 2
2 0 2
2 2 2
B =
52 76 56 52 14
96 120 106 80 50
80 102 100 70 36
52 68 62 54 34
T =
52 76 56 52 14
96 120 106 80 50
80 102 100 70 36
52 68 62 54 34

Karatsuba Algorithm: splitting strings

I am trying to implement the Karatsuba algorithm in C.
I work with char strings (which are digits in a certain base), and although I think I have understood most of the Karatsuba algorithm, I do not get where I should split the strings to multiply.
For example, where should I cut 123 * 123, and where should I cut 123 * 12?
I can't get to a solution that works with both these calculations.
I tried to cut it in half and flooring the result when the number if odd, but it did not work, and ceiling does not work too.
Any clue?
Let a, b, c, and d be the parts of the strings.
Let's try with 123 * 12
First try (a = 1, b = 23, c = 1, d = 2) (fail)
z0 = a * c = 1
z1 = b * d = 46
z2 = (a + b) * (c + d) - z0 - z1 = 24 * 3 - 1 - 46 = 72 - 1 - 46 = 25
z0_padded = 100
z2_padded = 250
z0_padded + z1 + z2_padded = 100 + 46 + 250 = 396 != 123 * 12
Second try (a = 12, b = 3, c = 12, d = 0) (fail)
z0 = 144
z1 = 0
z2 = 15 * 12 - z1 - z0 = 180 - 144 = 36
z0_padded = 14400
z2_padded = 360
z0_padded + z1 + z2_padded = 14760 != 1476
Third try (a = 12, b = 3, c = 0, d = 12) (success)
z0 = 0
z1 = 36
z2 = 15 * 12 - z0 - z1 = 144
z0_padded = 0
z2_padded = 1440
z0_padded + z1 + z2_padded = 1476 == 1476
Let's try with 123 * 123
First try (a = 1, b = 23, c = 1, d = 23) (fail)
z0 = 1
z1 = 23 * 23 = 529
z2 = 24 * 24 - z0 - z1 = 46
z0_padded = 100
z2_padded = 460
z0_padded + z1 + z2_padded = 561 != 15129
Second try (a = 12, b = 3, c = 12, d = 3) (success)
z0 = 12 * 12 = 144
z1 = 3 * 3 = 9
z2 = 15 * 15 - z0 - z1 = 72
z0_padded = 14400
z2_padded = 720
z0_padded + z1 + z2_padded = 15129 == 15129
Third try (a = 12, b = 3, c = 1, d = 23) (fail)
z0 = 12
z1 = 3 * 23 = 69
z2 = 15 * 24 - z0 - z1 = 279
z0_padded = 1200
z2_padded = 2799
z0_padded + z1 = z2_padded = 4068 != 15129
Here, I do not get where I messed this up. Note that my padding method adds n zeroes at the end of a number where n = m * 2 and m equals the size of the longest string divided by two.
EDIT
Now that I have understood that b and d must be of the same length, it works almost everytime, but there are still exceptions: for example 1234*12
a = 123
b = 4
c = 1
d = 2
z0 = 123
z1 = 8
z2 = 127 * 3 - 123 - 8 = 250
z0_padded = 1230000
z2_padded = 25000
z0_padded + z1 + z2_padded = 1255008 != 14808
Here, assuming I split the strings correctly, the problem is the padding, but I do not get how I should pad. I read on Wikipedia that I should pad depending on the size of the biggest string (see a few lines up), there should be another solution.
The Karatsuba algorithm is a nice way to perform multiplications.
If you want it to work, b and d must be of the same length.
Here are two possibilities to compute 123x12 :
a= 1;b=23;c=0;d=12;
a=12;b= 3;c=1;d= 2;
Let's explain how it works for the second case :
123=12×10+3
12= 1×10+2
123×12=(12×10+3)×(1×10+2)
123×12=12×1×100+ (12×2+3×1)×10+3×2
123×12=12×1×100+((12+3)×(1+2)-12×1-3×2)×10+3×2
Let's explain how it works for the first case :
123=1×100+23
12=0×100+12
123×12=(1×100+23)×(0×100+12)
123×12=1×0×10000+ (1×12+23×0)×100+23×12
123×12=1×0×10000+((1+23)×(0+12)-1×0-23×12)×100+23×12
It also works with 10^k, 2^k or n instead of 10 or 100.

How to assign values to image in matlab

I have 5 columns x, y, r, g, b with values of line number, column number, red, green and blue. The lines of this n by 5 matrix are not in a particular order, however they are consistent with image(x,y) and the r,g,b.
I would like to do something like I=uint8(zeros(480,640,3) and just change those rgb values based on the n by 5 mat.
Something along the lines of I(mat(:,1), mat(:,2), 1)=mat(:,3) for red etc
The following uses the concept of linear indexing and the versatile bsxfun function:
m = 640; %// number of rows
n = 480; %// number of columns
I = zeros(m, n, 3, 'uint8'); %// initiallize directly as uint8
I(bsxfun(#plus, x(:)+(y(:)-1)*m, (0:2)*m*n)) = [r(:) g(:) b(:)]; %// fill values
Small example: for
m = 2;
n = 3;
x = [1 2 1];
y = [1 1 2];
r = [ 1 2 3];
g = [11 12 13];
b = [21 22 23];
the code produces
I(:,:,1) =
1 3 0
2 0 0
I(:,:,2) =
11 13 0
12 0 0
I(:,:,3) =
21 23 0
22 0 0
An alternative:
INDr = sub2ind([480, 640, 3], mat(:, 1), mat(:,2), ones([numel(mat(:,3)), 1]));
INDg = sub2ind([480, 640, 3], mat(:, 1), mat(:,2), 2*ones([numel(mat(:,3)), 1]));
INDb = sub2ind([480, 640, 3], mat(:, 1), mat(:,2), 3*ones([numel(mat(:,3)), 1]));
I=uint8(zeros(480,640, 3));
I(INDr)=mat(:,3);
I(INDg)=mat(:,4);
I(INDb)=mat(:,5);
Note that in Matlab, the convention between axes is different between images and arrays.

Deleting elements from array in Matlab

Given,
a = [2 4 6 8 10 0 7 18 9 0 8 2 0 5];
b = [1 3 0 5 70 8 6 87 1 9 7 8 0 2];
I am trying to delete elements (in both 'a' & 'b') that corresponds
to '0' or less than '0' in either 'a' or 'b' i.e., I want
% a = [2 4 8 10 7 18 9 8 2 5];
% b = [1 3 5 70 6 87 1 7 8 2];
I am trying like this -
n = length(b);
a1 = [];
b1 = [];
for k = 1:n
if a(n) <= 0 || b(n) <= 0
a1 = [a; a(a > 0)] % eliminates 0 from a
b1 = [b; b(b > 0)] % eliminates 0 from b
end
end
Any help will be very helpful.
Use find:
a = [2 4 6 8 10 0 7 18 9 0 8 2 0 5];
b = [1 3 0 5 70 8 6 87 1 9 7 8 0 2];
A = a( find( a > 0 & b > 0 ) );
B = b( find( a > 0 & b > 0 ) );
or even faster:
C = a( a > 0 & b > 0 );
D = b( a > 0 & b > 0 );
returns:
C =
2 4 8 10 7 18 9 8 2 5
D =
1 3 5 70 6 87 1 7 8 2
If you can be sure, that there are no values below zero you could also use:
E = a( logical(a) & logical(b) );
F = b( logical(a) & logical(b) );
which is a little faster, but containing also negative values.
The efficient and compact way to do this is to first create the relevant index, that prevents double calculation:
idx = a>0 & b>0
a = a(idx);
b = b(idx);

Resources