HaB has asked for the wisdom of the Perl Monks concerning the following question:

So I have this younger cousin. He's really into fooling around with codes/ciphers and such. I was into the same stuff as a kid, so I figure I'd save him all the work of encoding and decoding by hand, and write him a coupla cool little programs that would do it for him.

So there's a code table I'd like to generate for him, but I'm not sure of the best way to store the data for easy retrieval later. The table works like this:

------------------- e x c h a m p i o n b d f g j k l q r s t u v w y z . ! ? , The last 4 chars are just here to complete the table.
1 2 3 4 5 6 7 8 9 0 ------------------- a c e h i m n o p x j f b g q k s r l d y w t w ! z , ? . u

Replies are listed 'Best First'.
Script to find optimal words
by tedv (Pilgrim) on Nov 10, 2000 at 00:15 UTC
    Just for fun, I wrote this script to parse /usr/dict/words looking for long words without repeating letters. Here's the code:
    #!/usr/bin/perl -w use strict; my @words = (); my $max_len = 0; my $delta = 2; # Number of letters less than maximum which is acceptab +le while (<>) { # Check for words which are too short my $cur_len = length; next if $cur_len + $delta < $max_len; # Check for words with repeating letters next if /(.).*\1/; # Store value in list, possibly destroying old values if ($cur_len > $max_len) { $max_len = $cur_len; @words = ($_); } else { push @words, $_; } } print @words;
    And if you're curious, here's the output:
    ambidextrously bankruptcies bluestocking configurable considerably consumptively copyrightable customizable exclusionary flowcharting incomputable productively questionably recognizably unpredictably unprofitable upholstering
    A thirteen letter word might work better because you wouldn't have to pad the cypher.

Re: Kiddie Codes
by Fastolfe (Vicar) on Nov 09, 2000 at 21:21 UTC
    I might do something like this:
    $letter = 'a'; @ct = qw{ 11 41 71 }; $forward{$letter} = [ @ct ]; ... # Build reverse hash foreach $letter (keys %forward) { foreach $ciphertext (@{$forward{$letter}}) { $reverse{$ciphertext} = $letter; } } print join(" ", @forward{split(//, "plaintext")}); print join("", @reverse{qw{ 19 59 71 75 77 63 13 66 33 }});
Try a list of list refs.
by TGI (Parson) on Nov 10, 2000 at 00:56 UTC

    For the cyphertest lookup try using the indexes of your arrays as keys. This should be speedy and cheaper from a memory standpoint.

    Split your cyphertext 'letters' into two digits. Then create a list of list references.Something like this:

    @ct[2,5,8]=['d', 'j', 'f', 'b', 'g', 'q', 'k', 's', 'r', 'l']; print $ct[2][3]; # Should print b.

    Warning:code untested as all get out.

Re: Kiddie Codes
by HaB (Sexton) on Nov 09, 2000 at 21:19 UTC
    Minor correction: In the example above, a plaintext 'b' would become ciphertext 23, 53 or 83, NOT 52. My apologies.