On 3/8/11 Tue Mar 8, 2011 2:51 PM, "Ben Lavery" <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]
http://learn.perl.org/