Home: Perl Programming Help: Beginner:
converting letters to corresponding numbers

Larkdog
User

Oct 30, 2004, 8:41 AM

Views: 11681
 converting letters to corresponding numbers
i am working on a larger project...but what i need to know is pretty simple.

how would i take a message (\$data{message}) and convert it to numbers corresponding to the following system: a=1, b=2, c=3,...z=26, space=27, '.'=28, '?'=29

i think you could use a switch, but how would i define my correspondence system to later call from?
www.MrLarkins.com

(This post was
edited by Larkdog on Oct 30, 2004, 11:04 AM)

Larkdog
User

Oct 30, 2004, 11:08 AM

Views: 11677
 Re: [Larkdog] converting letters to corresponding numbers
well, i figured out how to define my correlation using the hash...

this is what i have so far:

#!/usr/bin/perl

use warnings;

use CGI ':cgi';

use CGI::Carp qw(fatalsToBrowser);

#defines my correlation system

my %code = (

a => 1, b => 2, c => 3, d => 4, e => 5, f => 6, g => 7, h => 8, i => 9,

j => 10, k => 11, l => 12, m => 13, n => 14, o => 15, p => 16, q => 17,

r => 18, s => 19, t => 20, u => 21, v => 22, w => 23, x => 24, y => 25,

z => 26, '+' => 27, '.' => 28, '?' => 29

);

#uses the param function to define user input from a webform

my %data;

\$data{\$_} = param(\$_) for qw(message);

#seperate user string to array

