#!c:/perl/bin/perl.exe # make sure you "hardwire" in your word list (see 8 lines down). use integer; # so the calculation of $mid will be integers $words=""; ($anagram,$words)=@ARGV; if ($anagram eq ""){ print "Usage: Perl anagram.pl anagram dictionary"; exit; } if ($words eq "") { #$words="c:/windows/desktop/perlhtml/SmallWordList.txt"; $words="c:/BigWordList.txt"; } open WORDS, $words or die "Cannot open $words for read :$!"; chomp (@list=); $st=&getpermutations($anagram); for $temp (@$st){ if (binarysearch($temp)) { print "anagram: $temp \n"; } } # this subroutine converts strings to arrays so they can be fed to # subroutine permute. They take the returned arrayref and reformat it so # that individual elements are words not individual letters. sub getpermutations { my ($str)=@_; @array=split //, $str; $length=$#array+1; $answer=&permute([@array], []); $fact=&factorial($length); for ($i=0;$i<$fact;$i++) { $string[$i]=""; for ($j=0;$j<$length;$j++) { $string[$i].=@$answer[$i*$length+$j]; } } return (\@string); } sub factorial { my ($temp)=@_; if ($temp>1) { return $temp*factorial($temp-1); } if ($temp==1) { return 1; } } # sub permute is a slightly modified version of a subroutine I found in # the CORE perl FAQs. I return an arrayref rather than print out # permutations sub permute { my @items = @{ $_[0] }; my @perms = @{ $_[1] }; unless (@items) { push (@output,@perms); } else { my(@newitems,@newperms,$i); foreach $i (0 .. $#items) { @newitems = @items; @newperms = @perms; unshift(@newperms, splice(@newitems, $i, 1)); permute([@newitems], [@newperms]); } } return (\@output); } sub binarysearch { my ($myword)=@_; $low=0; $high=$#list; $mid=($high+$low)/2; for(;;){ if (($high-$low)<3) { last; } if ($myword lt $list[$mid]) { $high=$mid; $mid=($high+$low)/2; } if ($myword gt $list[$mid]) { $low=$mid; $mid=($high+$low)/2; } if ($myword eq $list[$mid]) { return 1; } } foreach $word (@list[$low..$high]) { if ($myword eq $word) { return 1; } } return 0; }