List all permutations of the numbers 1,...,n in lexicographic order - matlab

I'm trying to program a Matlab to list all permutations of the numbers 1 through n in lexicographic order. What I have so far is below. I am using recursion to try and write a program that will work for n=3 first, and then see if I can gain insight into writing the program for any n. So far I have 2 of the 6 columns for n=3: P=[1 2 3;1 3 2]. I need the next two columns to simply swap the ones and the twos. I don't know how to begin to do that.
function [P] = shoes(n)
if n == 1
P = 1;
elseif n == 2
P = [1 2; 2 1];
else
T = shoes(n-1) + 1;
G = ones(factorial(n-1),1);
P(1:2,1:3) = [G T];
end

See the documentation for a start. If by lexicographical order you mean alphabetical by english name, you may want to populate your input with the names, sort them, then permute that.
If I've misunderstood what you're wanting, comment or edit the question & I'll check back later.
Hints:
The permutations of an empty list are easy to find.
Induction is an important concept in mathematics. You should be familiar with it.
The environment you are working in supports recursion
The permutations of a longer list can be produced in the order you want by recursion; first figure out what you want the first element to be, and then figure out the rest.
If you get stuck again, edit the question posting what you've gotten so far and where/why you think you're stuck.
Hints after seeing your code.
Your core function permutes a vector, and so should take a vector as argument, not an integer
Don't start solving the n=3 case; try the n=0 case (it's []) and then go straight to the n=20 case.
Think about the n=20 case before you write any code. What is the first column going to look like? Are there any examples of the n=19 case hidden in the answer to the n=20 case? (The answer is yes, and they are all different).
Reread the first set of hints

You appear to have asked this question twice. Instead of reposting questions, you should simply click the "edit" link below your question and update it. I'll repost here the answer I gave to your other question, but you should really remove one of them.
If you have the following matrix:
A = [1 2 3; 1 3 2];
and you want all the ones to become twos and the twos to become ones, the following would be the simplest way to do it:
B = A;
B(A == 1) = 2;
B(A == 2) = 1;

Related

Fastest way to choose a matrix row given a certain condition

In Matlab, I have a 2x3 matrix, A, like this one:
A = [1 2 3; 4 5 6];
This matrix is defined inside of a function which takes a parameter, T. There are two cases that I need to take care of:
T < 10
T >= 10
If the user entered, say, T=40, then the 2nd row of A should be selected to make the calculations. On the other hand, if say T=5, the first row of A should be selected.
I can write a simple if-else condition like this:
if (T<10)
b = A(1,:) * ... %Do whatever with the first row
else
b = A(2,:) * ... %Do whatever with the second row
end
However I was wondering if it's possible to play around with Matlab indexes to save myself the overhead of having to write this if-else condition all around my code (this condition has to be checked many times, in different parts of my program).
For example, I was hoping to reach a simple expression like A(T<10, :) which would work fine if T<10 but for T>=10 would return an empty matrix.
I've been racking my brains for some hours but I'm a bit of a novice in optimising Matlab scripts. Could anyone kick me in the right direction?
You can use the following method:
A((T>=10) + 1, :)

Compare different sized vectors with different values

