Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a vector of repeating values sequences, with a given number of occurrences of each value

Tags:

matlab

I would like to implement the following function:

Input:

  1. Vector of values

  2. Vector of the same size, stating the number of occurrences each value (of the corresponding index) should have in the output vector.

Output:

A vector of the values, 1by1 in repeating sequences, where each value appears as it's needed number of occurrences.

The values will continue appearing 1by1, untill a value appeared as many times as needed, then the rest of the values will continue appearing without it.

Example:

Inputs:

  1. [1,2,3,4]

  2. [3,2,5,1]

Output: [1 2 3 4 1 2 3 1 3 3 3]

Wanted Solution:

I would like to find a solution that is simple, but does not use any loops, and is modular to any length of the input vectors.

Current Solution:

So far only managed to implement with loops or with unpleasant indexing. The solution with loops is as follows:

Double Loop:

vals_vec=1:4;
occur_vec=[3,2,5,1];
output_vec=zeros(1,sum(occur_vec));
num_of_vals=length(vals_vec);
output_i=1;

while (output_i<=length(output_vec)) % While in length of output vector
    for cur_val_i=1:num_of_vals % Loop over all values
        if(occur_vec(cur_val_i)>0) % If value hasn't reached its occurrence number
            occur_vec(cur_val_i)=occur_vec(cur_val_i)-1;
            output_vec(output_i)=vals_vec(cur_val_i);
            output_i=output_i+1;
        end

    end
end
output_vec

Single Loop:

vals_vec=1:4;
occur_vec=[3,2,5,1];
output_vec=[];

for cur_num_of_vals=length(vals_vec):-1:1
    [min_val,min_i]=min(occur_vec); % Find lowest occurrence number
    output_vec=[output_vec,repmat(vals_vec,1,min_val)]; % Add vals accordingly
    vals_vec=[vals_vec(1:min_i-1),vals_vec(min_i+1:cur_num_of_vals)]; % Remove the corresponding val
    occur_vec=occur_vec-min_val; % Reduce Occurences from all vals
    occur_vec=[occur_vec(1:min_i-1),occur_vec(min_i+1:cur_num_of_vals)]; % Remove the corresponding occurrence number
end

output_vec

Thanks!

like image 736
Prostagma Avatar asked Jun 27 '18 13:06

Prostagma


People also ask

How do you make a repeated value vector?

There are two methods to create a vector with repeated values in R but both of them have different approaches, first one is by repeating each element of the vector and the second repeats the elements by a specified number of times. Both of these methods use rep function to create the vectors.

Which of the following functions is used to create a vector with repeated values?

The rep function creates a vector with repeated elements.

How do you repeat a number in a vector in Matlab?

u = repelem( v , n ) , where v is a scalar or vector, returns a vector of repeated elements of v . If n is a scalar, then each element of v is repeated n times. The length of u is length(v)*n .

How do you make a repeating sequence in R?

How do you Repeat a Sequence of Numbers in R? To repeat a sequence of numbers in R you can use the rep() function. For example, if you type rep(1:5, times=5) you will get a vector with the sequence 1 to 5 repeated 5 times.


1 Answers

You can do this by over-replicating the input, then removing surplus repetitions.

Edit: here is a solution with no looping:

% Repeat array to max number of possible repetitions
out = repmat( vals, 1, max(reps) ); 
% Implicit expansion (requires R2016b or newer, otherwise use bsxfun) to create
% matrix of reducing repetition count, then remove repeated values
% where this is <= 0, i.e. where there are no repetitions remaining.
out(reshape( reps' - (0:max(reps)-1), 1, [] ) <= 0) = [];

% Pre-R2016b version would be 
% out(reshape( bsxfun(@minus, reps', (0:max(reps)-1)), 1, [] ) <= 0) = [];

Original: Requires a single loop, but over the input values not the output array so it's at least a short one...

vals = [1,2,3,4];
reps = [3,2,5,1];
out = repmat( vals, 1, max(reps) ); % repeat array to max number of possible repetitions
for ii = 1:numel(vals)
    % Remove elements which have appeared too many times
    out( out == vals(ii) & (cumsum(out==vals(ii)) > reps(ii)) ) = [];
end
like image 195
Wolfie Avatar answered Nov 20 '22 12:11

Wolfie