Frank wiene
Frank wiene

Reputation: 47

Matlab - generating combinations of input and their sum

I have to make a function that takes 3 inputs like e0, e1 and e2. The function will have 2 outputs x and y.

x will be the combinations of e0, e1 and e2. y will be a column vector containing sums of columns of x.

The following conditions must be met when creating the function:

  1. inputs e0, e1 and e2 each have a single number.
  2. if user doesn't enter a value for the input it set to 0 as default.
  3. if user doesn't enter any input then a message that no input has been entered should be shown.

Here's an example:

combination pattern of X (first 3 columns):     pattern for y is the sum of x  
1 1 1                                           3  
2 1 1                                           4  
3 1 1                                           5  
1 2 1                                           4  
2 2 1                                           5  
3 2 1                                           6  
1 3 1                                           5  
2 3 1                                           6  
and so on...                            and so on....  

So far I have only been able to do this much with x and y displayed separately.

function [x,y]=create(e0,e1,e2)  
switch nargin  
case 2  
    e1=0;  
    e2=0;  
case 1  
    e2=0;  
case 0  
    disp('no input')  
end  

I googled my problem and found that combvec and allcomb should help but i cant figure out how.. Please help any answer or hint will be a great help.

Upvotes: 0

Views: 203

Answers (2)

knedlsepp
knedlsepp

Reputation: 6084

You were on the right track with allcomb. You are in fact looking for the cartesian product:

[e0, e1, e2] x [e0, e1, e2] x [e0, e1, e2] == [e0, e1, e2]^3.

You don't need allcomb though, as ndgrid can already do this.

Let's start with your code. It has a bug. Basically case 2 and case 1 are flipped.

function [x,y] = create(e0,e1,e2)  
switch nargin
case 2
    e1=0; % <- When nargin==2, this value is set, and you overwrite it.
    e2=0;  
case 1  
    e2=0; % <- When nargin==1, e1 must also be set to zero.
case 0  
    disp('no input') % <- use `error` instead of `disp`? If not, use `return` here.
end  

You would then need to check that the numbers provided are not matrices. This can be achieved with something like that. (Fill in the blanks.)

assert(numel(e1)==1 && numel(__)___  && numel(__)___,'Input sizes are incorrect');

To generate the cartesian product [e0, e1, e2] x [e0, e1, e2] x [e0, e1, e2] you are looking for, you can either use this answer for allcomb or this answer for the built-in ndgrid.

sets = {[e0,e1,e2], [e0,e1,e2], [e0,e1,e2]};

cartProd1 = allcomb(sets{:})

[x y z] = ndgrid(sets{:});
cartProd2 = [x(:) y(:) z(:)]

You could swap the columns of cartProd if you want the correct ordering. For generating the sum along the rows, use

sum(cartProd,2)

Upvotes: 1

rayryeng
rayryeng

Reputation: 104484

What you want are permutations not combinations. You listed that 2 3 1 and 3 2 1 are different, yet if you were to make this a combination, you would consider these as being the same. As such, I'm going to refer you to this post instead:

How to find all permutations (with repetition) in MATLAB?

I'm specifically going to take Rody Oldenhuis's answer. Therefore, you can construct all possible permutations by:

x = unique(nchoosek(repmat([e0 e1 e2], 1, 3), 3), 'rows');

This will create an array of all possible permutations with e0 e1 and e2. As such, using your example with e0 = 1, e1 = 2, e2 = 3, we get:

x =

     1     1     1
     1     1     2
     1     1     3
     1     2     1
     1     2     2
     1     2     3
     1     3     1
     1     3     2
     1     3     3
     2     1     1
     2     1     2
     2     1     3
     2     2     1
     2     2     2
     2     2     3
     2     3     1
     2     3     2
     2     3     3
     3     1     1
     3     1     2
     3     1     3
     3     2     1
     3     2     2
     3     2     3
     3     3     1
     3     3     2
     3     3     3

Now to finally get what you want, you just have to sum over the rows, so do:

y = sum(x, 2)

y =

     3
     4
     5
     4
     5
     6
     5
     6
     7
     4
     5
     6
     5
     6
     7
     6
     7
     8
     5
     6
     7
     6
     7
     8
     7
     8
     9

You've already written the case to handle when the user doesn't enter anything for e0, e1 and/or e2, so all you have to do is take your code, and piece what I wrote above into your function. It should give what you want.

Upvotes: 0

Related Questions