順列を羅列する

#! /usr/bin/perl
# usage: ./permtation.pl 2 2 2 3 3 4 4 5 5 6 7
# 引数にリストを与えると、それで順列を作って、引数がなければ1, 2, 3, 1, 2, 3で実行
# 引数は、アルファベットなどでもok

use strict;

# main
my @list = scalar @ARGV ? @ARGV :  (1, 2, 3, 1, 2, 3); # 引数ゲット
my @r = parse(@list);
print join("\n", @r), "\n", "Total: ", scalar @r, "\n";

# parse
sub parse{
    # @tmpは使用可能な要素
    my @tmp = @_;
    my @toplist = @tmp;
    my @result;
    
    # 重複した要素を取り除く
    my %tmph;
    @toplist = map{ ($tmph{$_}++) ? () : $_ }@toplist;
    
    foreach my $i (@toplist){
        my @ag = @tmp;
        for my $j (0..$#ag){ # 使える要素リストから、一番目に使ってる要素を除く
            if( $ag[$j] eq $i ){ splice(@ag, $j, 1); last;}
        }
        
        # まだまだ再帰さ、運動会
        if(@ag){
            my @psd = parse( @ag );
            foreach my $d (@psd){
                push(@result, $i . $d);
            }
        } else {# 終わりのときは、再帰しない
            push(@result, $i);
        }
    }
    
    return @result;
}