#!/usr/bin/perl -w
# Lempel-Ziv Coding - Operating on a string of ASCII characters
# Lossless compression - variable length data to fixed length representation
###############################################################################

use strict;
my @chars = qw(a b b a a b b a a b a b b a a a a b a a b b a);
my @newdata = ();
my ($str, $char);
my %defs = ('a', 0, 'b', 1);
my $nextdef = 2;
my $line;

###############################################################################
### If a filename is passed as a command line argument, use its contents for 
### the @chars array instead of the test data. 
if (defined($ARGV[0])) {
	@chars = ();
	open (INFILE, $ARGV[0]) or die "Cannot open $ARGV[0]: $!\n";
	while ($line = <INFILE>) {
		chomp($line);
		push (@chars, split (//, $line));
	}
	close (INFILE) or die "Cannot close $ARGV[0]: $!\n";
}
###############################################################################

$str = $chars[0];
my $i;
for ($i=1; $i<@chars; $i++) {
	$char = $chars[$i];
	if (defined($defs{$str.$char})) {
		$str .= $char;
	} else {
		print "$str => $defs{$str}\n";
		push (@newdata, $defs{$str});
		$defs{$str.$char} = $nextdef++;
		$str = $char;
	}
}
print "$str => $defs{$str}\n";
push (@newdata, $defs{$str});

print "\nOriginal Data: @chars\n";
print "Encoded Data: @newdata\n";
	


open (OUTFILE, ">lzw.out") or die "Cannot write to lzw.out: $!\n";
print OUTFILE join("", @newdata), "\n";
close (OUTFILE) or die "Cannot close lzw.out: $!\n";

print "\nData has been written to lzw.out\n";
