CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

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

 



Larkdog
User

Oct 30, 2004, 8:41 AM

Post #1 of 21 (4057 views)
converting letters to corresponding numbers Can't Post

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

Post #2 of 21 (4053 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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);

print header;

#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

Post #3 of 21 (4051 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #4 of 21 (4050 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #5 of 21 (4048 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

this may help you:


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

Post #6 of 21 (4043 views)
Re: [KevinR] converting letters to corresponding numbers [In reply to] Can't Post

ok, a little teaching please

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

Post #7 of 21 (4040 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #8 of 21 (4038 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #9 of 21 (4036 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post


In Reply To
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. Smile
-------------------------------------------------


Larkdog
User

Oct 30, 2004, 3:29 PM

Post #10 of 21 (4033 views)
Re: [KevinR] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #11 of 21 (4023 views)
Re: [KevinR] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #12 of 21 (4015 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #13 of 21 (4007 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #14 of 21 (4005 views)
Re: [KevinR] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #15 of 21 (4002 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post


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

Post #16 of 21 (4001 views)
Re: [davorg] converting letters to corresponding numbers [In reply to] Can't Post

much thanks for all the help KevinRWink

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

Post #17 of 21 (3998 views)
Re: [KevinR] converting letters to corresponding numbers [In reply to] Can't Post


In Reply To
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

Post #18 of 21 (3997 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post

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

Post #19 of 21 (3995 views)
Re: [davorg] converting letters to corresponding numbers [In reply to] Can't Post


In Reply To

In Reply To
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

Post #20 of 21 (3994 views)
Re: [davorg] converting letters to corresponding numbers [In reply to] Can't Post


In Reply To
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. Smile
-------------------------------------------------


KevinR
Veteran


Nov 1, 2004, 6:19 PM

Post #21 of 21 (3992 views)
Re: [Larkdog] converting letters to corresponding numbers [In reply to] Can't Post


In Reply To
much thanks for all the help KevinRWink

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!


You're very welcome. I think you did an awesome job of it.

PS: don't feel bad when you look at Daves code, I think Dave is actually an alien from some faraway and much advanced planet in another Galaxy. He can write in two lines of code what takes most of us Earthlings 20 lines or more. Wink
-------------------------------------------------

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives