# Dear QOTW folks,
# 
# I attach my solution to novice QOTW #8.
# 
# It splits each input line on whitespace, so that the
# "dictionary" can have multiple words per line.
# 
# It uses substr() to look for substrings of a fixed length.
# The length specified in the problem is 4, of course.  These
# substrings are stored in a hash %super, with the substring as the
# key, and the (first) input string as its value.  A second
# hash, %nix, is used to see which substrings occur in one more
# than one word, and hence should be nixed from the final
# output.
# 
# Comparisons are done using lc() everywhere, but the input
# words are not modified.  So, if "Bill" and "bill" occur in
# the input, /bill/ is considered a unique substring, and gets
# listed in the "questions" file.  The "answers" file lists
# whichever of "Bill" and "bill" occurred first in the input
# stream.
# 
# So, if the input is "Bill bill carry harry Bill", %super will
# contain (bill => Bill, carr => carry, arry => carry, harr =>
# harry), and %nix will contain (arry => 1).
# 
# The output files will be as follows:
# 
#     questions  answers
#     ---------  -------
#       bill      Bill
#       carr      carry
#       harr      harry
# 
# peace,                              || From Child Labour to Scholarship
# --{kr.pA}                           || http://makeashorterlink.com/?J17F21842

#!/usr/bin/env perl

# $Id: qotw8.pl,v 1.1 2002/12/13 03:20:48 ksundar Exp ksundar $

# Intention: Solve QOTW #8.

use 5.006;
use warnings;
use strict;

use constant LEN => 4;	# The length of the unique substring.

my %super;	# Hold the super-string of each substring.
my %nix;

while (<>) {
    # Mark Jason says "... given a dictionary ...".  Assuming a liberal
    # interpretation, a dictionary need not have each word on a separate line.
    # So, split().
    for (split) {
	my $l = length;

	# Zap short and non- words.
	next if LEN > $l or /[^a-z]/i;

	# For every $LEN-character substring, check if it was seen
	# before in a different word.  The different word test is
	# important for multiple reasons: repeated words in the input,
	# words differing only in case, and repeated substrings within
	# a word.  e.g.: "Mississippi" has two (overlapping) substrings
	# "issi" in it.
	for my $i (0 .. $l - LEN) {
	    my $s = lc substr($_, $i, LEN);

	    if ($super{$s} 			# I've seen it before ...
		&& (lc $super{$s} ne lc)	# ... in a different word.
		) {
		$nix{$s}++;
	    } else {
		$super{$s} ||= $_;	# Remember first occurrence.
	    }
	} # for my $i
    } # for (split)
} # while (<>)

open QQ, ">questions" or die "Can't write to ./questions!";
open AA, ">answers" or die "Can't write to ./answers!";

$\ = "\n";
for (sort grep !defined $nix{$_}, keys %super) {
    print QQ $_;
    print AA $super{$_};
}

__END__
