use strict; use warnings; my $letters = 'ABCDEF??'; my $length = length($letters); ## We'll be using factorials a lot, so it's best to pre-calculate my @factorial = (0,1); $factorial[$_] = $factorial[$_-1] * $_ for 2..$length; my ($blanks, @lsets, $lset, $nlset, $words, $twords); ## Find the number of blanks while ($letters =~ /[^A-Z]/) { $letters =~ s/[^A-Z]//; $blanks++; } ## Produce unique letter sets, given blanks @lsets = ($letters); while ($blanks--) { my %lsets; for $lset (@lsets) { for ('A'..'Z') { $nlset = join '', sort split //, $lset.$_; $lsets{$nlset} = (); } } @lsets = keys %lsets; } ## Calculate the number of words possible from each letter set for (@lsets) { $words = $factorial[$length]; my %lcount; $lcount{$_}++ for split //, $_; for (keys %lcount) { $words /= $factorial[$lcount{$_}] if $lcount{$_} > 1; } $twords += $words; } print $twords;