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

9 次查看(过去 30 天)
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 个评论
Stephen23
Stephen23 2019-1-30
编辑:Stephen23 2019-1-30
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 2019-1-30
编辑:Marvin Heidkamp 2019-1-30
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 :)

请先登录,再进行评论。

采纳的回答

Jan
Jan 2019-1-30
编辑:Jan 2019-1-30
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 个评论
Jan
Jan 2019-1-30
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.

请先登录,再进行评论。

更多回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Language Support 的更多信息

产品


版本

R2017b

Community Treasure Hunt

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

Start Hunting!

Translated by