Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Kiddie Codes

by HaB (Sexton)
on Nov 09, 2000 at 21:15 UTC ( #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?



Comment on Kiddie Codes
Select or Download Code
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
Node Status?
node history
Node Type: perlquestion [id://40747]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (11)
As of 2016-05-24 17:04 GMT
Find Nodes?
    Voting Booth?