I'm still fairly new to working with Matlab and programming. I have a dataset with n trials, of these (in this case) m are relevant. So I have an m-by-1 vector with the indices of the relevant trials (rel). I have another vector (Correct which is n-by-1) that consists of 0 and 1. n is always bigger than m. I need to know which trials (of the m-by-1 relevant trials) have a 1 in the n-by-1 vector. I have tried for-loops but I always get an error 'Index exceeds matrix dimensions.'
Here is my code:
for i=1:length(rel);
CC=rel(find(Correct==1));
end;
I think it should be fairly simple but I don't know yet how to explain to Matlab what I want...
Thank you all for your answers. I realized that my question was not as clear as I thought (also a learning process I guess..) so your suggestions weren't exactly what I need. I'm sorry for being unclear.
Correct is not a logical, it does contain 0 and 1 but these refer to correct or incorrect answer (I'm actually not sure if this matters but I thought I let you know)
rel is a subset of the original data with all trials (all trials=n trials), Correct is the same length as the original vector with all trials (n trials). So rel contains the indices of the (for me) relevant trials of the original data and is that way connected to Correct.
I hope this makes my question a bit more clear, if not, let me know!
Thank you!
It's not quite clear from your question what you are trying to do but I think I have an idea.
You have a vector n similar to
>> n = round(rand(1, 10))
n =
0 1 1 0 0 0 1 0 0 1
and m is indices of this vector similar to
>> m = [1 3 7 9];
Now we use m to index n as n(m) which will return the values of n corresponding to the elements in m. Next we need to check these for equality with 1 as n(m) == 1 and finally we need to figure out what values of m have n equal to 1 again by indexing. So putting this altogether we get
>> m(n(m) == 1)
ans =
3 7
To find the indices of m that are being returned you can use
>> find(n(m) == 1)
ans =
2 4
I'm assuming that Correct is of type logical (i.e. it contains trues and falses instead of 0s and 1s).
You actually don't need a loop here (this is clear in your case, since you are looping over i and never actually use i in your loop):
m = numel(rel)
CC = rel(Correct(1:m))
The reason you are getting that error is because Correct has more elements than rel so you are attempting to address elements beyond the end of rel. I solve this above by only considering the first m elements of Correct.

Comparing columns of matrix and giving boolean output

I have checked other questions. I didn't find my answer. I have a matrix of n * 2 size. I want to compare the 1st and 2nd column and based on which is greater I want to assign 0/1 to the respective index. Suppose I want an output as
a = 1 2
4 3
7 8
I want the output like this
out = 0 1
1 0
0 1
I did this :
o1 = a(:,1) > a (:,2)
o2 = not(o1)
out = [o1, o2]
This does the job but I am sure there's a better way to do this. Need suggestions on that/.
Forgot to mention, the datatype is float in the matrix.
A more generic solution that can handle matrices with more than two columns:
out = bsxfun(#eq, a, max(a,[],2));
What you did is good. The number of lines doesn't really matter, what matters is the complexity of the operation in each line. Following the comments, I think you could gain some time as well by avoiding copy and multiple allocations:
out = false(size(a)); out(:,1) = (a(:,1) > a(:,2)); out(:,2) = ~out(:,1);
It is good practice to preallocate in Matlab, and in general to avoid copies in any programming language.
Optimizing further the runtime of this by using different operations is pointless IMO. If you really need speed you could Mex it to spare one iteration through the rows (second assignment), it's literally a dozen C lines, although you'd have to be careful about how you write the loop (the naive way would cause cache-miss at each iteration).

What's the most idiomatic way to create a vector with a 1 at index i?

In Matlab, suppose I would like to create a 0-vector of length L, except with a 1 at index i?
For example, something like:
>> mostlyzeros(6, 3)
ans =
0 0 1 0 0 0
The purpose is so I can use it as a 'selection' vector which I'll multiply element-wise with another vector.
The simplest way I can think of is this:
a = (1:N)==m;
where N>=m. Having said that, if you want to use the resulting vector as a "selection vector", I don't know why you'd multiply two vectors elementwise, as I would expect that to be relatively slow and inefficient. If you want to get a vector containing only the m-th value of vector v in the m-th position, this would be a more straightforward method:
b = ((1:N)==m)*v(m);
Although the most natural method would have to be this:
b(N)=0;
b(m)=v(m);
assuming that b isn't defined before this (if b is defined, you need to use zeros rather than just assigning the Nth value as zero - it has been my experience that creating a zero vector or matrix that didn't exist before that is most easily done by assigning the last element of it to be zero - it's also useful for extending a matrix or vector).
I'm having a hard time thinking of anything more sensible than:
Vec = zeros(1, L);
Vec(i) = 1;
But I'd be happy to be proven wrong!
UPDATE: The one-liner solution provided by #GlenO is very neat! However, be aware that if efficiency is the chief criteria, then a few speed tests on my machine indicate that the simple method proposed in this answer and the other two answers is 3 or 4 times faster...
NEXT UPDATE: Ah! So that's what you mean by "selection vectors". #GlenO has given a good explanation of why for this operation a vector of ones and zeros is not idiomatic Matlab - however you choose to build it.
ps Try to avoid using i as a subscript, since it is actually a matlab function.
Just for the fun of it, another one-liner:
function [out] = mostlyzeros(idx, L)
out([L, idx]) = [0 1];
I can think of:
function mostlyones(m,n)
mat=zeros(1,m);
mat(n)=1;
Also, one thing to note. In MATLAB, index starts from one and not from zero. So your function call should have been mostlyzeros(6,3)
I would simply create a zero-vector and change whatever value you like to one:
function zeroWithOne(int numOfZeros, int pos)
a = zeros(numOfZeros,1);
a(pos) = 1;
Another one line option, which should be fast is:
vec = sparse(1, ii, 1, 1, L);

Why does crossvalind fail?

I am using cross valind function on a very small data... However I observe that it gives me incorrect results for the same. Is this supposed to happen ?
I have Matlab R2012a and here is my output
crossvalind('KFold',1:1:11,5)
ans =
2
5
1
3
2
1
5
3
5
1
5
Notice the absence of set 4.. Is this a bug ? I expected atleast 2 elements per set but it gives me 0 in one... and it happens a lot that is the values are not uniformly distributed in the sets.
The help for crossvalind says that the form you are using is: crossvalind(METHOD, GROUP, ...). In this case, GROUP is the e.g. the class labels of your data. So 1:11 as the second argument is confusing here, because it suggests no two examples have the same label. I think this is sufficiently unusual that you shouldn't be surprised if the function does something strange.
I tried doing:
numel(unique(crossvalind('KFold', rand(11, 1) > 0.5, 5)))
and it reliably gave 5 as a result, which is what I would expect; my example would correspond to a two-class problem (I would guess that, as a general rule, you'd want something like numel(unique(group)) <= numel(group) / folds) - my hypothesis would be that it tries to have one example of each class in the Kth fold, and at least 2 examples in every other, with a difference between fold sizes of no more than 1 - but I haven't looked in the code to verify this.
It is possible that you mean to do:
crossvalind('KFold', 11, 5);
which would compute 5 folds for 11 data points - this doesn't attempt to do anything clever with labels, so you would be sure that there will be K folds.
However, in your problem, if you really have very few data points, then it is probably better to do leave-one-out cross validation, which you could do with:
crossvalind('LeaveMOut', 11, 1);
although a better method would be:
for leave_out=1:11
fold_number = (1:11) ~= leave_out;
<code here; where fold_number is 0, this is the leave-one-out example. fold_number = 1 means that the example is in the main fold.>
end