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() ) );