@text = split(//,\$data{message});

#switch user input to corresponding numbers

now i need to use s/// to replace the letters in my array with the appropriate numbers in my %code, not sure yet as to how this will be done. still learning!

www.MrLarkins.com

Larkdog
User

Oct 30, 2004, 1:24 PM

Views: 11675
 Re: [Larkdog] converting letters to corresponding numbers
well, i have been working real hard and getting almost nowhere...but i am learning a whole lot.

i couldn't figure out how to use my defined hash, so i have tried it this way:

 Code
`   #!/usr/bin/perl  use strict;  use warnings;  use CGI ':cgi';  use CGI::Carp qw(fatalsToBrowser);  print header;  #uses the param function to define user input from a webform  my %data;  \$data{\$_} = param(\$_) for qw(message);  #seperate user string to array  my @message;  @message = split(//,\$data{message});  \$data{message} =~ s/a/1/g;  \$data{message} =~ s/b/2/g;  \$data{message} =~ s/c/3/g;  \$data{message} =~ s/d/4/g;  \$data{message} =~ s/e/5/g;  \$data{message} =~ s/f/6/g;  \$data{message} =~ s/g/7/g;  \$data{message} =~ s/h/8/g;  \$data{message} =~ s/i/9/g;  \$data{message} =~ s/j/10/g;  \$data{message} =~ s/k/11/g;  \$data{message} =~ s/l/12/g;  \$data{message} =~ s/m/13/g;  \$data{message} =~ s/n/14/g;  \$data{message} =~ s/o/15/g;  \$data{message} =~ s/p/16/g;  \$data{message} =~ s/q/17/g;  \$data{message} =~ s/r/18/g;  \$data{message} =~ s/s/19/g;  \$data{message} =~ s/t/20/g;  \$data{message} =~ s/u/21/g;  \$data{message} =~ s/v/22/g;  \$data{message} =~ s/w/23/g;  \$data{message} =~ s/x/24/g;  \$data{message} =~ s/y/25/g;  \$data{message} =~ s/z/26/g;  \$data{message} =~ s/\s/27/g;  \$data{message} =~ s/\./28/g;  \$data{message} =~ s/\?/29/g;  print "\$data{message}\n";  print "@message";       `

the first print displays the numbers, but they are all bunched up

the second print displays the letters, but they are spaced out

what i would like is to have the numbers spaced out!

i tried to do something like

@message =~ s/t/20/g;

but it tells me "can't modify private array" which i assume means that i can't search and replace in an array.
www.MrLarkins.com

Larkdog
User

Oct 30, 2004, 1:34 PM

Views: 11674
 Re: [Larkdog] converting letters to corresponding numbers
well, it seems that i have created a 'trick' to fix my problem

 Code
`      #!/usr/bin/perl    use strict;    use warnings;    use CGI ':cgi';    use CGI::Carp qw(fatalsToBrowser);    print header;    #uses the param function to define user input from a webform    my %data;    \$data{\$_} = param(\$_) for qw(message);    \$data{message} =~ s/a/1_/g;    \$data{message} =~ s/b/2_/g;    \$data{message} =~ s/c/3_/g;    \$data{message} =~ s/d/4_/g;    \$data{message} =~ s/e/5_/g;    \$data{message} =~ s/f/6_/g;    \$data{message} =~ s/g/7_/g;    \$data{message} =~ s/h/8_/g;    \$data{message} =~ s/i/9_/g;    \$data{message} =~ s/j/10_/g;    \$data{message} =~ s/k/11_/g;    \$data{message} =~ s/l/12_/g;    \$data{message} =~ s/m/13_/g;    \$data{message} =~ s/n/14_/g;    \$data{message} =~ s/o/15_/g;    \$data{message} =~ s/p/16_/g;    \$data{message} =~ s/q/17_/g;    \$data{message} =~ s/r/18_/g;    \$data{message} =~ s/s/19_/g;    \$data{message} =~ s/t/20_/g;    \$data{message} =~ s/u/21_/g;    \$data{message} =~ s/v/22_/g;    \$data{message} =~ s/w/23_/g;    \$data{message} =~ s/x/24_/g;    \$data{message} =~ s/y/25_/g;    \$data{message} =~ s/z/26_/g;    \$data{message} =~ s/\s/27_/g;    \$data{message} =~ s/\./28_/g;    \$data{message} =~ s/\?/29_/g;    #seperate user string to array    my @message;    @message = split(/_/,\$data{message});         print "\$data{message}\n";    print "@message";          `

my next question is about the '?', the '.' works correctly,

but the '?' throws everything into an uproar.

it must be a special character in perl, and i thought that by

using a backslash i could escape it, but it didn't work? any ideas?
www.MrLarkins.com

(This post was
edited by Larkdog on Oct 30, 2004, 1:37 PM)

KevinR
Veteran

Oct 30, 2004, 1:44 PM

Views: 11672
 Re: [Larkdog] converting letters to corresponding numbers

 Code
`#!/perl/bin/perl.exe use strict; use CGI; use CGI::Carp qw(fatalsToBrowser);  my %code_hash = (    a => 1, b => 2, c => 3, d => 4, e => 5, f => 6, g => 7, h => 8, i => 9,    j => 10, k => 11, l => 12, m => 13, n => 14, o => 15, p => 16, q => 17,    r => 18, s => 19, t => 20, u => 21, v => 22, w => 23, x => 24, y => 25,    z => 26, '+' => 27, '.' => 28, '?' => 29 );  my \$q = new CGI; print \$q->header;  #my \$message = \$q->param('message')  my \$message = "this is a test. To see what happens"; my @message = &encode(\$message); print "@message";   sub encode {    my \$message = shift;    \$message = lc \$message; #convert to all lower case    \$message =~ s/[^a-zA-Z\.\?\s]//g; #get rid of unwanted characters    \$message =~ s/\s+/\+/g; #substitute + for spaces    my @temp = split(//,\$message); #split characters into @temp array    s/\Q\$_\E/\$code_hash{\$_}/gi for @temp; #convert message to code    return(@temp); #return results }`

note this line:

s/\Q\$_\E/\$code_hash{\$_}/gi for @temp;

\Q...\E escapes all meta characters in the string being evaluated by the regexp. Metacharaters, such "?", have special meaning and Perl will try and use the special meaning if the charater is not escaped.
-------------------------------------------------

(This post was edited by KevinR on Oct 30, 2004, 1:50 PM)

Larkdog
User

Oct 30, 2004, 2:27 PM

Views: 11667
 Re: [KevinR] converting letters to corresponding numbers

1] what does the 'shift' actually do?

2] i have trouble understanding this part: [^a-zA-Z\.\?\s]

3] why replace spaces with a + ?

4] /g means global, what is /gi ?
www.MrLarkins.com

Larkdog
User

Oct 30, 2004, 2:55 PM

Views: 11664
 Re: [Larkdog] converting letters to corresponding numbers
i got to thinkin (i went and took a shower), and i think i might know the answer to my second question. tell me if this is right:

a-zA-Z\.\? means all the characters in the hash_code and the '^' means 'not', and because i have no control over the user input (and the fact that there are way more characters available than are in the hash code), the s/[^a-zA-Z\.\?\s]//gi searches out all characters that i dont accept and in essence deletes them.

is that right?
www.MrLarkins.com

(This post was
edited by Larkdog on Oct 30, 2004, 2:56 PM)

KevinR
Veteran

Oct 30, 2004, 3:08 PM

Views: 11662
 Re: [Larkdog] converting letters to corresponding numbers
1] what does the 'shift' actually do?

