Problem with numbers - numbers

I am given a number N, and i must add some numbers from the array V so that they wil be equal. V is consisting of numbers that are all powers of 3:
N = 17
S = 0
V = 1 3 9 27 81 ..
I should add numbers from V to N and S in order to make them equal. The solution to the example above is :
17 + 1 + 9 = 27, 27, 1 and 9 are taken from V, a number from V can be taken only once, and when taken it's removed from V.
I tried sorting V and then adding the biggest numbers from V to S until S has reached N, but it fails on some tests when it's like:
N = 7
S = 0
V = 1 3 9 27
So the solution will be:
7 + 3 = 9 + 1
In examples like this i need to add numbers both to N and S, and also select them so they become equal.
Any idea of solving this ? Thanks.

Write N in base 3: 17 = 2*1 + 2*3 + 1*9
Find the first power of 3 with coefficient 2, in this case 1.
Add this power of 3: 17 + 1
Repeat until all coefficients are 0 or 1.
17 = 2*1 + 2*3 + 1*9
17 + 1 = 2*9
17 + 1 + 9 = 27
7 = 1*1 + 2*3
7 + 3 = 1*1 + 1*9

Related

Vectorising a Matlab code to pick specific indices of a matrix

I have a matrix A in Matlab of dimension Nx(N-1), e.g.
N=5;
A=[1 2 3 4;
5 6 7 8;
9 10 11 12;
13 14 15 16;
17 18 19 20];
I want to rearrange the elements of A in a certain way. Specifically I want to create a matrix B of dimension (N-1)xN such that:
for i=1,...,N,
B(:,i) collects
1) the first i-1 elements of the i-1th column of A and
2) the last N-i elements of the ith column of A.
Notice that for i=1 the i-1th column of A does not exist and therefore 1) is skipped; similarly, for i=N theith column of A does not exist and therefore 2) is skipped.
In the example above
B=[5 1 2 3 4
9 10 6 7 8
13 14 15 11 12
17 18 19 20 16];
This code does what I want. I am asking your help to vectorise it in an efficient way.
B=zeros(N-1,N);
for i=1:N
if i>1 && i<N
step1=A(1:i-1,i-1);
step2=A(i+1:N,i);
B(:,i)=[step1;step2];
elseif i==1
B(:,i)=A(i+1:N,i);
elseif i==N
B(:,i)=A(1:i-1,i-1);
end
end
Extract the lower and upper triangular matrices of A. Then reassemble them with a "diagonal shift":
u = triu(A);
l = tril(A,-1);
B = padarray(u(1:end-1,:),[0 1],'pre') + padarray(l(2:end,:),[0 1],'post');
Another valid approach using logical indexing combined with tril and triu:
B = zeros(size(A'));
B(tril(true(size(B)))) = A(tril(true(size(A)), -1));
B(triu(true(size(B)), 1)) = A(triu(true(size(A))));
Result:
>> B
B =
5 1 2 3 4
9 10 6 7 8
13 14 15 11 12
17 18 19 20 16

How to efficiently reshape one column matrix to many specific length columns by moving specific interval

The input is an N-by-1 matrix. I need to reshape it to L-by-M matrix. The following is an example.
Input:
b =
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Set length = 18, Output:
X =
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9
8 9 10
9 10 11
10 11 12
11 12 13
12 13 14
13 14 15
14 15 16
15 16 17
16 17 18
17 18 19
18 19 20
Because I have a very big matrix, using a loop to reshape is very inefficient. How can I improve the reshape speed?
Your example output matrix X is the perfect matrix to index a vector of length N to get what you want. It's also very easy to create using bsxfun:
N = 20;
b = rand(N,1);
M = 3; %// number of columns
L = N-M; %// Note that N-M is an upper limit for L!
idx = bsxfun(#plus, (0:L)', 1:M)
X = b(idx)
That's exactly what im2col (from the Image Processing Toolbox) does:
b = (1:20).'; %'// example data
L = 18; % // desired length of sliding blocks
x = im2col(b, [L 1]); % // result
I'd use horzcat. For example:
function X = reshaper(b,len)
diff = length(b) - len + 1;
X = b(1:len);
for i=2:diff
X = horzcat(X,b(i:len+(i-1)));
end
You could probably remove the for loop with some further thought.

Setting a specified number of rows in each column and block of elements to zero

Is there any easy way to set a specified number of rows k in nth column to zero ? Its a bit tricky question to explain so I guess its best to look at the example.
Lets say I have:
A =
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
16 17 18
I wish to set rows, like this: [row1 col1] = 0; [row2 col1] = 0, and then [row3 col2]= 0; row4 col2]= 0 and so on, so my output is:
k = 2
B =
0 2 3
0 5 6
7 0 9
10 0 12
13 14 0
16 17 0
Do you have any suggestions/solutions how this could be solved with a for loop, or maybe there is another way?
and how this solution could be extend further to something like this:
A =
1 2 3 1 2 3
4 5 6 4 5 6
7 8 9 7 8 9
10 11 12 10 11 12
13 14 15 13 14 15
16 17 18 16 17 18
B =
0 0 3 1 2 3
0 0 6 4 5 6
7 8 0 0 8 9
10 11 0 0 3 1
13 14 15 13 0 0
16 17 18 16 0 0
One approach -
k = 2;
row1 = 1:size(A,1)
col1 = ceil([1:size(A,1)]./k)
A(sub2ind(size(A),row1,col1))=0
For the edited question, use kron like this -
k = 2;
a1 = eye(size(A)./k);
b1 = ones(k,k);
A(logical(kron(a1,b1)))=0
That isn't a problem. We can figure out exactly which rows and columns you want to set to 0 based on this value k, then use sub2ind to get a single index to access into your matrix. This will be in column-major format. Then you can use this and set all of your values to zero. Here is an example. We need to know the width and height of your matrix first before we do this:
rows = [row1 row2 row3];
cols = [col1 col2 col3];
%// Get column major indices
ind = sub2ind([height width], rows, cols);
%// Set the values in this matrix to 0.
B(ind) = 0;
Now with your example, we need to access all of the rows. However, for the columns, we need to access k elements in each column and ensuring they don't overlap. As such, we can do it like so:
k = 2;
B = reshape(1:18, 6, 3).';
rows = 1 : 6;
cols = ceil(rows / k);
ind = sub2ind([rows cols], rows, cols);
B(ind) = 0;
You would thus get:
B =
0 2 3
0 5 6
7 0 9
10 0 12
13 14 0
16 17 0
The following code is executable in matlab, and does what you want:
% Create A-matrix
A = reshape(1:18,6,3)
% Set specified datapoints to zero
A([1,2],[1,1]) = 0
Alternatively, you can set each element separately
A(1,1) = 0
A(1,2) = 0
And the most general way, with k and n:
A([1:k],n) = 0
For first question:
A(mod(0:numel(A)-1, size(A,1)+k) < k) = 0;
For second question, including first question as a particular case:
c = repmat({ones(k,size(B,2)/size(B,1)*k)}, size(B,1)/k, 1);
B = B.*~blkdiag(c{:})

subset matrix using find function in Matlab

I made a matrix in Matlab, say,
A = magic(5);
A =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
Now I found the indices I want using the find function as:
ind = find(A(:,5)>3 & A(:,4)>= 8);
ind =
1
2
3
Now if I want to get a subset of matrix A for those indices using B = A(ind) function, I only get the first column of the matrix:
B = A(ind)
B =
17
23
4
How can I get all the columns as subset??
Oops ... I got it
B = A(ind,:);

MATLAB - Summing values after reading their position from another matrix

Suppose I have an array that consists of some elements (A) and I want to take the nth element and sum it with a number of elements that follow it, and I have a matrix that gives me the position of each of the elements from which I should start summing (B).
For example I have
A = [2 3 4 5 6 3 5 7 3 7 3 7 4 7 3 6 2 6 3 8 4 8 4 8 5 8 3]
And I have
B = [8 12 15]
So I would want to sum the value at position B(1,1) which is 8, therefore A(1,8) with the next 4 elements in the matrix
C(1,1) = 7 + 3 + 7 + 3
C(1,2) = 7 + 4 + 7 + 3
C(1,3) = 3 + 6 + 2 + 6
It's always a big fun to use bsxfun:
idx = bsxfun( #plus, B, (0:3)' ); %//' indices of A to be summed together
C = sum( A(idx), 1 );
What I undersdtand from you question is that you want to calculate a matrix C, you only shown an example for calculating C(1,1). C(1,2) will be like,
C(1,2) = 7 + 4 + 7 + 3 + 6 + 2 + 6 + 3 + 8 + 4 + 8 + 4 + 8 + 5 + 8 + 3 = 86
If I'm right my answer is like this
for i = 1:n
C(i) = 0;
for j = B(i):m
C(i) += A(j);
end
end
where
n = B's length (2 in your example)
m = 4 (because you want to add next 4 elements in the matrix)