#!/usr/bin/env perl -w sub mysort{ #I'm not actually going to use this function, but this code #spells out how the finished sorting procedure ends up working if (length $a < length $b){ return 1; #a is shorter, so b is first; } elsif (length $a > length $b){ return -1; #a is longer, so a is first; } else { #lengths are equal, now compare the strings if ($a lt $b){ return 1; #a is 'less than' b, so b is first } elsif ($a gt $b){ return -1; #a is 'greater than' b, so a is first } else{ return 0; #strings are equal, so it doesn't matter } } } #the or operator expects a scalar, so we get the size of @ARGV. If there #are no command line arguments, the size is 0, so we evaluate the other part #of the or statement. @ARGV or die "You must enter at least one file name on the command line!\n"; #go through each file and try to open it. We can't use the empty <> operator #here, because we need to be able to give an appropriate error message #if the file cannot be opened. foreach $file (@ARGV){ if (!open FILE, "$file"){ print STDERR "Could not open file $file: $!\n"; next; } #Go through each line, split it on the space character. foreach $line (){ chomp $line; @words = split / /, $line; foreach (@words){ #remove anything from the word that's not a letter, number, or ' s/[^\w\']//g; #add this word to the hash, incrementing its count $hash{$_}++; } } close FILE; } #Sort the keys of the hash by length, then in reverse ASCIIbetical order @sorted = sort {length($b) <=> length($a) or $b cmp $a} keys (%hash); #If I wanted to use the sort function above, I could have instead written: #@sorted = sort mysort keys (%hash); #We will now figure out to which set(s) each word belongs #instead of a foreach with a bunch of push ... if statements, #I could have just done 5 grep statements. But we didn't cover grep before #the homework was due. foreach (@sorted){ push @Capitals, $_ if /^[A-Z]/; #beginning of string, capital letter push @lowers, $_ if /^[a-z0-9]/; #beginning of string, lowercase or number push @apos, $_ if /\'/; #apostrophe, anywhere in the string push @vowels, $_ if /[aeiou]{2}/i; #two of a, e, i, o, u - case insensitive push @dups, $_ if /(.)\1/i; #any character, immediately followed by itself } #now, for each set, print out every member of the set, followed by #its count in the hash print "Words starting with Capitals:\n"; foreach (@Capitals){ print "\t$_ - $hash{$_}\n"; } print "\n"; print "Words starting with lowercase letters (or numbers):\n"; foreach (@lowers){ print "\t$_ - $hash{$_}\n"; } print "\n"; print "Words containing apostrophes:\n"; foreach (@apos){ print "\t$_ - $hash{$_}\n"; } print "\n"; print "Words containing adjacent vowels:\n"; foreach (@vowels){ print "\t$_ - $hash{$_}\n"; } print "\n"; print "Words containing adjacent duplicate letters:\n"; foreach (@dups){ print "\t$_ - $hash{$_}\n"; } print "\n";