sub word_to_struct {
my ( $word ) = @_;
my %out;
$out{$_}++ for split //, $word;
return \%out;
}
sub read_dict {
my ( $dict_file ) = @_;
my %out;
$dict_file ||= '/usr/share/dict/words';
open my $dict_fh, '<', $dict_file
or die "Can't read '$dict_file': $!\n";
while ( my $word = <$dict_fh> ) {
chomp $word;
if ( $word =~ m{ \A [a-z]+ \z }xmsi ) {
$out{$word} = word_to_struct($word);
}
}
close $dict_fh or die "close failed: $!\n";
return \%out;
}
####
...
'expletive' => {
'l' => 1,
'e' => 3,
'p' => 1,
'v' => 1,
'x' => 1,
'i' => 1,
't' => 1
},
'measles' => {
'l' => 1,
'e' => 2,
'a' => 1,
'm' => 1,
's' => 2
},
...
####
sub possible {
my ( $tiles_ref, $dict_ref ) = @_;
my @out;
my %tile_count;
$tile_count{$_}++ for @{$tiles_ref};
my $longest_word = scalar @{$tiles_ref};
WORD:
foreach my $word ( keys %{$dict_ref} ) {
next WORD if length $word > $longest_word;
foreach my $letter ( keys %{$dict_ref->{$word}} ) {
next WORD if ! defined $tile_count{$letter};
next WORD if $dict_ref->{$word}{$letter} > $tile_count{$letter};
}
push @out, $word;
}
return @out;
}
# example:
use Data::Dumper;
print Dumper( possible( [ qw( a b c d e ) ], read_dict() ) );