「A・E・H・R・T」でできるすべての文字列を表示するプログラム

そういえば「有限と微小のパン」にはそういう場面があったなあ。乱数でテキトーに求めるPerlスクリプトを書いたけれど、自分もモヤモヤ。綺麗な解答例が見てみたい。

#!/usr/bin/env perl -w
# pan.pl
# -*- Mode: Perl; coding: shift_jis -*-

use strict;
use warnings;

# ハッシュをqwで囲む
my %alphabet = qw(
    1  a
    2  e
    3  h
    4  r
    5  t
    );
my $length = keys(%alphabet);   # 文字列の長さ
my %wordlist;
my $id = 0;

while ( $id < fact($length) ) {
    my %copy = %alphabet;
    my $word;
    my $flag = 0;

    while ( $flag < $length ) {         # 文字列数に満たない間

        my $rand = int(rand $length) + 1;

        if ( $copy{$rand} eq '' ) { # すでに消されていたら
            next;               # 次へ
        }

        $word .= $copy{$rand};
        $copy{$rand} = '';      # 付け加えたものは消す
        $flag++;
    }

    unless ( defined $wordlist{$word} ) { # まだない
        $wordlist{$word} = $id; # 登録
        $id++;
    }
}

foreach my $key ( sort keys %wordlist ) {
    print uc("$key\n");
}


# マジックナンバーを入れたくなかった
sub fact {
    my $number = shift;
    my $result = 1;

    for ( my $i = 1; $i <= $number; $i++ ) {
        $result = $result * $i;
    }

    return $result;
}
# pan.pl ends here.

5/23追記 :小文字よりも大文字が良いような気がしたのでucで囲った。