Por exemplo, para o conjunto (A B), o único embaralhamento no qual os dois elementos estão forma de suas posições originais é (B A). Para o conjunto (A B C), há duas possibilidades: (B C A) e (C A B).
Escrevi uma pequena função que recebe uma função de callback e uma lista de elementos para embaralhar.
#!/usr/bin/perl
use strict;
use experimental 'smartmatch';
sub derange(&\@;$@) {
my $callback=\&{shift @_};
my $items=shift;
my $count=shift||0;
if($count>$#$items) {
$callback->(@_);
} else {
my @column=@$items;
splice @column, $count, 1;
for my $el (@column) {
if(!($el~~@_)) {
derange($callback, $items, $count+1, @_, $el);
}
}
}
}
derange {print "@_\n"} @ARGV;
Minha pequena função lançou mão do operador experimental ~~ para verificar se um elemento já não foi usado. Então, a função basicamente caminha pelas permutações, usando para cada posição apenas os elementos que não estavam ali originalmente e descartando os elementos já usados no ramo atual da busca.
Uma otimização óbvia seria deixar calculados os elementos que podem aparecer em cada posição.
O operador ~~ é experimental, então é preciso declarar seu uso.
Como ele imprime um desarranjo por linha, pude testar o resultado com o wc:
$ perl desarranjo.pl A B C D E F G H I J | wc -l
1334961