On 3/8/11 Tue  Mar 8, 2011  2:51 PM, "Ben Lavery" <ben.lav...@gmail.com>
scribbled:

> Here is my code, I've taken out a few irrelevant bits, but this is the main
> guts:
> use warnings;
> use strict;
> use Math::Combinatorics;
> 
> #Set up a hash for searching later
> my %word_list;
> 
> #Read list of valid words into hash
> my $WORDFILE='Words';
> open(WORDFILE, "$WORDFILE") or die "can't open $WORDFILE: $!";
> while (<WORDFILE>) {
> chomp;
> $word_list{$_} = 0;

If you assign 1 to the hash value, you can dispense with the 'exists' in
your test, below.

> }
> close(WORDFILE);
> 
> #Set up letters
> my @letters = split(//, $ARGV[0]);
> 
> #Used to hold all valid combinations of characters
> my @all_combinations;
> 
> #Iterate through the letters
> #We then calculate all combinations
> #of the letters and see if any of them match a real word.  If they
> #do, we add them to the @all_combinations array.
> my $count = 3;
> while($count <= @letters){
> my $combinator1 = Math::Combinatorics->new(
> count => $count,
> data => [@letters],
> );
> 
> while(my @combo = $combinator1->next_combination){
> my $combinator2 = Math::Combinatorics->new(
> count => $count,
> data => [@combo],
> );
> 
> while(my @perm = $combinator2->next_permutation){
> my $temp_word = join('',@perm);
> 
> #Here, using a hash looks much cleaner than iterating through an array
> push(@all_combinations, $temp_word) if (exists $word_list{$temp_word});

Here, if hash values are 1, you don't need 'exists':

push(@all_combinations, $temp_word) if $word_list{$temp_word};

> }
> }
> $count++;
> }
> 
> #Remove duplicates
> my %hash = map { $_ => 1 } @all_combinations;
> @all_combinations = keys %hash;
> 
> #Print out the array, separating each element with a newline.
> print join("\n",@all_combinations),"\n";
> 
> 
> Currently, I can call the script as below and get the following output:
> $ perl combinations.pl abcde
> bade
> bed
> dace
> bad
> dab
> bead
> ace
> bac
> cad
> aced
> cade
> abc
> ade
> cab
> 
> I want to be able to specify something like:
> $ perl combinations.pl ab.de
> This would essentially be the same as doing:
> cat Words | grep -e "^ab.de$"
> Where Words is a file containing all of the valid words.
> 
> I'm wondering if I need to convert my hash of valid words into an array, then
> iterate through each entry with something like:
> if($word_list[i] =~ m/$temp_word/){
> push(@all_combinations, $temp_word);
> }

You can use the built-in grep function to compare each of the words in your
word list to your specified pattern, used as a regular expression, and
return all that match. In that case, the period is fine, as it will match
any character:

my @matches = grep( /^$temp_word$/i, @word_list );
push( @all_combinations, @matches );

Note that I have anchored the pattern to the beginning and end of the string
so that only full words match, and I have used the i modifier for
case-insensitivity. If everything is in the same case, you can dispense with
the /i modifier for a little more efficiency; just lower-case your input
pattern first.



-- 
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to