Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

Kiddie Codes

by HaB (Sexton)
on Nov 09, 2000 at 21:15 UTC ( [id://40747]=perlquestion: print w/replies, xml ) Need Help??

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:

  • You take a key word, having as many non-repeating letters as possible. We'll use 'exchampion' for our example.
  • You write out that keyword, followed by the remaining letters in the alphabet in order, using columns of 10 letters, like so:
------------------- 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.
  • Then, rearrange the columns in alpha order according to the topmost letter, and number them:
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
  • Finally, number the rows from 1 to 9 vertically, 3 numbers on each row, like so:
  • 1 2 3 4 5 6 7 8 9 0 |--------------------- 1,4,7 | a c e h i m n o p x 2,5,8 | j f b g q k s r l d 3,6,9 | y w t w ! z , ? . u
    Now our table is complete. The way to use it find the plaintext letter you want to encrypt, the ciphertext then becomes a two number set made of a randomly selected row number for that row, and the column number. So, plaintext 'a' becomes ciphertext 11, 41 or 71, 'b' becomes 23, 52, or 83, etc, etc.

    I can figure out ways to generate the table, given a user supplied keyword, but I'm wondering what the best way to store it so it can easily be looked up against? My initial impression is to use 2 hashes, one with the plaintext as keys, the values of which are an array containing each of the 3 possible ciphertext values, and the other being the opposite, but is there a more elegant solution? Some way to store a matrix of data like that that I'm not thinking of?



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.


Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://40747]
Approved by root
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-06-21 21:25 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.