#!/usr/bin/perl # ichijou.pl - Don Yang (uguu.org) # # Translate tokens for each line, automatically select whether to use # lhs->rhs or rhs->lhs substitution. # # 06/11/06 use strict; my (@DEFAULT_DICT) = qw{ a=alpha b=bravo c=charlie d=delta e=echo f=foxtrot g=golf h=hotel i=india j=juliet k=kilo l=lima m=mike n=november o=oscar p=papa q=quebec r=romeo s=sierra t=tango u=uniform v=victor w=whiskey x=x-ray y=yankee z=zulu }; sub CmpKeys($$) { my ($c) = length($_[1]) - length($_[0]); return $c ? $c : $_[0] cmp $_[1]; } # Build dictionary from list of key=value pairs sub BuildDictionary($$$) { my ($key_pairs, $forward_dict, $reverse_dict) = @_; my (%forward_map, %reverse_map); # Parse pairs foreach my $entry (@$key_pairs) { next unless $entry =~ /([^=]+)=([^=]+)/; my ($a, $b) = (lc $1, lc $2); if( length($a) > 1 ) { $a .= ' '; } if( length($b) > 1 ) { $b .= ' '; } $forward_map{$a} = $b; $reverse_map{$b} = $a; } # Sort by longest key first foreach my $key (sort CmpKeys keys %forward_map) { push @$forward_dict, [$key, $forward_map{$key}]; } foreach my $key (sort CmpKeys keys %reverse_map) { push @$reverse_dict, [$key, $reverse_map{$key}]; } } # Consume tokens in text string, returns number of characters that # can't be substituted, and a list of transformed tokens. sub RunDFA($$) { my ($text, $dict) = @_; my ($errors, @tokens); $errors = 0; @tokens = (); while( $text ne "" ) { my ($key, $value); $key = $value = substr $text, 0, 1; $errors++; foreach my $i (@$dict) { if( substr($text, 0, length($$i[0])) eq $$i[0] ) { ($key, $value) = @$i; $errors--; last; } } push @tokens, $value; $text = substr $text, length($key); } return $errors, @tokens; } # Encode/decode text, return list of translated tokens: # 1. Prefer mapping with fewer errors. # 2. Prefer fewer transformations. sub Translate($$$) { my ($errors_f, @tokens_f) = RunDFA($_[0], $_[1]); my ($errors_b, @tokens_b) = RunDFA($_[0], $_[2]); return ($errors_f == $errors_b) ? ($#tokens_f < $#tokens_b ? @tokens_f : @tokens_b) : ($errors_f < $errors_b ? @tokens_f : @tokens_b); } my (@forward_dict, @reverse_dict); BuildDictionary( $#ARGV >= 0 ? \@ARGV : \@DEFAULT_DICT, \@forward_dict, \@reverse_dict); while( my $line = ) { chomp $line; print Translate("$line ", \@forward_dict, \@reverse_dict), "\n"; }