Jairo
Jairo

Reputation: 29

Issues with Perl program

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.

Upvotes: 1

Views: 62

Answers (1)

Schwern
Schwern

Reputation: 164629

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;

Upvotes: 3

Related Questions