Related
I have two vectors:
x = [1 2 3]; y = [4 5]
I need a single array yx that gives me one-to-one combinations of the elements of both vectors. This is the code I have tried so far using of the examples from Stackoverflow.
sets = {y, x};
[y x] = ndgrid(sets{:});
yx = [y x]'
This gives me the result:
yx =
4 5
4 5
4 5
1 1
2 2
3 3
Whereas, I am expecting the following result:
yx =
4 1
4 2
4 3
5 1
5 2
5 3
Please, what am I doing wrong here? Any help/suggestions is greatly appreciated. Thanks!
What you're trying to obtain is a cartesian product of the two vector.
Here's a solution:
>> x = [1 2 3]; y = [4 5];
>> [X,Y] = meshgrid(y,x);
>> result = [X(:) Y(:)]
result =
4 1
4 2
4 3
5 1
5 2
5 3
(this works also in Octave and does not require extra libraries)
Your final cat is wrong. You expect that x and y are column vectors but they are 2x3-matrices. To get a 2-column matrix of all pairs, you need to linearize first:
yx = [y(:) x(:)]
It outputs the data in a different order. If you want the same order, transpose x and y before vectorizing and concatenating.
you are looking for combvec(x, y)
>> x = [1 2 3]
x =
1 2 3
>> y = [4 5]
y =
4 5
>> combvec(x, y)
ans =
1 2 3 1 2 3
4 4 4 5 5 5
Here is a way to do it with no complicated functions.
x = [1 2 3];
y = [4 5];
nx = numel(x);
ny = numel(y);
xy = [reshape(repmat(y,nx,1), 1, [])', repmat(x',ny,1)];
% xy = [4 1
% 4 2
% 4 3
% 5 1
% 5 2
% 5 3
Explanation:
We know that the output will have x repeated for each element in y, named ny.
We know that the output will have each element of y repeated for each element in x, nx
repmat repeats x simply for the second column.
repmat used with reshape to "interweave" y with its repeated self to get the repeated digits in the y vector as the first column.
You could condense the code by not using nx and ny.
xy = [reshape(repmat(y,numel(x),1), 1, [])', repmat(x',numel(y),1)];
I have two arrays:
array1: [0 1 2 3]
array2: [0 1 2 3 4 5 6 7]
array3: [0 1 2 3 4 5]
I want to find combination from each array like 1 element from each array such that the sum >= m eg.3 and sum <=r eg. 6
Example:
array1 array2 array3 elements
1 1 1 (sum is 3)
1 5 0 (sum is 6)
1 6 1 (wrong result sum is greater than 6)
Thanks in advance.
I don't understand how to solve this problem . A pseudocode will be very helpful.
As I have mentioned in my comment; compared to the brute force, in JS by a dynamical programming approach you may get the results much faster, like in total around 10ms for your test case, as follows;
function getCombos(arr,n,m){
function getBinaryMap(d){
return Array(a.length).fill()
.reduce((p,c,i) => p.concat(d >> i & 1),[]);
}
var a = arr.reduce((p,c) => p.concat(c.filter(e => e !== 0 && e <= m)),[]);
t = [0],
r = [];
a.forEach(e => t = t.concat(t.map((f,i) => (f + e >= n && f + e <= m && r.push(getBinaryMap(t.length + i)), f + e))));
return r.map(e => e.reduce((p,c,i) => c ? p.concat(a[i]) : p,[]));;
}
var arrays = [[0, 1, 2, 3],[0, 1, 2, 3, 4, 5, 6, 7],[0, 1, 2, 3, 4, 5]];
result = getCombos(arrays,3,6);
console.log(JSON.stringify(result));
Let there be N=3 sorted arrays A(size = p), B(size = q) and C(size=r).
Choose a number say X and try finding a sum of N=3 numbers x1 + x2 + x3
such that X = x1 + x2 + x3. Finding x1, x2 and x3 can be done using dynamic programming.
Now,
Consider the sequence ABC and use binary search to find x1 in array A, x2 in array B and x3 in array C.
Consider the sequence ACB and use binary search to find x1 in array A, x2 in array C and x3 in array B.
Consider the sequence BAC and use binary search to find x1 in array B, x2 in array A and x3 in array C.
You will find that there are N! number of such sequences.
You will be required to repeat the above process for all X such that [m]<=[X]<=[r].
Total Complexity would be (r - m + 1) * (N!) * ((log p) + (log q) + (log r)).
Total Complexity does not include the dynamic programming part.
I have N points denoted by (xi,yi).
1<=i<=N
I have Q queries of the following form :
Given a rectangle (aligned with x,y axes) defined by the points x1, y1, x2, y2 where (x1, y1) is the lower left corner and (x2, y2) is the upper right corner, find the number of points inside the rectangle. Points on rectangle are considered outside.
Constraints :
1 ≤ N ≤ 100 000
1 ≤ Q ≤ 100 000
0 ≤ xi, yi ≤ 100 000
0 ≤ x1 < x2 ≤ 100 000
0 ≤ y1 < y2 ≤ 100 000
I have thought of following approaches :
Build a 2D segment tree on N*N matrix. A query will be solved in log N time.
But the size of the segment tree built would be >=10^7. Hence memory insufficient.
Keep two arrays(say X and Y), with both array containing all the N points.
X is sorted with respect to x coordinates and Y is sorted with respect to y coordinate. Now given x1,y1,x2,y2 : I can find all points >=x1 && <=x2 from X array in log N time. Similarly, I can find all points >=y1 && <=y2 from Y in log N time. But how to find number of points in given rectangle, I cannot workout out further!
Complexity should be O(NlogN) or O(QlogN)
This problem is called Orthogonal Range Searching:
Given a set of n points in Rd, preprocess them such that reporting or
counting the k points inside a d-dimensional axis-parallel box will be
most efficient.
Your queries are range counting queries (not range reporting queries).
A two-dimensional range tree can be used to answer a range counting query in O(log n) time using O(n log n) storage (see for example Ch.36 of Handbook of Discrete and Computational Geometry 2Ed, 2004)
If your x's and y's are on a grid, and the grid is narrow, see Orthogonal range searching in linear and almost-linear space [Nekrich, 2009] where an O((logn / log logn)2) time data structure is presented.
Create a map<x, y>, populate it with all coordinates, then sort with comparator (sort by key then by value):
return a.first != b.first? a.first < b.first : a.second < b.second;
So that you can have y value sorted as well with a particular x key.
Now you need to traverse within >=x1 && <=x2 incrementally, and apply binary search to find y_min and y_max by passing iterator_start_for_xi and iterator_end_for_xi as start and end index.
Count at xi = iterator_for_xi_y_max - iterator_for_xi_y_min.
You need to find summation of count at xi where x1<=xi<=x2
For example, a map upon sorting would look like this:
2 6
3 4
3 5
3 10
3 12
3 25
5 1
5 5
5 15
6 6
6 20
8 0
Lets say the x1 = 3, x2 = 7, y1 = 3, y2 = 12
2 6
3 4 < y_min for x = 3
3 5 <
3 10 <
3 12 < y_max for x = 3
3 25
5 1
5 5 < y_min and y_max for x = 5
5 15
6 6 < y_min and y_max for x = 6
6 20
8 0
Here is what i want to do:
I have 4 inputs x1, x2, x3, x4
They each have a range of possible values, f.e
x1={1,2}
x2=x3=x4={1,2,3}
These values x1, x2, x3, x4 may be known, but they can also be unknow (input=0). I want to generate a matrix with all possible combinations.
So for example:
the input (0,0,2,3) means, that x1 and x2 are unknown and x3 and x4 are known. Since x1 has 2 possibilities and x2 has 3 possibilities I need 2*3=6 combinations, where x3 and x4 are fixed:
1 1 2 3
1 2 2 3
1 3 2 3
2 1 2 3
2 2 2 3
2 3 2 3
How do i archieve that? Normally i would do a couple nested for loops, but that doenst work, since i dont know which variables are known and which one are not. On the other hand perm() doenst really help either.
You can pre-generate all of the possible combinations of values for [x1 x2 x3 x4] and store it in the variable, for example comb.
From there on:
inputs = [x1 x2 x3 x4]; % Put your inputs in a vector
fixed = ~(inputs == 0); % Logical vector for where inputs is not zero
select = ismember(combs(:,fixed),inputs(fixed),'rows') % find where the values correspond
yourMatrix = combs(select,:); % Get your results
Try this (this should be generalisable):
% This is your input
ranges = {[1, 2], [1, 2, 3], [1, 2, 3], [1, 2, 3]};
input_v = [0, 0, 2, 3];
% initialise a cell to hold vectors to be combined
combine_us = cell(size(ranges));
for ii = 1:length(input_v)
% this tests for 0. If your arrays can contain 0, use NaN instead
if input_v(ii) == 0
combine_us{ii} = ranges{ii};
else
combine_us{ii} = input_v(ii);
end
end
% calculate the numbers of combinations added with every input
n_combinations = [1 cumprod(cellfun(#numel, combine_us))];
% initialize output matrix
out_v = zeros(n_combinations(end), length(input_v));
% set the output values, cycling so that each combination will be obtained
for ii = 1:length(input_v)
for jj = 1:n_combinations(end)
out_v(jj, ii) = combine_us{ii}(mod(ceil(jj / n_combinations(ii)) - 1, length(combine_us{ii} )) + 1);
end
end
I'm assuming your inputs are numeric vectors, rather than cell arrays of numbers. If they are really cell arrays of numbers, you can convert to numeric vectors with x1 = [x1{:}]; etc.
You can proceed as follows:
Build a cell array such that each cell contains either a whole input vector or a specific value thereof, according to s. This is easily done with a for loop, or with arrayfun.
Apply one of these answers to generate all combinations.
Code:
%// Inputs
x1 = [1,2];
x2 = [1,2,3];
x3 = [1,2,3];
x4 = [1,2,3];
s = [0 0 2 3];
%// Step 1
x = {x1 x2 x3 x4};
ind = s~=0;
x(ind) = arrayfun(#(y,t) {y{1}(t)}, x(ind), s(ind));
%// Step 2
n = numel(x);
combs = cell(1,n);
[combs{end:-1:1}] = ndgrid(x{end:-1:1});
combs = cat(n+1, combs{:});
combs = reshape(combs,[],n);
I have a 5 by 3 matrix, e.g the following:
A=[1 1 1; 2 2 2; 3 3 3; 4 4 4; 5 5 5]
I run a for loop:
for i = 1:5
AA = A(i)'*A(i);
end
My question is how to store each of the 5 (3 by 3) AA matrices?
Thanks.
You could pre-allocate enough memory to the AA matrix to hold all the results:
[r,c] = size(A); % get the rows and columns of A (r and c respectively)
AA = zeros(c,c,r); % pre-allocate memory to AA for all 5 products
% (so we have 5 3x3 arrays)
Now do almost the same loop as above BUT realize that A(i) in the above code only returns one element whereas you want the full row. So you want the data from row i but all columns which can be represented as 1:3 or just the colon :
for i=1:r
AA(:,:,i) = A(i,:)' * A(i,:);
end
In the above, A(i,:) is the ith row of A and we are setting all rows and columns in the third dimension (i) of AA to the result of the product.
Assuming, as in Geoff's answer, that you mean A(i,:)'*A(i,:) (to get 5 matrices of size 3x3 in your example), you can do it in one line with bsxfun and permute:
AA = bsxfun(#times, permute(A, [3 2 1]), permute(A, [2 3 1]));
(I'm also assuming that your matrices only contain real numbers, as in your example. If by ' you really mean conjugate transpose, you need to add a conj in the above).