What is the fastest and most elegant way to calculate permutations of a vector of numbers?
9 Ansichten (letzte 30 Tage)
Ältere Kommentare anzeigen
Marvin Heidkamp
am 30 Jan. 2019
Kommentiert: Marvin Heidkamp
am 30 Jan. 2019
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
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
Akzeptierte Antwort
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.
In your loop move the calculation of the power of 10 outside the loop.
3 Kommentare
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.
Weitere Antworten (0)
Siehe auch
Kategorien
Mehr zu Language Support finden Sie in Help Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!