sub permute { my @items = @_; my $n = 0; return sub { $n++, return @items if $n==0; my $i; my $p = $n; for ($i=1; $i<=@items && $p%$i==0; $i++) { $p /= $i; } my $d = $p % $i; my $j = @items - $i; return if $j < 0; @items[$j+1..$#items] = reverse @items[$j+1..$#items]; @items[$j,$j+$d] = @items[$j+$d,$j]; $n++; return @items; } } #### 15 = 2*3! + 1*2! + 1*1! #### sub fb_to_perm { my @arr = @{ shift() }; my $fb = shift; return unless defined $fb; my @ret; push @ret, splice @arr, $_, 1 for @$fb; push @ret, @arr; return @ret; } #### my $n = 0; { my $fb = n_to_fb( $n, scalar @my_list ); last unless $fb; my @perm = fb_to_perm( \@my_list, $fb ); print "@perm\n"; ++$n; redo; } #### A B C D 000_F B A C D 100_F C A B D 200_F D A B C 300_F A B D C 001_F B A D C 101_F C A D B 201_F D A C B 301_F A C B D 010_F B C A D 110_F C B A D 210_F D B A C 310_F A C D B 011_F B C D A 111_F C B D A 211_F D B C A 311_F A D B C 020_F B D A C 120_F C D A B 220_F D C A B 320_F A D C B 021_F B D C A 121_F C D B A 221_F D C B A 321_F #### A B C D 000_F A D C B 021_F B A C D 100_F B D C A 121_F C A B D 200_F C D B A 221_F D A B C 300_F #### A B C D 000_F A C B D 010_F A D B C 020_F B A C D 100_F B C A D 110_F B D A C 120_F C A B D 200_F C B A D 210_F C D A B 220_F D A B C 300_F D B A C 310_F D C A B 320_F #### sub offsets { my $p = $_[ 0 ]; my $i = 2; my $d; $p /= $i++ until $d = $p % $i; return ( $i, $d ); } #### sub perms { my @arr = @_; my $m = @arr; my $n = 0; { print "@arr\n"; ++$n; my ( $i, $d ) = offsets( $n ); last if $i > @arr; my $j = @arr - $i; @arr[ $j+1..$#arr ] = reverse @arr[ $j+1..$#arr ]; @arr[ $j, $j+$d ] = @arr[ $j+$d, $j ]; redo; } } #### my $j = @arr - $i; @arr[ $j+1..$#arr ] = reverse @arr[ $j+1..$#arr ]; @arr[ $j, $j+$d ] = @arr[ $j+$d, $j ]; #### @arr[ 0..$i-1 ] = reverse @arr[ 0..$i-1 ]; #### if ( $i % 2 ) { @arr[ $i-1, 0 ] = @arr[ 0, $i-1 ]; } else { @arr[ $i-1, $d-1 ] = @arr[ $d-1, $i-1 ]; } #### Iterator {...} #### \sum_{k=0}^{m-1}k*k! = m!-1 #### (m - 1)*(m - 1)! + (m - 1)! - 1 = m! - 1 #### sub n_to_fb { my ( $n, $m ) = @_; my @fb; for my $i ( 2 .. $m ) { my $r = $n % $i; unshift @fb, $r; $n = int( $n/$i ); ++$i; } return $n ? undef : \@fb; }