#!/usr/bin/perl -w

# quick solution to Pascal assignment (symbol table), written in Perl
#
# takes input from standard input; divides into space-separated tokens, prints
# a list of token in reverse order of occurrence count, secondarily in order of
# "sequence", where each token is numbered in 1 .. .
#
# Raphael Finkel 1/2008

use strict;

my %table; # hash table of words; each entry is a reference to a hash
	# containing two keys: serial and count.

sub readData {
	$/ = undef; # read in one go.
	my $text = <STDIN>;
	my $serial = 0;
	my $elementCount = 0;
	my $first = 1; # special case for first word, which is a count
	for my $word (split /\s+/, $text) {
		if ($first) { # ignore the first word
			$first = 0;
			next;
		}
		$serial += 1;
		# print STDERR "serial $serial, word $word\n"; # debug
		if (defined $table{$word}) {
			${$table{$word}}{'count'} += 1;
		} else {
			$table{$word} = {'serial' => $serial, 'count' => 1};
		}
	} # each word
} # readData


sub printData {
	print "There are " . (scalar keys %table) .
		" entries in the symbol table\n";	
	for my $word (sort {
			my $aCount = ${$table{$a}}{'count'};
			my $bCount = ${$table{$b}}{'count'};
			if ($aCount == $bCount) {
				 ${$table{$a}}{'serial'} <=> ${$table{$b}}{'serial'}
			} else {
				$bCount <=> $aCount;
			}
		}	keys %table) {
		my %entry = %{$table{$word}};
		printf "serial %4d, count %2d: %s\n",
			$entry{'serial'}, $entry{'count'}, $word;
	} # each word
} # printData

readData();
printData();
