How to check if any variable in one array is in another - arrays

I'm developing a program with MatLab that calculates powers of numbers, adds them together, and then sees if any of the first set of numbers (numbers to powers) equals any of the added numbers to powers. I'm trying to check this for each value in the first array, however, I am getting an output like this:
m =
1
128
2187
16384
78125
279936
823543
2097152
4782969
10000000
for each m value, which is just the result of a simple for loop of the array. So when I go to check if m is in the array, it checks is [1, 128,2187,16384,78125...] in the array, and the answer is no. How can I get it to evaluate each individual entry, like this:
Array n is [1,128,2187,16384]
for m = n
m = 1
Is m in array? No
m = 128
Is m in array? No
m = 2187
Is m in array? Yes
m = 16384
Is m in array? No
end
My code is below:
C = [];
D = [];
E = [];
F = [];
numbers1 = [];
numbers2 = [];
numbers = 10;
powers = 10;
for i = 1:numbers
for j = 3:powers
C = [C;i^j];
end
C = transpose(C);
D = [D;C];
C = [];
end
[~,b] = unique(D(:,1)); % indices to unique values in first column of D
D(b,:); % values at these rows
for i = D
for a = D
E = [E;i+a];
end
E = transpose(E);
F = [F;E];
E = [];
end
[~,b] = unique(F(:,1)); % indices to unique values in first column of F
F(b,:); % values at these rows
for m = D % this is the for loop mentioned above
m
end

Example vectors:
>> m = [1 3 5 9];
n = [5 2 1 4 8];
To check if each element of vector m is in n, use ismember:
>>ismember(m,n)
ans =
1 0 1 0
To get the values, not the indices: use logical indexing on m:
>> m(ismember(m,n))
ans =
1 5
or directly use intersect:
>> intersect(m,n)
ans =
1 5

Related

Finding number(s) that is(are) repeated consecutively most often

Given this array for example:
a = [1 2 2 2 1 3 2 1 4 4 4 5 1]
I want to find a way to check which numbers are repeated consecutively most often. In this example, the output should be [2 4] since both 2 and 4 are repeated three times consecutively.
Another example:
a = [1 1 2 3 1 1 5]
This should return [1 1] because there are separate instances of 1 being repeated twice.
This is my simple code. I know there is a better way to do this:
function val=longrun(a)
b = a(:)';
b = [b, max(b)+1];
val = [];
sum = 1;
max_occ = 0;
for i = 1:max(size(b))
q = b(i);
for j = i:size(b,2)
if (q == b(j))
sum = sum + 1;
else
if (sum > max_occ)
max_occ = sum;
val = [];
val = [val, q];
elseif (max_occ == sum)
val = [val, q];
end
sum = 1;
break;
end
end
end
if (size(a,2) == 1)
val = val'
end
end
Here's a vectorized way:
a = [1 2 2 2 1 3 2 1 4 4 4 5 1]; % input data
t = cumsum([true logical(diff(a))]); % assign a label to each run of equal values
[~, n, z] = mode(t); % maximum run length and corresponding labels
result = a(ismember(t,z{1})); % build result with repeated values
result = result(1:n:end); % remove repetitions
One solution could be:
%Dummy data
a = [1 2 2 2 1 3 2 1 4 4 4 5 5]
%Preallocation
x = ones(1,numel(a));
%Loop
for ii = 2:numel(a)
if a(ii-1) == a(ii)
x(ii) = x(ii-1)+1;
end
end
%Get the result
a(find(x==max(x)))
With a simple for loop.
The goal here is to increase the value of x if the previous value in the vector a is identical.
Or you could also vectorized the process:
x = a(find(a-circshift(a,1,2)==0)); %compare a with a + a shift of 1 and get only the repeated element.
u = unique(x); %get the unique value of x
h = histc(x,u);
res = u(h==max(h)) %get the result

Return all unique permutations of possibly-repeating array elements

