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

I have some questions about the following code:
#!/usr/bin/perl -w use strict; my @fr = ([], [], [], [], []); my $low_count; for my $x (10 .. 99) { for my $y (101 .. 999) { my $result = $x * $y; if ($result < 10000) { $low_count++; next; } $result =~ m/(\d)?(\d)?(\d)?(\d)?(\d)?/; $fr[0][$5]++; $fr[1][$4]++; $fr[2][$3]++; $fr[3][$2]++; $fr[4][$1]++; } } $fr[4][0] = 0; #This line print "$low_count\n\n"; for my $digit (0 .. 9) { print "$digit\t"; for my $exp (reverse 0 .. 4) { print "$fr[$exp][$digit]\t"; } print "\n"; }
1. Is there a better way to write it, that would enable it to be scaled up to multiplcations of any size?

2. Is there a way to prevent a 'use of uninitialised value' error other than explicitly setting the variable like I have done in the line marked '#This line' (which I think is kludgy)?

3. Can you tell from the code what my editor of choice is? :-)
  • Comment on Frequency analysis of the digits of the result of a multiplication
  • Download Code

Replies are listed 'Best First'.
Re: Frequency analysis of the digits of the result of a multiplication
by Masem (Monsignor) on Nov 17, 2001 at 23:54 UTC
    There's definitely an easier way to build up your arrays:
    foreach my $x ( 10..99 ) { foreach my $y ( 10..999 ) { @result = reverse split //, $x*$y; $fr[ $_ ][ $result[$_] ]++ foreach (0..$#result); } }
    And to remove that uninitialized value, you can do something like:
    my @fr; $fr[$_] = [ (0)x10 ] foreach (0..$maxdigits);
    where $maxdigits is the largest number of digits you expect in your results.

    -----------------------------------------------------
    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
    "I can see my house from here!"
    It's not what you know, but knowing how to find it if you don't know that's important

      Thanks for that.

      I found that after getting @result, I had to add:
      while (scalar @result < $maxdigits) { push @result, 0; }
      to cope with when the result is less than $maxdigits in length. (M-x mpuz, which is behind why I wrote this code in the first place, throws away results less than 5 digits in length anyway.)
Re: Frequency analysis of the digits of the result of a multiplication
by demerphq (Chancellor) on Nov 18, 2001 at 01:07 UTC
    I came up with pretty much the same as Masem and Grinder but my table generater looked like this:
    for my $digit (0 .. 9) { print "$digit\t"; print map { ($_->[$digit]||=0)."\t" } reverse @fh; print "\n"; }
    This seemed like a good time to use map.

    :-)

    Yves / DeMerphq
    --
    Have you registered your Name Space?

Re: Frequency analysis of the digits of the result of a multiplication
by grinder (Bishop) on Nov 17, 2001 at 23:56 UTC

    re: question 2, try, a few lines below your kluge, the following fix:

    $fr[$exp][$digit] ||= 0; print "$fr[$exp][$digit]\t";

    That is, if you never actually saw any digits at a certain power of ten, then set it to zero before printing it out.

    Cool idea. I love applying computers to existential mathematical questions.

    --
    g r i n d e r
Re: Frequency analysis of the digits of the result of a multiplication
by hopes (Friar) on Nov 18, 2001 at 01:19 UTC
    This is my code to make the program independent of the number of digits.
    I donīt know how to interprete 999 and 99, maybe 10^3-1 and 10^2-1, but I don't know how would be if digits is "6".
    999 and 999?
    99 and 9999?

    Regards
    Hopes
    #!/usr/bin/perl -w use strict; my $fr; my $low_count; my $digits=5; for my $x (10 .. 99) { for my $y (101 .. 999) { my $result = $x * $y; if ($result < 10**($digits-1)) { $low_count++; next; } my $index; $fr->[5-$index++][$&]++ while ($result =~ /\d/g); } } $fr->[$digits-1][0] = 0; #This line print "$low_count\n\n"; for my $digit (0 .. 9) { print "$digit\t"; for my $exp (reverse 0 .. 4) { print "$fr->[$exp][$digit]\t"; } print "\n"; }
Re: Frequency analysis of the digits of the result of a multiplication
by pjf (Curate) on Nov 18, 2001 at 01:57 UTC
    If you want to be able to work with integers of an arbitary size, you might want to check out the Math::BigInt package.

    Cheers,
    Paul