CSCI 4230
Internet Application Development
Spring 2001
Suugested Solution to Homework #2

(1)    For example,

perl -ne "tr /A-Z/a-z/; ($i++, print $i . ': ' . $_) if /a/ && /e/ && /i/ && /o/ && /u/;" words.txt

(2)    For example, a Perl-style, efficient, but not too flexible solution:

use strict;
#
# h2q1.pl
# Find all words from words.txt that are also words when all
# characters are shifted by three characters cyclically.
# Bun Yue   January 20, 20001
#

# Open the dictionary.
my $FILENAME = "words.txt";
open(IN, $FILENAME) || die "Can't open input file $FILENAME.\n";

# Store all words from the dictionary in lower cases into
# the key of the hash %words for fast searching.
my %words = ();  # Each key store a word in lower cases.
while ($_ = <IN>) {
   chomp;
   tr /A-Z/a-z/;
   $words{$_}++;
}

# Check every word to see whether shifting the word
# result in another word.
# Less portable but faster.
my $shiftedWord = ""; # The word shifted.
foreach (sort keys %words) {
    $shiftedWord = $_;
 # Each word is shifted three positions to the right cyclically.
 $shiftedWord =~ tr/a-z/d-za-c/;
    print "$_ => $shiftedWord\n" if $words{$shiftedWord};
}
exit 0;  # Main

A C-style (use of ord), less efficient but more flexible solution.

use strict;
#
#    h2q1.pl
#    Find all words from words.txt that are also words when all
#    characters are shifted by three characters cyclically.
#    Bun Yue   January 20, 20001
#

# Prepare array for efficient obtaining shifted characters.
my %SHIFTED_CHARS = ();
my $CHARS_SHIFT = 3;
for (my $i=0; $i<26; $i++) {
    my $char = chr(ord('a') + $i);
    $SHIFTED_CHARS{$char} = chr(ord('a') + (ord($char) - ord('a') + $CHARS_SHIFT) % 26);
}

# Open the dictionary.
my $FILENAME = "words.txt";
open(IN, $FILENAME) || die "Can't open input file $FILENAME.\n";

# Store all words from the dictionary in lower cases into
# the key of the hash %words for fast searching.
my %words = ();  # Each key store a word in lower cases.
while ($_ = <IN>) {
   chomp;
   tr /A-Z/a-z/;
   $words{$_}++;
}

# Check every word to see whether shifting the word
# result in another word.
my $shiftedWord = ""; # The word shifted.
foreach (sort keys %words) {
    $shiftedWord = join '', map {charShift($_)} split //;
    print "$_ => $shiftedWord\n" if $words{$shiftedWord};
}
exit 0;  # Main

# Shift a lower case letter by $CHARS_SHIFT characters cyclically.
sub charShift {
    my ($char) = split //, shift; # First char of the argument
    $SHIFTED_CHARS{$char}? $SHIFTED_CHARS{$char} : $char;
}
 

#    Alternative implementation of charShift without using a global
#    hash: less efficient but easier to understand.
#sub charShift {
#    my ($char) = split //, shift; # First char of the argument
#    my $CHARS_SHIFT = 3;
#    if ('a' le $char and $char le 'z') {
#    $char = chr(ord('a') + (ord($char) - ord('a') + $CHARS_SHIFT) % 26);
#    }
#    $char;
#}

(3)    For example,

perl -ne "print qq($1\n) if /<headline_text>(.*?)<\/headline_text>/" news.xml