theillien1 has asked for the wisdom of the Perl Monks concerning the following question:

I have a script which, based on a number passed from the command line will create random numbers of varying lengths. The way the script is written I may get 0 more than once. As it is a hash, no matter how many times 0 shows up, it will only appear once in the hash with the last value assigned. This leaves me short on elements compared to the request.

In order to determine how short I'm trying to find out how many keys there are:

print "randList length: " . scalar keys %randList;

This has the strange habit of printing twice. If there are 18 elements I'll get 1818; 20 elements begets 2020.

Later in the script I assign the keys to an array. I attempted to do the same thing using

print "numList length: " . ($#numList + 1);

This also outputs the value twice. Interestingly, if I don't add one to it I get two numbers. If the length is 17 I get 1617. I've also tried scalar @numList with the same results.

What could I be doing wrong? Full script below:
#!/usr/bin/perl use warnings; use strict; use Lingua::JA::Numbers; my $converted = "converted_numbers.csv"; my $len = $ARGV[0]; my (@numList, @rom, @kana, @kanji, %randList); open(OUTFILE, ">$converted"); binmode OUTFILE, ":utf8"; for (my $i=0; $i<$ARGV[1]; $i++) { my $genlen = int rand($len); my $max = 1 . 0 x $genlen; my $num = int rand($max); $randList{$num} = 1; } print "randList length: " . (scalar keys %randList) . "\n"; foreach my $key (keys %randList) { push(@numList, $key); } print "Length randList: " . ($#numList + 1); for my $num (@numList){ my $jaRom = Lingua::JA::Numbers->new($num, {style=>'romaji'}); my $jaKana = Lingua::JA::Numbers->new($num, {style=>'hiragana'}); my $jaKanji = Lingua::JA::Numbers->new($num, {style=>'kanji'}); push(@rom, $jaRom); push(@kana, $jaKana); push(@kanji, $jaKanji); } my (@hyphens, @noHyphens); for my $strg (@rom){ @hyphens = Lingua::JA::Numbers::to_string($strg); for my $val (@hyphens){ $val =~ s/-//g; } push(@noHyphens, join(" ", @hyphens)); } @rom = @noHyphens; my $size = scalar @numList; foreach (my $i=0; $i<$size; $i++){ print OUTFILE $numList[$i] . "," . $rom[$i] . "," . $kana[$i] . ", +" . $kanji[$i] . "\n"; } close OUTFILE;

Replies are listed 'Best First'.
Re: Bizarre hash/array [size,length,whatever-you-want-to-call-it] output
by toolic (Bishop) on May 31, 2010 at 01:32 UTC
    This has the strange habit of printing twice. If there are 18 elements I'll get 1818; 20 elements begets 2020.
    No matter what I pass into your program from the command line, I can not reproduce that result. Please show the exact command line you use to get that result. Also, post the contents of the hash using:
    use Data::Dumper; print Dumper(\%randList);

    On a side note, this:

    foreach my $key (keys %randList) { push(@numList, $key); }
    can be simplified to this:
    @numList = keys %randList;

      Basically, all I'm doing is running it as

      > script.pl 6 20

      The 6 being @ARGV[0] for the purpose of generating the random numbers and the 20 being $ARGV[1] and for how many numbers to generate. The computer is my system at work. I'll have to log in tomorrow sometime to get the dump that you asked for.

      As for the simplification, thanks for the suggestion. I have no doubt that there are numerous places I could optimize my code.

        I tried script.pl 6 20. That doesn't work. You need at least 3 numbers. I tried script.pl 6 20 21. It worked:).
      I've added the Data::Dumper lines as you requested:
      #!/usr/bin/perl use warnings; use strict; use Lingua::JA::Numbers; my $converted = "converted_numbers.csv"; my $len = $ARGV[0]; my (@numList, @rom, @kana, @kanji, %randList); open(OUTFILE, ">$converted"); binmode OUTFILE, ":utf8"; for (my $i=0; $i<$ARGV[1]; $i++) { my $genlen = int rand($len); my $max = 1 . 0 x $genlen; my $num = int rand($max); $randList{$num} = 1; } use Data::Dumper; print "Data Dump:\n"; print Dumper(\%randList) . "\n"; print "randList length: " . (scalar keys %randList) . "\n"; @numList = keys %randList; print "Length numList: " . (scalar @numList) . "\n"; for my $num (@numList){ my $jaRom = Lingua::JA::Numbers->new($num, {style=>'romaji'}); my $jaKana = Lingua::JA::Numbers->new($num, {style=>'hiragana' +}); my $jaKanji = Lingua::JA::Numbers->new($num, {style=>'kanji'}) +; push(@rom, $jaRom); push(@kana, $jaKana); push(@kanji, $jaKanji); } my (@hyphens, @noHyphens); for my $strg (@rom){ @hyphens = Lingua::JA::Numbers::to_string($strg); for my $val (@hyphens){ $val =~ s/-//g; } push(@noHyphens, join(" ", @hyphens)); } @rom = @noHyphens; my $size = scalar @numList; print $size . "\n"; foreach (my $i=0; $i<$size; $i++){ print OUTFILE $numList[$i] . "," . $rom[$i] . "," . $kana[$i] +. "," . $kanji[$i] . "\n"; } close OUTFILE;
      I've also added a newline at the end of the second print statement which has exposed something else:
      msnyder@msnyder:~/bin> ./num-to-jp4.pl 6 20 Data Dump: $VAR1 = { '48766' => 1, '9732' => 1, '33' => 1, '66526' => 1, '328' => 1, '4344' => 1, '438' => 1, '0' => 1, '55' => 1, '6' => 1, '5148' => 1, '182' => 1, '3' => 1, '46726' => 1, '3319' => 1, '59' => 1, '2851' => 1, '652' => 1 }; randList length: 18 Length numList: 18 18
      While I still don't know why the output is printing twice, this is the script I was ultimately trying to come up with and it works. That's all I really needed. This thread was simply a result of the odd, mostly unrelated output I was seeing.
      #!/usr/bin/perl use strict; use warnings; use Lingua::JA::Numbers; my $len = $ARGV[0]; my (@numList, @rom, @kana, @kanji, %randList); open(OUTFILE, '>', 'converted.csv'); binmode OUTFILE, ":utf8"; while ((scalar(keys %randList)) != $ARGV[1]){ $randList{int (rand (1 . 0 x (int (rand $len))))} = 1; } @numList = keys %randList; for my $num (@numList){ my $jaRom = Lingua::JA::Numbers->new($num, {style=>'romaji'}); my $jaKana = Lingua::JA::Numbers->new($num, {style=>'hiragana'}); my $jaKanji = Lingua::JA::Numbers->new($num, {style=>'kanji'}); push @rom, $jaRom; push @kana, $jaKana; push @kanji, $jaKanji; } my (@hyphens, @noHyphens); for my $strg (@rom){ @hyphens = Lingua::JA::Numbers::to_string($strg); foreach my $val (@hyphens){ $val =~ s/-//g; } push @noHyphens, join(' ', @hyphens); } @rom = @noHyphens; for (my $i = 0; $i < (scalar @numList); ++$i){ print OUTFILE $numList[$i] . "," . $rom[$i] . "," . $kana[$i] ."," + . $kanji[$i] . "\n"; } close OUTFILE;
      If we can figure out the cause of the output I'll be happy but it isn't really a pressing matter.
Re: Bizarre hash/array [size,length,whatever-you-want-to-call-it] output
by Khen1950fx (Canon) on May 31, 2010 at 07:50 UTC
    I made a few adjustments and tried this script. It prints random numbers to convert.txt and sends to output something like what you described, for example randList length 67/Length randList 67.
    #!/usr/bin/perl use strict; use warnings; use Lingua::JA::Numbers; my $converted = shift @ARGV; my $len = $ARGV[0]; my (@numList, @rom, @kana, @kanji, %randList); open(OUTFILE, '>', 'converted.txt'); binmode OUTFILE, ":utf8"; foreach (my $i = 0; $i < $ARGV[1]; ++$i) { my $genlen = int rand $len; my $max = 1 . 0 x $genlen; my $num = int rand $max; $randList{$num} = 1; } print "randList length: " . scalar(keys %randList) . "\n"; foreach my $key (keys %randList) { push @numList, $key; } print "Length randList: " . ($#numList + 1); for my $num (@numList){ my $jaRom = Lingua::JA::Numbers->new($num, {style=>'romaji'}); my $jaKana = Lingua::JA::Numbers->new($num, {style=>'hiragana'}); my $jaKanji = Lingua::JA::Numbers->new($num, {style=>'kanji'}); push @rom, $jaRom; push @kana, $jaKana; push @kanji, $jaKanji; } my (@hyphens, @noHyphens); for my $strg (@rom){ @hyphens = Lingua::JA::Numbers::to_string($strg); foreach my $val (@hyphens){ $val =~ s/-//g; } push @noHyphens, join(' ', @hyphens); } @rom = @noHyphens; my $size = scalar @numList; for (my $i = 0; $i < $size; ++$i){ print OUTFILE $numList[$i] . "," . $rom[$i] . "," . $kana[$i] . ", +" . $kanji[$i] . "\n"; } close OUTFILE;
Re: Bizarre hash/array [size,length,whatever-you-want-to-call-it] output
by Anonymous Monk on May 31, 2010 at 11:11 UTC
    all I can think of is that you probably had an extra print statement for hash size that was later removed from the code you pasted pasted here ;)
Re: Bizarre hash/array [size,length,whatever-you-want-to-call-it] output
by perreal (Monk) on May 31, 2010 at 11:56 UTC
    I've seen some cases when having weird characters in the print statements causes strange things in the terminal window. you can try to write to a file.