use strict;
use warnings;
use FindBin;
use lib $FindBin::Bin;
use genNumeros;
my #palabra;
open (my $ARCHIVO, '<', "palabras.txt") or warn ("No se encontro el archivo palabras.txt, $!");
while (my $palabra = <$ARCHIVO>) {
chomp $palabra;
push #palabra, $palabra;
}
close $ARCHIVO;
my $palabraAleatoria = $palabra[genNumeros::crearNumero()];
print"$palabraAleatoria";
<>;
The genNumeros module has this code:
package genNumeros;
use strict;
use warnings;
use Math::Complex;
my $seed = time();
my $a = $seed / 5;
my $c = $seed - 7;
my $x = $seed;
my $m = sqrt($seed % 574) + $seed;
my $numAleatorio;
sub generadorMultiplicativo{
$numAleatorio = ((($a*$x) + $c) % $m);
$x = $numAleatorio;
}
my $letra;
my $residuo;
sub crearNumero{
generadorMultiplicativo();
$residuo = $x/$m;
if($residuo < 0.0384615384615385){
$letra = 1;
}
if($residuo > 0.0384615384615385 && $residuo < 0.076923076923077){
$letra = 2;
}
if($residuo > 0.076923076923077 && $residuo < 0.1153846153846154){
$letra = 3;
}
if($residuo > 0.1153846153846154 && $residuo < 0.1538461538461538){
$letra = 4;
}
if($residuo > 0.1538461538461538 && $residuo < 0.1923076923076923){
$letra = 5;
}
if($residuo > 0.1923076923076923 && $residuo < 0.2307692307692308){
$letra = 6;
}
if($residuo > 0.2307692307692308 && $residuo < 0.2692307692307692){
$letra = 7;
}
if($residuo > 0.2692307692307692 && $residuo < 0.3076923076923077 ){
$letra = 8;
}
if($residuo > 0.3076923076923077 && $residuo < 0.3461538461538462){
$letra = 9;
}
if($residuo > 0.3461538461538462 && $residuo < 0.3846153846153846){
$letra = 10;
}
if($residuo > 0.3846153846153846 && $residuo < 0.4230769230769231){
$letra = 11;
}
if($residuo > 0.4230769230769231 && $residuo < 0.4615384615384615){
$letra = 12;
}
if($residuo > 0.4615384615384615 && $residuo < 0.5){
$letra = 13;
}
if($residuo > 0.4615384615384615 && $residuo < 0.5384615384615385){
$letra = 14;
}
if($residuo > 0.5384615384615385 && $residuo < 0.5769230769230769){
$letra = 15;
}
if($residuo > 0.5769230769230769 && $residuo < 0.6153846153846154){
$letra = 16;
}
if($residuo > 0.6153846153846154 && $residuo < 0.6538461538461538){
$letra = 17;
}
if($residuo > 0.6538461538461538 && $residuo < 0.6923076923076923){
$letra = 18;
}
if($residuo > 0.6923076923076923 && $residuo < 0.7307692307692308){
$letra = 19;
}
if($residuo > 0.7307692307692308 && $residuo < 0.7692307692307692){
$letra = 20;
}
if($residuo > 0.7692307692307692 && $residuo < 0.8076923076923077){
$letra = 21;
}
if($residuo > 0.8076923076923077 && $residuo < 0.8461538461538462){
$letra = 22;
}
if($residuo > 0.8461538461538462 && $residuo < 0.8846153846153846){
$letra = 23;
}
if($residuo > 0.8846153846153846 && $residuo < 0.9230769230769231){
$letra = 24;
}
if($residuo > 0.9230769230769231 && $residuo < 0.9615384615384615){
$letra = 25;
}
if($residuo > 0.9615384615384615 && $residuo < 1){
$letra = 26;
}
return $letra;
}
1;
The thing is, that when i execute the .pl, it only closes up, i've already checked the "palabras.txt" and it has 27 words, the perl -c and perl -wc says that the syntax is OK, the #INC with perl -V finishes with a '.', I really don't know what's happening, I'm on ActivePerl 5.20 in Windows 10.
Your code is working, but it's just not displaying the number before the window closes.
STDOUT (printing to the screen) is often line buffered. This means it will only display the line when it sees a newline. For example...
print "SLEEP!!!";
sleep 2;
print " AWAKE!!!\n"'
This will sleep for two seconds and then print SLEEP!!! AWAKE!!! all at once.
Try print "$palabraAleatoria\n";
For more detail, read Suffering From Buffering.
It seems like you're making your own random number generator? Perl already has one, rand(), and it will use a better seed than the time in seconds, and a better algorithm. rand takes a range of numbers to produce. rand(27) will give a number from 0 to 27 exclusive (so 0 to 26.9999). To use it to pick an element out of an array, use the size of the array.
my $random_idx = int rand #palabra;
print "$palabra[$random_idx]\n";
This also avoids having to hard code the number of elements in your array into your code.
Using rand eliminates the need for the big if chain, but let's talk about it anyway. It can be better written as an if/elsif starting at the top.
if( $residuo > 0.9615384615384615 ) {
return 26;
}
elsif( $residuo > 0.9230769230769231 ) {
return 25;
}
...and so on...
This avoids having to duplicate the range twice meaning less opportunities for typos. An if/elsif is more efficient, it doesn't have to check every condition, it will stop as soon as a condition is met. Returning immediately is also simpler and more efficient than using an intermediate return variable.
All those magic numbers makes one wonder why they're magical. Once you notice that 0.0384615384615385 is 1/26 you can use that instead.
if( $residuo > 25/26 ) {
return 26;
}
elsif( $residuo > 24/26 ) {
return 25;
}
...and so on...
Replacing the magic numbers with fractions makes it easier to read and clearer what's going on. Once that happens it becomes clear this can be replaced with some simple math.
return $residuo * 26 + 1;
Related
The program below works fine, but there is a warning that says:
Use of uninitialized value in numeric lt (<) line 17.
How do I fix the warning?
Any help would be really appreciated !
#!/usr/bin/perl
use strict;
use Carp;
use warnings;
my #array = (1,3,7,9,7,10,11,12,13,14,15,16,27,10,9,18,19,20,21,22,23,24,9,3,4);
my $i = 0;
my $j = 0;
my $k = 0;
my $n = $#array+1;
my $tempj = 0;
while(1){
$j=$i;
while (($array[$i] < $array[$i+1]) && ($i < ($n-1))){
$i++;
}
if(( $i - $j) > $k){
$k = $i-$j;
$tempj=$j;
}
if ($i >= ($n-1)){
print "la position : ",$j," , la langueur: ",$k,"\n";
exit;
}
else{
$j=$i;
while ($array[$i]>$array[$i+1] && $i < ($n-1)){
$i++;
}
if(($i-$j) > $k){
$k = $i-$j;
$tempj=$j;
}
if ($i >= ($n-1)){
print "la position : ",$j," , la langueur",$k,"\n";
exit;
}
}
}
Thank you in advance
Change the order of the conditions to make sure the array access is not out of bounds. This eliminates the warning:
while ( ($i < ($n-1)) && ($array[$i] < $array[$i+1]) ) {
I have a program which uses a module, located at the same folder that the executable but when I execute it it only closes.
use strict;
use warnings;
use genLetras;
for my $k (1 .. 30 ) {
for my $j (1 .. 30 ) {
genLetras::generarLetra();
$matriz[$k][$j] = genLetras::generarLetra();
}
}
for my $i (1 .. 30 ) {
for my $j (1 .. 30 ) {
print "[$matriz[$k][$j]] ";
}
print "\n";
}
<>;
That is the code of the executable.
An this one is the modules's one
use strict;
use warnings;
use Math::Complex;
my $seed = time();
my $a = $seed / 5;
my $c = $seed - 7;
my $x = $seed;
my $m = sqrt($seed % 574) + $seed;
my $numAleatorio;
sub generadorMultiplicativo{
$numAleatorio = ((($a*$x) + $c) % $m);
$x = $numAleatorio;
}
my $letra;
my $residuo;
sub generarLetra{
for my $i(1..30){
generadorMultiplicativo();
$residuo = $x/$m;
if($residuo < 0.0384615384615385 ){
$letra = 'A';
}
if($residuo > 0.0384615384615385 && $residuo < 0.076923076923077){
$letra = 'B';
}
if($residuo > 0.076923076923077 && $residuo < 0.1153846153846154){
$letra = 'C';
}
if($residuo > 0.1153846153846154 && $residuo < 0.1538461538461538){
$letra = 'D';
}
if($residuo > 0.1538461538461538 && $residuo < 0.1923076923076923){
$letra = 'E';
}
if($residuo > 0.1923076923076923 && $residuo < 0.2307692307692308){
$letra = 'F';
}
if($residuo > 0.2307692307692308 && $residuo < 0.2692307692307692){
$letra = 'G';
}
if($residuo > 0.2692307692307692 && $residuo < 0.3076923076923077 ){
$letra = 'H';
}
if($residuo > 0.3076923076923077 && $residuo < 0.3461538461538462){
$letra = 'I';
}
if($residuo > 0.3461538461538462 && $residuo < 0.3846153846153846){
$letra = 'J';
}
if($residuo > 0.3846153846153846 && $residuo < 0.4230769230769231){
$letra = 'K';
}
if($residuo > 0.4230769230769231 && $residuo < 0.4615384615384615){
$letra = 'L';
}
if($residuo > 0.4615384615384615 && $residuo < 0.5){
$letra = 'M';
}
if($residuo > 0.4615384615384615 && $residuo < 0.5384615384615385){
$letra = 'N';
}
if($residuo > 0.5384615384615385 && $residuo < 0.5769230769230769){
$letra = 'O';
}
if($residuo > 0.5769230769230769 && $residuo < 0.6153846153846154){
$letra = 'P';
}
if($residuo > 0.6153846153846154 && $residuo < 0.6538461538461538){
$letra = 'Q';
}
if($residuo > 0.6538461538461538 && $residuo < 0.6923076923076923){
$letra = 'R';
}
if($residuo > 0.6923076923076923 && $residuo < 0.7307692307692308){
$letra = 'S';
}
if($residuo > 0.7307692307692308 && $residuo < 0.7692307692307692){
$letra = 'T';
}
if($residuo > 0.7692307692307692 && $residuo < 0.8076923076923077){
$letra = 'U';
}
if($residuo > 0.8076923076923077 && $residuo < 0.8461538461538462){
$letra = 'V';
}
if($residuo > 0.8461538461538462 && $residuo < 0.8846153846153846){
$letra = 'W';
}
if($residuo > 0.8846153846153846 && $residuo < 0.9230769230769231){
$letra = 'X';
}
if($residuo > 0.9230769230769231 && $residuo < 0.9615384615384615){
$letra = 'Y';
}
if($residuo > 0.9615384615384615 && $residuo < 1){
$letra = 'Z';
}
return;
}
}
I've already compiled both with perl-c , perl -V and all said it was correct.
I'm using ActivePerl 5.20 on Windows 10
Four things to consider here:
The module's filename must be genLetras.pm.
The main script must find it. Do as #ikegami suggested in his answer and add
use FindBin qw( $RealBin );
use lib $RealBin;
before the use genLetras; line.
The module must end with some true value else the loader will complain.
Add the line
1;
as the very last line to your module.
The module needs a line package genLetras; as the first line. Add that.
Further notes:
Module names – by convention – usually start with an uppercase letter, like GenLetras, because
lowercase letters are reserved for pragmas (like e.g. warnings or strict).
I use FindBin usually like this:
use FindBin;
use lib $FindBin::Bin;
but that's more a matter of taste.
The <>; at the end of your main script normally is useless. I think you used it to prevent your Perl window from
closing immediately but wait for you to press ENTER instead.
That's ok then.
I wonder why perl -c script.pl didn't show any errors. At my PC it did.
During your testing, you probably set the Current Directory to be the directory in which the script resides. The module could be found because the module search paths (#INC) includes ..
When it fails, the Current Directory was probably set to some other directory. The module couldn't be found because #INC didn't contain the directory in which it resides.
Add the following to add the script's directory to #INC:
use FindBin qw( $RealBin );
use lib $RealBin;
I am trying to finish a homework for my class. After I installed a API::Twitter module using CPAN, the Net::Twitter module seems to be affected and can no longer be used.
I tried to run this code in my Mac terminal:
song_hanlun_hw8.pl
#!/usr/bin/perl
use Net::Twitter;
use JSON;
use LWP::Simple;
use XML::Bare;
use Data::Dumper;
# keys for twitter
$consumer_key = "key";
$consumer_secret = "key";
$token = "key-key";
$token_secret = "key";
# keys for sentiment analysis
$apikey = "key";
# As of 13-Aug-2010, Twitter requires OAuth for authenticated requests
my $nt = Net::Twitter->new(
traits => [qw/API::RESTv1_1/],
# traits => [qw/API::Search/],
consumer_key => $consumer_key,
consumer_secret => $consumer_secret,
access_token => $token,
access_token_secret => $token_secret,
);
#enter a term you want to search for
$search_term = "Halloween";
$count = 100;
my $r = $nt->search( { q => $search_term, count => $count } );
# print Dumper $r;
for my $status ( #{ $r->{statuses} } ) {
push #tweets, $status->{text};
}
$nextMaxId = $r->{search_metadata}->{next_results};
$nextMaxId =~ s/\?max_id=//g;
$nextMaxId =~ s/&q=Halloween&count=100&include_entities=1//g;
# print $nextMaxId;
my $r2 = $nt->search( { q => $search_term, count => $count, max_id => $nextMaxId } );
for my $status ( #{ $r2->{statuses} } ) {
push #tweets, $status->{text};
}
foreach $tweet ( #tweets ) {
# $tweet = $tweets[1];
$return = get "http://gateway-a.watsonplatform.net/calls/text/TextGetTextSentiment?apikey=$apikey&text=$tweet&outputMode=xml";
$bare = new XML::Bare( text => $return );
$root = $bare->parse();
$sentiment = $root->{results}->{docSentiment}->{score}->{value};
push #sentiments, $sentiment;
# print "$sentiment";
}
$m100to75 = 0;
$m75to50 = 0;
$m50to25 = 0;
$m25to0 = 0;
$p0to25 = 0;
$p25to50 = 0;
$p50to75 = 0;
$p75to100 = 0;
foreach $sent ( #sentiments ) {
# smaller than zero. four ranges.
if ( $sent >= -1 && $sent < -0.75 ) {
$m100to75++;
}
if ( $sent >= -0.75 && $sent < -0.5 ) {
$m75to50++;
}
if ( $sent >= -0.5 && $sent < -0.25 ) {
$m50to25++;
}
if ( $sent >= -0.25 && $sent < 0 ) {
$m25to0++;
}
#bigger than zero. four ranges.
if ( $sent >= 0 && $sent < 0.25 ) {
$p0to25++;
}
if ( $sent >= 0.25 && $sent < 0.5 ) {
$p25to50++;
}
if ( $sent >= 0.5 && $sent < 0.75 ) {
$p50to75++;
}
if ( $sent >= 0.75 && $sent < 1 ) {
$p75to100++;
}
}
# print "$m100to75\n$m75to50\n$m50to25\n$m25to0\n$p0to25\n$p25to50\n$p50to75\n$p75to100\n";
print "tweets sentiment score summary histogram:\n";
print "-1.00 to -0.75: ";
for ( $i = 0 ; $i < $m100to75 ; $i++ ) {
print "*";
}
print "\n";
print "-0.75 to -0.50: ";
for ( $i = 0 ; $i < $m75to50 ; $i++ ) {
print "*";
}
print "\n";
print "-0.50 to -0.25: ";
for ( $i = 0 ; $i < $m50to25 ; $i++ ) {
print "*";
}
print "\n";
print "-0.25 to -0.00: ";
for ( $i = 0 ; $i < $m25to0 ; $i++ ) {
print "*";
}
print "\n";
print "+0.00 to +0.25: ";
for ( $i = 0 ; $i < $p0to25 ; $i++ ) {
print "*";
}
print "\n";
print "+0.25 to +0.50: ";
for ( $i = 0 ; $i < $p25to50 ; $i++ ) {
print "*";
}
print "\n";
print "+0.50 to +0.75: ";
for ( $i = 0 ; $i < $p50to75 ; $i++ ) {
print "*";
}
print "\n";
print "+0.75 to +1.00: ";
for ( $i = 0 ; $i < $p75to100 ; $i++ ) {
print "*";
}
print "\n";
But the terminal returns
Invalid version format (version required) at /Library/Perl/5.18/Module/Runtime.pm line 386.
BEGIN failed--compilation aborted at /Library/Perl/5.18/Net/Twitter.pm line 3.
Compilation failed in require at song_hanlun_hw8.pl line 3.
BEGIN failed--compilation aborted at song_hanlun_hw8.pl line 3.
Could someone tell me how to fix this?
After some Google search I highly believe downgrading the Module::Runtime would solve this issue. But I could't find how.
Eventually I solved this issue by delete the Runtime module file in perl folder and reinstalled the Net::Twitter module, which also reinstalled the Runtime that Net::Twitter depends on.
Attached is my decision table, where in I'm using sv2.SV202_CompMedProcedId.get("SV202-02") several times in my condition. Is there any way that we can create an alias for sv2.SV202_CompMedProcedId.get("SV202-02") (for example, S) and use that alias in my condition instead of using the entire line every time?
CONDITION
sv2.SV202_CompMedProcedId.get(""SV202-02"").Value >= '70010' && sv2.SV202_CompMedProcedId.get(""SV202-02"").Value <= '76499' || sv2.SV202_CompMedProcedId.get(""SV202-02"").Value >= '76506' && sv2.SV202_CompMedProcedId.get(""SV202-02"").Value <= '76999' || sv2.SV202_CompMedProcedId.get(""SV202-02"").Value >= '77001' && sv2.SV202_CompMedProcedId.get(""SV202-02"").Value <= '77032' || sv2.SV202_CompMedProcedId.get(""SV202-02"").Value >= '77051' && sv2.SV202_CompMedProcedId.get(""SV202-02"").Value <= '77059' || sv2.SV202_CompMedProcedId.get(""SV202-02"").Value >= '77071' && sv2.SV202_CompMedProcedId.get(""SV202-02"").Value <= '77084' || sv2.SV202_CompMedProcedId.get(""SV202-02"").Value >= '77261' && sv2.SV202_CompMedProcedId.get(""SV202-02"").Value <= '77999' || sv2.SV202_CompMedProcedId.get(""SV202-02"").Value >= '78000' && sv2.SV202_CompMedProcedId.get(""SV202-02"").Value <= '79999'
where sv2 is the object and SV2 is the class
Yes, you can use an alias. Change your condition to:
$s : sv2.SV202_CompMedProcedId.get("SV202-02").Value >= '70010' && $s <= '76499' ||
$s >= '76506' && $s <= '76999' ||
$s >= '77001' && $s <= '77032' ||
$s >= '77051' && $s <= '77059' ||
$s >= '77071' && $s <= '77084' ||
$s >= '77261' && $s <= '77999' ||
$s >= '78000' && $s <= '79999'
If this is frequent enough you might write and import a static Java (!) function:
public boolean isInRanges( Comparable value, Comparable... bounds ){
for( int i = 0; i < bounds.length; i += 2 ){
if( bounds[i].compareTo(value) <= 0 &&
value.compareTo(bounds[i+1]) <= 0 ) return true;
}
return false;
}
The simple call is obvious.
You can't use a DRL function: AFAIK, the vararg notation isn't implemented (but check).
I want to add a flat $25 handling fee for Alaska (AK) and Hawaii (HI) - my test breaks when I add the states and flat fee to the shipping matrix below. Can someone point me in the right direction?
my $totalPounds = sprintf("%.2f",($totalWeight / 16));
#my $shipping = &getShipUPS($totalPounds, $zip, $shipType);
if ($subtotal <= 24.99) {$shipping = '10.95';}
elsif (($subtotal > 24.99) && ($subtotal <= 74.99)) {$shipping = '13.95';}
elsif (($subtotal > 74.99) && ($subtotal <= 149.99)) {$shipping = '14.95';}
elsif ($subtotal >= $150) {$shipping = '18.95';}
elsif ($state eq 'HI','AK') ($subtotal <= 24.99) {$shipping = '10.95'+'25.00';}
elsif ($state eq 'HI','AK') (($subtotal > 24.99) && ($subtotal <= 74.99)) {$shipping = '13.95'+'25.00';}
elsif ($state eq 'HI','AK') (($subtotal > 74.99) && ($subtotal <= 149.99)) {$shipping = '14.95'+'25.00';}
elsif ($state eq 'HI','AK') ($subtotal >= $150) {$shipping = '18.95'+'25.00';}else
$shipping = sprintf("%.2f", $shipping);
my $total = $subtotal + $tax + $shipping;
$subtotal = sprintf("%.2f", $subtotal);
$total = sprintf("%.2f", $total);
You cannot use multiple parameters with eq like this
$state eq 'HI','AK'
You need to do
$state eq 'HI' or $state eq 'AK'
ALso, you cannot put another parenthesis after the first after elsif like this
elsif ($state eq 'HI','AK') ($subtotal >= $150)
You need to do
elsif ( ($state eq 'HI' or $state eq 'AK') or ($subtotal >= $150) )
# ^---- main parantheses -------^
Of course, the smarter choice might be to use a hash
%extra_charges = ( AK => 25,
HI => 25,
# etc
);
...
$subtotal += $extra_charges{$state}; # assuming no missing states
The if-else logic is also all kinds of redundant. This ought to be the equivalent of your code:
if ($subtotal <= 24.99) { $shipping = '10.95' }
elsif ($subtotal <= 74.99) { $shipping = '13.95' }
elsif ($subtotal <= 149.99) { $shipping = '14.95' }
else { $shipping = '18.95' }
if ($state eq 'AK' or $state eq 'HI') { $shipping += 25 }
Those meandering forests of ifs are enough to make one dizzy, and most of them were not required. If a value is not less than or equal to 24.99, it must be bigger than 24.99, so no need to double check that.
That code is a total mess, has multiple syntax errors, and violates DRY.
It would be best to first calculate the basic shipping fee, depending on the subtotal. In a second step you add the $25 charge if the state is Hawaii or Alaska:
my #shipping_fees = (
# max subtotal => fee
[ 24.99 => 10.95 ],
[ 74.99 => 13.95 ],
[ 149.99 => 14.95 ],
[ inf => 18.95 ],
);
my %extra_fees_per_state = (
AK => 25.00,
HI => 25.00,
);
Then:
my $shipping;
for my $shipping_fee (#shipping_fees) {
my ($max, $fee) = #$shipping_fee;
if ($subtotal <= $max) {
$shipping = $fee;
last;
}
}
if (defined( my $extra = $extra_fees_per_state{$state})) {
$shipping += $extra;
}