#!/usr/bin/perl # This is a letter-frequency analyzer by Chris Staecker # Modified 4/28/08 use strict; use CGI; my $query = new CGI; sub maketop() { print "Chris Staecker: Frequency counter"; print ""; print "

Chris Staecker's frequency counter!

"; print "

This tool can help you crack a substitution or Vigenere cipher. Type your text below, and hit the button to compute the letter frequencies. You can also count frequencies in groups of letters offset by a particular number. (Choosing 5 offsets will count the frequencies in the groups of letters obtained by taking every 5th letter from the text.)

"; print "
"; print "


"; print "Count frequency using this many offsets:
"; print "
"; } sub isletter { my ($c) = @_; return (ord($c) > 64 and ord($c)<91); } sub makeoffsetfreqs { my ($t, $skip, $o) = @_; my %freq; my $total; # reverse it since chop takes off the end $t = reverse(uc($t)); # start at the offset my $i = 0; while ($i < $o and $t) { my $c = chop($t); while (not isletter($c) and $t) { $c = chop($t); } $i++; } while ($t) { my $c; $c = chop($t); # keep going until we get a letter while (not isletter($c) and $t) { $c = chop($t); } if (isletter($c)) { #to avoid counting the last character $freq{$c}++; } # skip some letters my $i = 1; while ($i < $skip and $t) { $c = chop($t); while (not isletter($c) and $t) { $c = chop($t); } $i++; } } # go through to compute the total count, and put in 0s for missed letters foreach (65..90) { if ($freq{chr($_)}) { $total += $freq{chr($_)}; } else { $freq{chr($_)} = 0; } } # print the frequencies, highest first while (keys %freq) { my $maxkey = (keys %freq)[0]; foreach (keys %freq) { if ($freq{$_} > $freq{$maxkey}) { $maxkey = $_; } } if ($freq{$maxkey}) { print "$maxkey: "; printf("%.3f", 100 * $freq{$maxkey} / $total); print "%
"; } else { print "$maxkey: 0
"; } delete $freq{$maxkey}; } } print $query->header(); maketop(); if ($query->param('text')) { my %freq; my $t = $query->param('text'); my $o = $query->param('offset'); print "

Results

"; print "

"; for (0..$o-1) { print ""; } print ""; for (0..$o-1) { print ""; } print "
Offset $_
"; makeoffsetfreqs($t, $o, $_); print "

"; } print "

You can see the source code for this CGI script

"; print "";