What is the fastest and most elegant way to calculate permutations of a vector of numbers?

9 Ansichten (letzte 30 Tage)
First question Is this this the best way to calculate the permutation of a number (I don't want an array of digits)?
>> n = 123;
>> x = str2double(cellstr(perms(int2str(n))))
x =
321
312
231
213
132
123
I rather doubt it...
Second question If it is, what is the best way to calculate the permutation matrix of a number vector (assuming the number of digits is prescribed)?
For example (in this case the numbers from 111 to 999):
Permut = nan(6,889);
for number = 111:999
counter = number-111+1;
Permut(:,counter) = str2double(cellstr(perms(int2str(number))));
end
Or more generic:
numDigits = 3;
nStart = str2double(strrep(num2str(ones( 1,numDigits)), ' ', ''));
nFinal = str2double(strrep(num2str(repmat(9,1,numDigits)), ' ', ''));
Permut = nan(factorial(numDigits),nFinal-nStart+1);
for number = nStart:nFinal
counter = number-nStart+1;
Permut(:,counter) = str2double(cellstr(perms(int2str(number))));
end
  4 Kommentare
Stephen23
Stephen23 am 30 Jan. 2019
Bearbeitet: Stephen23 am 30 Jan. 2019
Note that perms is documented to return the "...all permutations of the elements of vector v...". It does not return the unique permutations of the set of values, only of the elements of the vector. Do not confuse the unique permutations of vector elements with unique permutations of their values (which perms cares absolutely nothing about).
Your example shows that MATLAB correctly returns the six permutations of the elements of the vector [1,1,1], exactly as documented. But there is only one permutation of the set of values (1,1,1):
>> factorial(3) / factorial(3)
ans = 1
Marvin Heidkamp
Marvin Heidkamp am 30 Jan. 2019
Bearbeitet: Marvin Heidkamp am 30 Jan. 2019
Yes, thanks Stephen for that note. In my case the permutations of vector elements with unique permutations fit for my problem.
I like the brilliant explanation, thanks for the link :)

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Jan
Jan am 30 Jan. 2019
Bearbeitet: Jan am 30 Jan. 2019
Question 1:
perms(1:3) * [100; 10; 1]
Or the general case:
v = [2,5,4,8];
r = perms(v) * 10.^(numel(v)-1:-1:0).'
The multiple conversions by str2double, cellstr, and int2str are too indirect. If you want to work with numbers, stay at working with numbers.
If speed matters, replace perms by FEX: VChooseKO, which is about 10 times faster.
In your loop move the calculation of the power of 10 outside the loop.
  3 Kommentare
Jan
Jan am 30 Jan. 2019
sprintf('%d', number) - 48 is most likely faster than int2str. I'd prefer to avoid the conversion to a char vector and back to numbers:
num = mod(floor(N ./ pow10, 10);
A small test:
numDig = 5;
pow10 = 10.^(numDig-1:-1:0).';
tic;
for k = 11111:99999
n = int2str(k) - 48;
end
toc
tic;
for k = 11111:99999
n = sprintf('%i', k) - 48;
end
toc
tic;
for k = 11111:99999
n = mod(floor(k ./ pow10), 10);
end
toc
% INT2STR: 1.66 sec
% SPRINTF: 0.96 sec
% MOD: 0.33 sec
int2str calls sprintf internally, so calling it directly saves the overhead. But sprintf is extremely powerful, and this costs time. It is cheaper to avoid a conversion, most of all because the expensive pow10 vector has been calculated already.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Language Support finden Sie in Help Center und File Exchange

Produkte


Version

R2017b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by