Click to See Complete Forum and Search --> : How to speed up?


debiandude
06-05-2002, 09:20 AM
Does anyone see a way to speed this up. I was told it was a little slow. What it does it covert three letters into is numbers, ie, AAA is 1 AAB is 2, AZZ is 676, BAA is 677, etc. It also does the reverse of this to.
The boundary is ZZZ or 26^3

#!/usr/bin/perl -w
use strict;

my $data = uc shift @ARGV || exit(0);

if (($data =~ /^\d+$/) && $data <= 17576) { # 3 Numbers
my @array = (0, 'AAA'..'ZZZ');
print $array[$data], "\n";
} elsif ($data =~ /^[A-Z]{3}$/) { # 3 Letters
my %hash;
my $i = 1;
foreach ('AAA'..$data) {
$hash{$_} = $i++;
}
print $hash{$data}, "\n";
} else { # Something else
print "Three alpha/numeric characters only please!\n";
exit 0;
}

jemfinch
06-06-2002, 11:38 PM
I can't tell you how to do it in Perl, because I don't feel like looking up the syntax to substr, but you should use this algorithm:


import re

def lettersToNumber(s):
if not re.match(r'[A-Z][A-Z][A-Z]', s):
raise ValueError, "Argument must be string of three capital letters."
l = map(lambda c: ord(c)-65, s)
return (l[0]*676 + l[1]*26 + l[2])

def numberToLetters(i):
if i > 17575:
raise ValueError, "17575 is the highest representable number."
a = i/676
b = (i % 676) / 26
c = (i % 676 % 26)
return (chr(a+65) + chr(b+65) + chr(c+65))


That shouldn't be too hard to translate into Perl, if you insist on using it. The problem with your Perl program is that it uses way too much memory.

(Oh, and the boundary isn't 26**3, it's 26**3-1.)

Jeremy

[ 06 June 2002: Message edited by: jemfinch ]

debiandude
06-07-2002, 02:08 PM
What is this lambda function. Im quite unfamilar with it.

Also the bound is 26^3 becuase 0 is 0 and AAA is 1. If 17675 becomes the top then AAB is 1.

Also, it is not an option to write it in python becuase it does not exist on the sun production machines I am using, and they will not install it for one simple program.

bwkaz
06-07-2002, 03:07 PM
lambda in general is "an unnamed function" ( :cool: Lisp :cool: -- OK, sorry, I'm back now). It looks like he's using it there to convert from a character to the ASCII value to an int between 0 and 25 (inclusive).

In ASCII, A is 65, B is 66, etc., so subtracting 65 from the ASCII value of a character sets the range correctly.

(If AAA is indeed 1, then you'll still have to map A's to 0, but then you'll want to add 1 to the final integer).

jemfinch
06-08-2002, 01:49 PM
It's too bad Python isn't installed on those machines -- it provides much better tools for this. Does Perl even offer an easy way to iterate over strings? I can't remember.

Anyway, as bwkaz said, "lambda" makes an anonymous function -- a function with no name, created at runtime. The equivalent in Perl is "sub { BLOCK }", but unless Perl offers an easy way to iterate over strings (it doesn't seem that "map { BLOCK }" will do it) you won't be able to use the same method as I've used.

Really, it's rather inconsistent to have "0" be "0" and "AAA" be 1. What you're doing is basically just counting in base 26, with 'A' being 0. But bwkaz is again right on: you'll just take the output of the function and add 1 to it.

Jeremy

debiandude
06-08-2002, 11:02 PM
Thank you very much jeremy. I don't know why it didn't smack me in the face in the begining that I was just counting in base 26.

Anyway this is what I eneded up with. I improved the program so that I'm not limited to AAA or 17675, just in case they ever decied to use more than that for the Order ID nums. Thanks guys.


#!/usr/bin/perl -w
#
use strict;
$_ = uc shift @ARGV;

if(/^[A-Z]+$/) {
$_ = reverse;
my($result, $i) = 0;

while(/(\w)/g) {
$result += (ord $1)-65)*(26**$i++);
}

print ++$result, "\n";

} elsif (/^\d+$/) {

$_--;
my $result;

do {
$result .= chr(($_ % 26)+65);
} while(( $_ = int($_ / 26)));

$result = resverse $result;

print $result, "\n";

} else {

die "Incorrect syntax\n";

}

exit 0;



BTW, although you probably don't care since you left Perl a while ago, to traverse though a string you just need to a do a while match with the /g option.

[ 09 June 2002: Message edited by: debiandude ]