shift is used to remove the first element of an array:

@animals = ('dog','cat','fish');
\$animal = shift(@animals);
print \$animal;

prints: dog

when we passed \$message to the subroutine:

my @message = &encode(\$message);

its passed in the system array: @_

to get the data back into a scalar in the subroutine I used shift since there is only one element in the system array at that time (\$message) the entire string gets put back into \$message and is ready for further processing. Its a pretty standard way of passing data to and from subroutines.

2] i have trouble understanding this part: [^a-zA-Z\.\?\s]

I am using a character class ([]) to tell the regexp to remove all characters from the string; except (^) the ones in the charater class. So by deafualt everything is removed except the charaters you want. If someone enters anything other than those characters in your form, they will be removed since they will not be encoded according to your rules. You want only a-z, space, dot, question mark.

3] why replace spaces with a + ?

because we can't define a hash key using just a space, at least I don't think so, you can't have:

z => 26,
' ' => 27,
'.' => 28,

the + symbol is the standard symbol for spaces anyway in URI encoded srings so it makes sense to me to use it.

4] /g means global, what is /gi ?

i means case insensitive, it really doesn't have to be there since the string was converted to all lower case before it gets to that part of the script. It could be like this:

\$message =~ s/[^a-z\.\?\s]//g;
-------------------------------------------------

(This post was edited by KevinR on Oct 30, 2004, 3:10 PM)

KevinR
Veteran

Oct 30, 2004, 3:14 PM

Views: 11660
 Re: [Larkdog] converting letters to corresponding numbers
i got to thinkin (i went and took a shower), and i think i might know the answer to my second question. tell me if this is right:

a-zA-Z\.\? means all the characters in the hash_code and the '^' means 'not', and because i have no control over the user input (and the fact that there are way more characters available than are in the hash code), the s/[^a-zA-Z\.\?\s]//gi searches out all characters that i dont accept and in essence deletes them.

is that right?

Yes, exactly.
-------------------------------------------------

Larkdog
User

Oct 30, 2004, 3:29 PM

Views: 11657
 Re: [KevinR] converting letters to corresponding numbers
ok those make sense now, thanks...i guess that ends my questions about converting letters to corresponding numbers.
www.MrLarkins.com

Larkdog
User

Nov 1, 2004, 7:51 AM

Views: 11647
 Re: [KevinR] converting letters to corresponding numbers
well, i tried to reuse the %code_hash to convert the numbers back to numbers...but to no avail...so i created the following:

 Code
`  my %decode_hash = (1 => a, 2 => b, 3 => c, 4 =>d, 5 => e, 6 => f, 7 => g, 8 => h,9 => i, 10 => j, 11 => k, 12 => l, 13 => m, 14 => n, 15 => o,16 => p, 17 => q, 18 => r, 19 => s, 20 => t, 21 => u, 22 => v,23 => w, 24 => x, 25 => y, 26 => z, 27 => '+', 28 => '.', 29 => '?');`

well, you can see that i just reversed the assignments. then i tryed this subroutine:

 Code
`  sub decode {s/\$_/\$decode_hash{\$_}/gi for @coded_message;return (@coded_message);}`

but i keep getting a syntax error saying near 'm, 14 => n, 15'

grr, i have tried to fix the post so it wasn't so long, but it keeps making it long, sorry, nothig i can do
www.MrLarkins.com

(This post was
edited by Larkdog on Nov 1, 2004, 8:57 AM)

Larkdog
User

Nov 1, 2004, 9:08 AM

Views: 11639
 Re: [Larkdog] converting letters to corresponding numbers
well, i thought that maybe there was a conflit between the \$_ of the %decode_hash and my \$n and \$p that i was using elsewhere, so i renamed \$n to \$n1 and \$p to \$p1...but i am still getting the error.
www.MrLarkins.com

KevinR
Veteran

Nov 1, 2004, 10:45 AM

Views: 11631
 Re: [Larkdog] converting letters to corresponding numbers
We didn't use quotes in the first hash because digits do not need to be quoted, but alpha characters do, so just add single quotes around all your alpha characters:

1 => 'a', 2 => 'b', etc etc etc
-------------------------------------------------

Larkdog
User

Nov 1, 2004, 10:53 AM

Views: 11629
 Re: [KevinR] converting letters to corresponding numbers
ok, so that is why in the first one, it was '+', '?', and '.'

i do have a problem with the translation of ? to 29

it doesn't do it.
www.MrLarkins.com

(This post was
edited by Larkdog on Nov 1, 2004, 10:55 AM)

davorg
Thaumaturge / Moderator

