Welcome to the Monastery PerlMonks

### Kiddie Codes

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

Thanks!

HaB

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
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.

-Ted
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.

-HaB

Create A New User
Node Status?
node history
Node Type: perlquestion [id://40747]
Approved by root
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (6)
As of 2018-04-21 01:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (81 votes). Check out past polls.

Notices?