Let's say I have an array of length N with M different object (M < N) so that some of these objects repeat N_i ... N_M times. I'd like to find all possible unique dispositions (like, arrangements) of the elements of such arrays without computing the entire list of permutations beforehand (both for time and memory constraints).
Of course, the naive solution would be to use perms to generate all possible permutations, and then select the unique ones:
A = [1, 1, 2];
all_perms = perms(A)
% all_perms =
% 2 1 1
% 2 1 1
% 1 2 1
% 1 1 2
% 1 2 1
% 1 1 2
unique_perms = unique(all_perms, 'rows')
% unique_perms =
% 1 1 2
% 1 2 1
% 2 1 1
but this will generate all N! permutations, instead of just the N! / (N_1! * N_2! * ... * N_M!). For N = 3, this doesn't affect much neither the memory consumption nor the timing, but as N increases and the number of unique elements decreases, the difference can be huge. So:
Is there a (hopefully built-in) way to list all the unique permutations of an array containing non distinct objects, without intermediately keeping all permutations?
Below is code suggested in 2014 by Bruno Luong for this problem:
function p = uperm(a)
[u, ~, J] = unique(a);
p = u(up(J, length(a)));
end % uperm
function p = up(J, n)
ktab = histc(J,1:max(J));
l = n;
p = zeros(1, n);
s = 1;
for i=1:length(ktab)
k = ktab(i);
c = nchoosek(1:l, k);
m = size(c,1);
[t, ~] = find(~p.');
t = reshape(t, [], s);
c = t(c,:)';
s = s*m;
r = repmat((1:s)',[1 k]);
q = accumarray([r(:) c(:)], i, [s n]);
p = repmat(p, [m 1]) + q;
l = l - k;
end
end
The above can be further improved by replacing nchoosek with one of Jan Simon's functions.

Find unique elements of multiple arrays

Let say I have 3 MATs
X = [ 1 3 9 10 ];
Y = [ 1 9 11 20];
Z = [ 1 3 9 11 ];
Now I would like to find the values that appear only once, and to what array they belong to
I generalized EBH's answer to cover flexible number of arrays, arrays with different sizes and multidimensional arrays. This method also can only deal with integer-valued arrays:
function [uniq, id] = uniQ(varargin)
combo = [];
idx = [];
for ii = 1:nargin
combo = [combo; varargin{ii}(:)]; % merge the arrays
idx = [idx; ii*ones(numel(varargin{ii}), 1)];
end
counts = histcounts(combo, min(combo):max(combo)+1);
ids = find(counts == 1); % finding index of unique elements in combo
uniq = min(combo) - 1 + ids(:); % constructing array of unique elements in 'counts'
id = zeros(size(uniq));
for ii = 1:numel(uniq)
ids = find(combo == uniq(ii), 1); % finding index of unique elements in 'combo'
id(ii) = idx(ids); % assigning the corresponding index
end
And this is how it works:
[uniq, id] = uniQ([9, 4], 15, randi(12,3,3), magic(3))
uniq =
1
7
11
12
15
id =
4
4
3
3
2
If you are only dealing with integers and your vectors are equally sized (all with the same number of elements), you can use histcounts for a quick search for unique elements:
X = [1 -3 9 10];
Y = [1 9 11 20];
Z = [1 3 9 11];
XYZ = [X(:) Y(:) Z(:)]; % one matrix with all vectors as columns
counts = histcounts(XYZ,min(XYZ(:)):max(XYZ(:))+1);
R = min(XYZ(:)):max(XYZ(:)); % range of the data
unkelem = R(counts==1);
and then locate them using a loop with find:
pos = zeros(size(unkelem));
counter = 1;
for k = unkelem
[~,pos(counter)] = find(XYZ==k);
counter = counter+1;
end
result = [unkelem;pos]
and you get:
result =
-3 3 10 20
1 3 1 2
so -3 3 10 20 are unique, and they appear at the 1 3 1 2 vectors, respectively.

MATLAB: ceate a x b matrix (or 2D array) from 2 1Darrays, and populate each cell from another array

I am using MATLAB.
So I have 3 arrays; say a,b,c. a and b represent distances, and c represents a variable with a specific value at the point (a,b).
I have been trying to create a matrix which comprises of (b x a) cells, and the populate it with the values of c, in order to then image, heatmap it etc.
However the issue I have having is that there are many repeating values of a and b; a stays fixed and it then iterates across all values of b, then moves onto the next value of a, and so forth. The range of a and b is fixed and always iterate across equally spaced values though.
Below is the code I have created for this. So for it seems to not to work and I am out of ideas.
z_true_len = length(unique(a)); %number of z distances
r_true_len = length(unique(b)); %number of r disatances
data_matrix = zeros(r_true_len,z_true_len); %create r x z matrix, full of 0s
z_past = 0;
r_past = 0;
z_count = 1;
r_count = 1;
for count = 1: length(a)
z_current = a(count);
if z_past ~= z_current
data_matrix(1:z_count) = c(count);
z_past = z_current;
z_count = z_count + 1;
r_count = 1;
else
data_matrix(r_count:z_count) = c(count);
r_count = r_count + 1;
end
end
data_matrix
Any help would be appriciated
I included a mapping of the a and b arrays into a space of integers:
% Data
a = [ 0.5 0.5 2.5 0.5 2.5 2.5 4.5 4.5 4.5 2.5 4.5 0.5];
b = [-35 -25 -25 -15 -45 -35 -35 -45 -15 -15 -25 -45];
c = [2 1 -2 4 6 4 6 8 4 1 -5 2];
% Mapping from real to integers
a_unique = sort(unique(a));
b_unique = sort(unique(b));
a_idx = zeros(size(a));
b_idx = zeros(size(b));
for ii = 1:numel(a_unique),
a_idx(a_unique(ii)==a) = ii;
end
for ii = 1:numel(b_unique),
b_idx(b_unique(ii)==b) = ii;
end
% Create matrix
data_matrix = zeros(numel(b_unique),numel(a_unique));
for count = 1:length(a_idx),
data_matrix(b_idx(count),a_idx(count)) = c(count);
end
% Plot
figure;
imagesc(data_matrix);
You basically need to define data_matrix with the appropriate dimensions, and then fill values in using linear indexing (see sub2ind):
m = max(b); %// number of rows in result
n = max(a); %// number of columns in result
data_matrix = NaN(m,n); %// define result matrix with appropriate dimensions
data_matrix(sub2ind([m n], b, a)) = c; %// fill values using indexing
If a and b don't always contain integers: first transform into "integer labels" with the third output of unique, and then proceed as above:
[~, ~, bb] = unique(b); %// get integer labels for b
[~, ~, aa] = unique(a); %// get integer labels for a
m = max(bb); %// number of rows in result
n = max(aa); %// number of columns in result
data_matrix = NaN(m,n); %// define result matrix with appropriate dimensions
data_matrix(sub2ind([m n], bb, aa)) = c; %// fill values using indexing

Create all possible Mx1 vectors from an Nx1 vector in MATLAB

I am trying to create all possible 1xM vectors (word) from a 1xN vector (alphabet) in MATLAB. N is > M. For example, I want to create all possible 2x1 "words" from a 4x1 "alphabet" alphabet = [1 2 3 4];
I expect a result like:
[1 1]
[1 2]
[1 3]
[1 4]
[2 1]
[2 2]
...
I want to make M an input to my routine and I do not know it beforehand. Otherwise, I could easily do this using nested for-loops. Anyway to do this?
Try
[d1 d2] = ndgrid(alphabet);
[d2(:) d1(:)]
To parameterize on M:
d = cell(M, 1);
[d{:}] = ndgrid(alphabet);
for i = 1:M
d{i} = d{i}(:);
end
[d{end:-1:1}]
In general, and in languages that don't have ndgrid in their library, the way to parameterize for-loop nesting is using recursion.
[result] = function cartesian(alphabet, M)
if M <= 1
result = alphabet;
else
recursed = cartesian(alphabet, M-1)
N = size(recursed,1);
result = zeros(M, N * numel(alphabet));
for i=1:numel(alphabet)
result(1,1+(i-1)*N:i*N) = alphabet(i);
result(2:M,1+(i-1)*N:i*N) = recursed; % in MATLAB, this line can be vectorized with repmat... but in MATLAB you'd use ndgrid anyway
end
end
end
To get all k-letter combinations from an arbitrary alphabet, use
n = length(alphabet);
aux = dec2base(0:n^k-1,n)
aux2 = aux-'A';
ind = aux2<0;
aux2(ind) = aux(ind)-'0'
aux2(~ind) = aux2(~ind)+10;
words = alphabet(aux2+1)
The alphabet may consist of up to 36 elements (as per dec2base). Those elements may be numbers or characters.
How this works:
The numbers 0, 1, ... , n^k-1 when expressed in base n give all groups of k numbers taken from 0,...,n-1. dec2base does the conversion to base n, but gives the result in form of strings, so need to convert to the corresponding number (that's part with aux and aux2). We then add 1 to make the numbers 1,..., n. Finally, we index alphabet with that to use the real letters of numbers of the alphabet.
Example with letters:
>> alphabet = 'abc';
>> k = 2;
>> words
words =
aa
ab
ac
ba
bb
bc
ca
cb
cc
Example with numbers:
>> alphabet = [1 3 5 7];
>> k = 2;
>> words
words =
1 1
1 3
1 5
1 7
3 1
3 3
3 5
3 7
5 1
5 3
5 5
5 7
7 1
7 3
7 5
7 7
use ndgrid function in Matlab
[a,b] = ndgrid(alphabet)

Resources