Nov 1, 2004, 11:36 AM

Views: 11626
 Re: [Larkdog] converting letters to corresponding numbers
 Code
`#!/usr/bin/perl                                                                                  use strict; use warnings;                                                                                  my \$message = 'the quick brown fox jumps over the lazy dog.';                                                                                  my @chars = ('a' .. 'z', ' ', '.', '?'); my %chars = map { \$chars[\$_] => \$_ + 1 } 0 .. \$#chars;                                                                                  \$message =~ s/(.)/\$chars{\$1}/g;                                                                                  print \$message;`

But there's a fundamental flaw in your encryption algorithm. It's impossible to unencrypt it. If, for example, there is the sequence '12' in an encrypted message it's impossible to know if that's a 12 ('l') or a 1 followed by a 1 ('ab').

You should probably enforce two digits for each character.
 Code
`my %chars = map { \$chars[\$_] => sprintf '%02d', \$_ + 1 } 0 .. \$#chars;`

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks

Larkdog
User

Nov 1, 2004, 12:34 PM

Views: 11625
 Re: [davorg] converting letters to corresponding numbers
much thanks for all the help KevinR

i teach high school math and we were learning matrices. well, in class, we used matrices to encrypt and decode messages. well, i thought it would be cool to provide this on my website using the same process...and finally my hard work (and kevinR's) have paid off...i fixed the bugs and it runs flawlessly!

check it out ==> http://www.mrlarkins.com/cryptology.html

kevin, i am posting my/our code for the encrypt.pl file (the decode.pl is similar)

 Code
`      #!/perl/bin/perl    use strict;     use CGI;     use CGI::Carp qw(fatalsToBrowser);     my %code_hash = (     a => 1, b => 2, c => 3, d => 4, e => 5, f => 6, g => 7, h => 8, i => 9, j => 10, k => 11, l => 12, m => 13, n => 14, o => 15, p => 16, q => 17, r => 18, s => 19, t => 20, u => 21, v => 22, w => 23, x => 24, y => 25, z => 26, '+' => 27, '.' => 28, '?' => 29, '_' => 27);     my %decode_hash = (    1 => 'a', 2 => 'b', 3 => 'c', 4 => 'd', 5 => 'e', 6 => 'f', 7 => 'g', 8 => 'h', 9 => 'i', 10 => 'j', 11 => 'k', 12 => 'l', 13 => 'm', 14 => 'n', 15 => 'o', 16 => 'p', 17 => 'q', 18 => 'r', 19 => 's', 20 => 't', 21 => 'u', 22 => 'v', 23 => 'w', 24 => 'x', 25 => 'y', 26 => 'z', 27 => '_', 28 => '.', 29 => '?');    my \$q1 = new CGI;    print \$q1->header;    my \$message = \$q1->param('message');    my @message = &encode(\$message);     sub encode {     my \$message = shift;    \$message = lc \$message; #convert to all lower case     \$message =~ s/[^a-zA-Z\.\?\s]//g; #get rid of unwanted characters     \$message =~ s/\s+/\+/g; #substitute + for spaces     my @temp = split(//,\$message); #split characters into @temp array     s/\Q\$_\E/\$code_hash{\$_}/gi for @temp; #convert message to code     return(@temp); #return results     }    my \$count;    my \$remainder;    \$count = @message;    \$remainder = \$count % 3;    while (\$remainder == 1 || \$remainder == 2) {    push @message,'27';    \$count = @message;    \$remainder = \$count % 3;    };    my @code;    @code = (0,1,0,1,1,0,1,0,1);    my \$n1;    my \$p1;    my @coded_message;    \$n1 = 0;    \$p1 = 0;    until (\$n1 == \$count){        \$coded_message[\$p1] = (\$code[0] * \$message[\$n1++]) + (\$code[1] * \$message[\$n1++]) + (\$code[2] * \$message[\$n1++]);    \$p1+=3;    }    \$n1 = 0;    \$p1 = 1;    until (\$n1 == \$count){    \$coded_message[\$p1] = (\$code[3] * \$message[\$n1++]) + (\$code[4] * \$message[\$n1++]) + (\$code[5] * \$message[\$n1++]);    \$p1+=3;    }    \$n1 = 0;    \$p1 = 2;    until (\$n1 == \$count){    \$coded_message[\$p1] = (\$code[6] * \$message[\$n1++]) + (\$code[7] * \$message[\$n1++]) + (\$code[8] * \$message[\$n1++]);    \$p1+=3;    }    \$n1 = 0;    until (\$n1 == \$count) {    until (\$coded_message[\$n1] < 30){    \$coded_message[\$n1] = \$coded_message[\$n1] - 29;    }    \$n1++;    }    \$n1 = 0;    until (\$n1 == \$count) {    until (\$coded_message[\$n1] > 0) {    \$coded_message[\$n1] = \$coded_message[\$n1] + 29;    }    \$n1++;    }        @coded_message = &decode(@coded_message);    sub decode {    s/\Q\$_\E/\$decode_hash{\$_}/gi for @coded_message;        return (@coded_message);    }    print <<EOF    <HTML>    <HEAD>    <TITLE>Encrypted Message!</TITLE>    </HEAD>    <BODY><center>    <H1>Your message has been encrypted\!</H1>    <p>Your message has been successfully encrypted.<BR><font color=orange size=4><b>@coded_message</b></font></p></center>    </BODY>    </HTML>    EOF`
www.MrLarkins.com

(This post was
edited by Larkdog on Nov 1, 2004, 12:38 PM)

davorg
Thaumaturge / Moderator

Nov 1, 2004, 12:54 PM

Views: 11622
 Re: [KevinR] converting letters to corresponding numbers
because we can't define a hash key using just a space, at least I don't think so, you can't have:

z => 26,
' ' => 27,
'.' => 28,

There's no reason why you can't have a space as a hash key.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks

davorg
Thaumaturge / Moderator

Nov 1, 2004, 1:59 PM

Views: 11621
 Re: [Larkdog] converting letters to corresponding numbers
You might find this version a little easier to follow:

 Code
`#!/usr/bin/perl      use strict;    use warnings;    use CGI ':standard'; use CGI::Carp qw(fatalsToBrowser);       my @chars = ('a' .. 'z', ' ', '.', '?'); my %code_hash = map { \$chars[\$_] => \$_ + 1 } 0 .. \$#chars; my %decode_hash = reverse %code_hash;    print header;      my @message = encode(param('message'));       while (@message % 3) {   push @message, '27'; };  my @code = (0,1,0,1,1,0,1,0,1);  my @coded_message;  foreach my \$p1 (0 .. 2) {   my \$n1 = 0;   my @index = (\$p1 * 3, \$p1 * 3 + 1, \$p1 * 3 + 2);    until (\$n1 == @message) {     \$coded_message[\$p1] = (\$code[\$index[0]] * \$message[\$n1++])                         + (\$code[\$index[1]] * \$message[\$n1++])                         + (\$code[\$index[2]] * \$message[\$n1++]);     \$p1 += 3;   } }  foreach my \$n1 (0 .. \$#message) {   until (\$coded_message[\$n1] < 30) {     \$coded_message[\$n1] = \$coded_message[\$n1] - 29;   }    until (\$coded_message[\$n1] > 0) {     \$coded_message[\$n1] = \$coded_message[\$n1] + 29;   } }   @coded_message = decode(@coded_message);  print <<EOF;  <html>     <head>     <title>Encrypted Message!</title>   </head>   <body>     <center>       <h1>Your message has been encrypted!</h1>       <p>Your message has been successfully encrypted.<br />       <font color=orange size=4><b>@coded_message</b></font></p>     </center>   </body> </html>   EOF  sub encode {      my \$message = shift;      \$message = lc \$message; #convert to all lower case   \$message =~ s/[^a-zA-Z\.\? ]//g; #get rid of unwanted characters      my @temp = split(//, \$message); #split characters into @temp array         s/\Q\$_\E/\$code_hash{\$_}/gi for @temp; #convert message to code    return @temp; #return results    }  sub decode {   my @msg = @_;   s/\Q\$_\E/\$decode_hash{\$_}/gi for @msg;      return (@msg); }`

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks

KevinR
Veteran

Nov 1, 2004, 6:01 PM

Views: 11619
 Re: [davorg] converting letters to corresponding numbers
because we can't define a hash key using just a space, at least I don't think so, you can't have:

z => 26,
' ' => 27,
'.' => 28,

There's no reason why you can't have a space as a hash key.

Thanks Dave, I wasn't sure.
-------------------------------------------------

KevinR
Veteran

Nov 1, 2004, 6:10 PM

Views: 11618
 Re: [davorg] converting letters to corresponding numbers
You might find this version a little easier to follow:

Daves the man! I'm a bit flattered to see remnants of my code in the script you wipped up Dave.

Kudos to Mr. Larkin too.
-------------------------------------------------

KevinR
Veteran

Nov 1, 2004, 6:19 PM

Views: 11616
 Re: [Larkdog] converting letters to corresponding numbers