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:
Need help from you PERL masters

 



viclaster
Novice

Feb 24, 2005, 5:25 PM

Post #1 of 18 (1988 views)
Need help from you PERL masters Can't Post

I am writing a PERL code to create an array made up of a text file, then this code is supposed to generate 10000 account numbers and search the array for the numbers generated. I especially need help with the sub routine searchaccounts. Here is the code I have so far. Can anyone help?




Code
 #This script reads from the accounts.txt file and reads all data then calculates time to read the data 
#!/usr/bin/perl
use strict;# Call subroutine to load account data
# This is supposed to pull the array out of the sub routine below at the load data comments
loadaccounts(); # Generate a random list of accounts to search for
my @search_accounts = &randomAccounts();# Record the current time
my $start_time = time();# Search for accounts
my @foundIndeces = searchAccounts( @accounts, @search_accounts );# Display elapsed time
print "Time to find accounts: ";
print time() - $start_time;
print "\n";# print all found accounts
foreach my $i (@foundIndeces)
{
print "Found: $accounts[$i]\n";
}

#####################################################################
# searchAccounts: searches for account numbers in an array
# Parameters: accounts (array of account numbers)
# search_array (of account numbers to look for accounts)
# Returns: array of indeces into accounts of found account numbers
#####################################################################
sub searchAccounts
{

}#####################################################################
# loadData:
#
#
#####################################################################
sub loadAccounts()
(
open(FILE,"account.txt") or die "$!";
my @accountsarray = <FILE>;
close(FILE); return@accountsarray;

}#####################################################################
# randomAccounts generates 10000 random account numbers
# Parameters: none
# Returns: Array of 10000 random account numbers
#####################################################################
sub randomAccounts()
{
my @search_accounts = ();
for (my $i = 0; $i < 10000; $i++)
{
$search_accounts[$i] = $accounts[int(rand $#accounts) + 1];
$search_accounts[$i] =~ s/([0-9-]{12})\t.*/$1/;
chomp($search_accounts[$i]);
}
return @search_accounts;
}



I get the following errors when I try to run. I know it's not finished but I thought the errors were probably a hint to something wrong as the code is so far. Any help will be greatly appreciated.

Global symbol "@accounts" requires explicit package name at perlcode3.pl line 18.
Global symbol "@accounts" requires explicit package name at perlcode3.pl line 28.
Illegal declaration of subroutine main::loadAccounts at perlcode3.pl line 48.


KevinR
Veteran


Feb 24, 2005, 9:50 PM

Post #2 of 18 (1982 views)
Re: [viclaster] Need help from you PERL masters [In reply to] Can't Post

When you use "strict" you have to declare (package) all variables. You have:


Code
my @foundIndeces = searchAccounts( @accounts, @search_accounts );


but @accounts has never been packaged, maybe you mean to do this earlier in the script:

my @accounts = loadAccounts();

but notice in your script you have:

loadaccounts();

but your sub routine uses an upper case A:

sub loadAccounts

so you have to change them to match.

You also have a syntax error here:


Code
sub loadAccounts()  
(


that should be:


Code
sub loadAccounts()  
{ <-- left curly bracket


I don't understand what you are trying to do here:

Code
sub randomAccounts()  
{
my @search_accounts = ();
for (my $i = 0; $i < 10000; $i++)
{
$search_accounts[$i] = $accounts[int(rand $#accounts) + 1];
$search_accounts[$i] =~ s/([0-9-]{12})\t.*/$1/;
chomp($search_accounts[$i]);
}
return @search_accounts;
}

-------------------------------------------------


viclaster
Novice

Feb 25, 2005, 2:31 PM

Post #3 of 18 (1973 views)
Re: [KevinR] Need help from you PERL masters [In reply to] Can't Post

"I don't understand what you are trying to do here:
sub randomAccounts()
{
my @search_accounts = ();
for (my $i = 0; $i < 10000; $i++)
{
$search_accounts[$i] = $accounts[int(rand $#accounts) + 1];
$search_accounts[$i] =~ s/([0-9-]{12})\t.*/$1/;
chomp($search_accounts[$i]);
}
return @search_accounts;
}"
This is supposed to generate 10000 account numbers. Then the code is supposed to search the account array and find any matches with the generated numbers.


KevinR
Veteran


Feb 25, 2005, 4:12 PM

Post #4 of 18 (1971 views)
Re: [viclaster] Need help from you PERL masters [In reply to] Can't Post

OK, I think I understand now. Its pulling a random element out of your array 1000 times that was made from your file account.txt.

Assuming your data is all generated correctly, you could use List::Compare to do the work but I don't think it's a standard perl module so you would have to install it yourself if you wanted to.

Or you could do something like this which could work but seems tedious:


Code
my @foundIndeces = searchAccounts( \@accounts, \@search_accounts ); 

print "$_\n" for @foundIndeces;

sub searchAccounts {
my ($accounts,$search_accounts) = @_;
my @temp = ();
for (@{$accounts}){
for my $i (0 .. $#{$search_accounts}){
push @temp , $_ if $_ == $search_accounts->[$i];
}
}
return (@temp);
}


you may have to change this:

$_ == $search_accounts->[$i] #numeric equality

to:

$_ =~ / ^$search_accounts->[$i]$/ #string equality
-------------------------------------------------


MrPJ
User

Feb 26, 2005, 4:54 PM

Post #5 of 18 (1957 views)
Re: [KevinR] Need help from you PERL masters [In reply to] Can't Post


Quote
$_ =~ / ^$search_accounts->[$i]$/ #string equality


Or even better, just:


Code
$_ eq $search_accounts->[$i]



KevinR
Veteran


Feb 26, 2005, 6:26 PM

Post #6 of 18 (1955 views)
Re: [MrPJ] Need help from you PERL masters [In reply to] Can't Post


In Reply To

Quote
$_ =~ / ^$search_accounts->[$i]$/ #string equality


Or even better, just:


Code
$_ eq $search_accounts->[$i]




Yes, you're right, for this application using "eq" would be better. Cool
-------------------------------------------------


viclaster
Novice

Feb 27, 2005, 7:13 PM

Post #7 of 18 (1948 views)
Re: [MrPJ] Need help from you PERL masters [In reply to] Can't Post

Okay I think you guys are real close on this one. I used your suggestions and now the code prints the time it takes to run the search. But it will not tell how many were found. Here is the code so far:




Code
 #This script reads from the accounts.txt file and reads all data then calculates time to read the data 
#!/usr/bin/perl
use strict; # Call subroutine to load account data
# This is supposed to pull the array out of the sub routine below at the load data comments
my @accounts = loadAccounts();



# Generate a random list of accounts to search for
# This is supposed to generate 10000 different account numbers
my @search_accounts = &randomAccounts();



# Record the current time
my $start_time = time();



# Search for accounts
my @foundIndeces = searchAccounts( \@accounts, \@search_accounts );



# Display elapsed time
print "Time to find accounts: ";
print time() - $start_time;
print "\n";



# print all found accounts
foreach my $i (@foundIndeces)
{
print "$_\n" for @foundIndeces;
}

#####################################################################
# searchAccounts: searches for account numbers in an array
# Parameters: accounts (array of account numbers)
# search_array (of account numbers to look for accounts)
# Returns: array of indeces into accounts of found account numbers
#####################################################################
sub searchAccounts {
my ($accounts,$search_accounts) = @_;
my @temp = ();
for (@{$accounts}){
for my $i (0 .. $#{$search_accounts}){
push @temp , $_ if $_ eq $search_accounts->[$i];
}
}
return (@temp);
}



#####################################################################
# loadData:
#
#
#####################################################################
sub loadAccounts()
{
open(FILE,"accounts.txt") or die "$!";
my @accountsarray = <FILE>;
close(FILE);
return@accountsarray;
}



#####################################################################
# randomAccounts generates 10000 random account numbers
# Parameters: none
# Returns: Array of 10000 random account numbers
#####################################################################
sub randomAccounts()
{
my @search_accounts = ();
for (my $i = 0; $i < 10000; $i++)
{
$search_accounts[$i] = $accounts[int(rand $#accounts) + 1];
$search_accounts[$i] =~ s/([0-9-]{12})\t.*/$1/;
chomp($search_accounts[$i]);
}
return @search_accounts;
}



KevinR
Veteran


Feb 27, 2005, 8:31 PM

Post #8 of 18 (1944 views)
Re: [viclaster] Need help from you PERL masters [In reply to] Can't Post

without knowing if you are getting all the data you need to get the results you are looking for, I would say this part where you want to print the results:


Code
# print all found accounts  
foreach my $i (@foundIndeces)
{
print "$_\n" for @foundIndeces;
}


would be better written as:


Code
print "$_\n" for @foundIndeces;


hopefully thats all you need to do. Smile

but there is a possibility that the line where you are comparing the two arrays needs to be changed:


Code
push @temp , $_ if $_ eq $search_accounts->[$i];


since we do not know what data you are actually comparing, you may need to use:


Code
$_ eq $search_accounts->[$i]


or


Code
$_ == $search_accounts->[$i]


or maybe:


Code
$_ =~ /$search_accounts->[$i]/

-------------------------------------------------


viclaster
Novice

Feb 28, 2005, 6:56 PM

Post #9 of 18 (1910 views)
Re: [KevinR] Need help from you PERL masters [In reply to] Can't Post

Thanks Kevin but now when I run the program it freezes my command prompt. Here is the code:


Code
 #!/usr/bin/perl 
use strict; # Call subroutine to load account data
# This is supposed to pull the array out of the sub routine below at the load data comments
my @accounts = loadAccounts();



# Generate a random list of accounts to search for
# This is supposed to generate 10000 different account numbers
my @search_accounts = &randomAccounts();



# Record the current time
my $start_time = time();



# Search for accounts
my @foundIndeces = searchAccounts( \@accounts, \@search_accounts );



# Display elapsed time
print "Time to find accounts: ";
print time() - $start_time;
print "\n";



# print all found accounts
print "$_\n" for @foundIndeces;




#####################################################################
# searchAccounts: searches for account numbers in an array
# Parameters: accounts (array of account numbers)
# search_array (of account numbers to look for accounts)
# Returns: array of indeces into accounts of found account numbers
#####################################################################
sub searchAccounts {
my ($accounts,$search_accounts) = @_;
my @temp = ();
for (@{$accounts}){
for my $i (0 .. $#{$search_accounts}){
push @temp , $_ if $_ =~ /$search_accounts->[$i]/;
}
}
return (@temp);
}



#####################################################################
# loadData:
#
#
#####################################################################
sub loadAccounts()
{
open(FILE,"accounts.txt") or die "$!";
my @accountsarray = <FILE>;
close(FILE);
return@accountsarray;
}



#####################################################################
# randomAccounts generates 10000 random account numbers
# Parameters: none
# Returns: Array of 10000 random account numbers
#####################################################################
sub randomAccounts()
{
my @search_accounts = ();
for (my $i = 0; $i < 10000; $i++)
{
$search_accounts[$i] = $accounts[int(rand $#accounts) + 1];
$search_accounts[$i] =~ s/([0-9-]{12})\t.*/$1/;
chomp($search_accounts[$i]);
}
return @search_accounts;
}



KevinR
Veteran


Feb 28, 2005, 10:05 PM

Post #10 of 18 (1902 views)
Re: [viclaster] Need help from you PERL masters [In reply to] Can't Post

Try changing this line:

my @accounts = loadAccounts();

to this:

my @accounts = &loadAccounts();

I get a warning message with the first line above:

main::loadAccounts called too early to check prototype line 4

Honestly I am not sure what that means.
-------------------------------------------------


viclaster
Novice

Mar 1, 2005, 6:20 PM

Post #11 of 18 (1880 views)
Re: [KevinR] Need help from you PERL masters [In reply to] Can't Post

I changed

my @accounts = loadAccounts();

to:

my @accounts = &loadAccounts();



I just get an ongoing printout of account numbers. It still doesn't work as intended. hehe, this is a tough one. Thanks for all of your help so far.


KevinR
Veteran


Mar 1, 2005, 8:27 PM

Post #12 of 18 (1876 views)
Re: [viclaster] Need help from you PERL masters [In reply to] Can't Post

I think thats as much help as I can give without seeing some sample lines of actual data you are working with.
-------------------------------------------------


viclaster
Novice

Mar 2, 2005, 1:52 PM

Post #13 of 18 (1871 views)
Re: [KevinR] Need help from you PERL masters [In reply to] Can't Post

You're right. I completely forgot. This is the format that the account.txt file is in:



399-477714-6 $192.62
366-862974-6 $2881.73
263-981472-2 $4021.16
489-943747-4 $8388.53
756-676775-3 $6326.68
681-335226-8 $3387.55
684-485476-6 $5400.37
682-447536-7 $418.76
253-972157-5 $3677.94
634-135853-8 $5260.13
722-848571-2 $3993.13
398-563513-9 $1003.28
124-112748-7 $1217.18
815-296733-8 $1053.64
856-253442-2 $3601.78
697-367541-4 $7191.86
212-462426-4 $8628.49
278-979547-9 $7232.57
333-155154-1 $8677.69
748-323355-5 $2342.16
515-757131-2 $8830.19
542-294411-5 $7837.76
526-736826-9 $8740.33
712-718854-1 $4586.66
978-386418-8 $9044.15
197-897712-5 $2212.91
281-277175-9 $6475.66
674-379724-5 $1417.21
274-416745-8 $6944.24
598-479148-2 $2141.97
767-178933-3 $8589.49
189-248574-1 $8189.26
342-585473-6 $3482.86
268-257629-3 $8677.26
676-558413-9 $3481.37
215-553549-6 $3367.85
781-229439-3 $8927.99
758-521572-7 $4008.19
547-765552-7 $4798.83
173-158926-7 $8323.34
726-183438-5 $3689.85
762-515976-2 $8638.92
551-983638-2 $4924.72
531-453931-8 $4492.37
591-693216-7 $497.88

At least a few hundred lines like this.


davorg
Thaumaturge / Moderator

Mar 3, 2005, 4:54 AM

Post #14 of 18 (1862 views)
Re: [KevinR] Need help from you PERL masters [In reply to] Can't Post


In Reply To
Try changing this line:

my @accounts = loadAccounts();

to this:

my @accounts = &loadAccounts();

I get a warning message with the first line above:

main::loadAccounts called too early to check prototype line 4

Honestly I am not sure what that means.


Did you try looking for the error message in perldiag?

It means that loadAccounts has a prototype but Perl hasn't yet seen the the defnition of the function so it can't know what the prototype is.

The best fix is probably to remove the prototype from all of the subroutines. Prototypes in Perl are bet avoided unless you are trying to do something that you can't do without them.

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


KevinR
Veteran


Mar 3, 2005, 7:15 AM

Post #15 of 18 (1861 views)
Re: [davorg] Need help from you PERL masters [In reply to] Can't Post

No Dave, I'll go to the back of the class... Blush

Actually I had forgotten all about that valuable resource, thanks for posting the link I have it bookmarked now for future reference. Smile
-------------------------------------------------


KevinR
Veteran


Mar 3, 2005, 7:37 AM

Post #16 of 18 (1859 views)
Re: [viclaster] Need help from you PERL masters [In reply to] Can't Post

OK, I had a few minutes last night to go over the script.
For me it makes things easier to see actual data, I'm not as
good as others at working with theoretical data. Wink

Although I must admit I am not sure how practical your script is
or what the real purpose is. The random generation of 10,000
account numbers could potentially include many duplicates, it
depends on how many account numbers you have in the
accounts.txt file. If you are looking for the frequency of
matches the code would have tobe changed, if you are just
looking for a single match then this will work OK I think. I
changed the subroutine searchAccounts method after I
realized how inefficient the method was I had posted
previously. Anyway, see how this flies:



Code
#!perl 
use strict;
use warnings;

# This is supposed to pull the array out of the sub routine below at the load data comments
my @accounts = &loadAccounts();

# Generate a random list of accounts to search for
# This is supposed to generate 10000 different account numbers
my @search_accounts = &randomAccounts();

# Search for accounts
my @foundIndeces = &searchAccounts( \@accounts, \@search_accounts );
my $num = int @foundIndeces;

# Display elapsed time $^T stores the time the progam started
print 'Time to find accounts: ', time - $^T, " seconds\n";
print "Total number found: $num\n";
print "Account Numbers Found:\n";

# print all found accounts
print "$_\n" for (sort @foundIndeces);

#####################################################################
# searchAccounts: searches for account numbers in an array
# Parameters: accounts (array of account numbers)
# search_array (of account numbers to look for accounts)
# Returns: array of indeces into accounts of found account numbers
#####################################################################
#I used a hash (%search_accounts) here now to find matches

sub searchAccounts {
my ($accounts,$search_accounts) = @_;
my %search_accounts = ();
my %found_accounts = ();
$search_accounts{$_}=1 for (@{$search_accounts});#build the lookup hash
foreach (@{$accounts}) {
$found_accounts{$_}=1 if ( exists $search_accounts{$_});
}
return (keys %found_accounts); #we only need the keys
}



#####################################################################
# loadData:
#
#
#####################################################################
sub loadAccounts
{
open(FILE,"accounts.txt") or die "$!";
my @accountsarray = <FILE>;
close(FILE);
my @temp = map {(split(/\s+/))[0]} @accountsarray;
return @temp;
}

#####################################################################
# randomAccounts generates 10000 random account numbers
# Parameters: none
# Returns: Array of 10000 random account numbers
#####################################################################
sub randomAccounts
{
my @search_accounts = ();
for (my $i = 0; $i < 10000; $i++)
{
$search_accounts[$i] = $accounts[int(rand $#accounts) + 1];
#using split to get the account numbers instead of a regexp
$search_accounts[$i] = (split(/\s+/,$search_accounts[$i]))[0];
chomp($search_accounts[$i]);
}
return @search_accounts;
}

-------------------------------------------------


viclaster
Novice

Mar 4, 2005, 3:35 PM

Post #17 of 18 (1846 views)
Re: [KevinR] Need help from you PERL masters [In reply to] Can't Post

Thanks KevinR. I got the changes in place but now I get an error that says:

"Missing right curly or square bracket at perlcode3b.pl line 72, at end of line
syntax error at perlcode3b.pl line 72, at EOF
Execution of perlcode3b.pl aborted due to compilation errors."



Here is the code now:


Code
 #!/usr/bin/perl   
use strict;
use warnings;
# This is supposed to pull the array out of the sub routine below at the load data comments
my @accounts = &loadAccounts(); # Generate a random list of accounts to search for
# This is supposed to generate 10000 different account numbers
my @search_accounts = &randomAccounts();



# Search for accounts
my @foundIndeces = &searchAccounts( \@accounts, \@search_accounts );
my $num = int @foundIndeces;



# Display elapsed time $^T stores the time the progam started
print 'Time to find accounts: ', time - $^T, " seconds\n";
print "Total number found: $num\n";
print "Account Numbers Found:\n";



# print all found accounts
print "$_\n" for (sort @foundIndeces);
#####################################################################
# searchAccounts: searches for account numbers in an array
# Parameters: accounts (array of account numbers)
# search_array (of account numbers to look for accounts)
# Returns: array of indeces into accounts of found account numbers
#####################################################################
#I used a hash (%search_accounts) here now to find matches



sub searchAccounts
{
my ($accounts,$search_accounts) = @_;
my %search_accounts = ();
my %found_accounts = ();
$search_accounts{$_}=1 for (@{$search_accounts}); #build the lookup hash
foreach (@{$accounts})
{
$found_accounts{$_}=1 if ( exists $search_accounts{$_});
}
return (keys %found_accounts); #we only need the keys
}



#####################################################################
# loadData:
#
#
#####################################################################
sub loadAccounts
{
open(FILE,"accounts.txt") or die "$!";
my @accountsarray = <FILE>;
close(FILE);
my @temp = map {(split(/\s+/))[0]} @accountsarray;
return @temp;
}
#####################################################################
# randomAccounts generates 10000 random account numbers
# Parameters: none
# Returns: Array of 10000 random account numbers
#####################################################################
sub randomAccounts
{
my @search_accounts = ();
for (my $i = 0; $i < 10000; $i++)
{
$search_accounts[$i] = $accounts[int(rand $#accounts) + 1];
#using split to get the account numbers instead of a regexp
$search_accounts[$i] = (split(/\s+/,$search_accounts[$i]))[0];
chomp($search_accounts[$i]);
}
return @search_accounts;
}



KevinR
Veteran


Mar 4, 2005, 4:49 PM

Post #18 of 18 (1845 views)
Re: [viclaster] Need help from you PERL masters [In reply to] Can't Post

make sure the very first line of your script is fulshe with theleft margin, what you posted has a space:

#!/usr/bin/perl <-- first line


but that would not cause the error message you are getting. I don't see any errors in the code myslef. It runs fine for me.
-------------------------------------------------

 
 


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

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