# Employ strictures and warnings. # use strict; use warnings; # Declare things we don't change as constants (by convention # use upper-case for these). # use constant { NUM_TOSSES => 20, RUNS => 10_000_000, }; # Initialise all possible elements of @collect to avoid # "uninitialised" warnings at the printing stage if, for # example, no "twenties" were thrown. # my @collect = map 0, 0 .. NUM_TOSSES; # Use Perl-style for or foreach loops rather than C-style # ones. The for and foreach are synonymous in Perl and can # be freely interchanged. The loop variable is, by default, # available in $_ or you can assign it to a lexically # scoped variable as I do further down when printing the # results. We don't need it in these nested loops. # for ( 1 .. RUNS ) { # Declare lexically scoped $tailsCt so a new variable is # brought into existence each time round the outer loop # and will go out of scope on loop exit, thus no need to # zeroise every time. # my $tailsCt; # Toss the coin NUM_TOSSES times. # for ( 1 .. NUM_TOSSES ) { # Give rand() an argument n and it will return a value # such that 0 <= value < n. Use int to truncate so # that $tailsCt is incremented by 0 or 1 (heads or # tails respectively). # $tailsCt += int rand 2; } $collect[ $tailsCt ] ++; } # Rather than trying to line things up with tabs it might be # easier to use printf and employ the same field widths in the # heading and data rows. The RUNS constant is, in effect, a # piece of code rather than a variable so we have to enclose # it in a ${ \ ... } or a @{ [ ... ] } construct to interpolate # it into a double-quoted string. # printf qq{%5s%25s%9s\n}, q{Tails}, qq{Count out of ${ \ RUNS }}, q{%ge}; # q{Tails}, qq{Count out of @{ [ RUNS ] }}, q{%ge}; also works # Loop over the possible results from all heads to all tails # using lexically scoped $tailsCt to access elements in the # @collect array. This $tailsCt is a different variable to the # $tailsCt in the for ( 1 .. RUNS ) { ... } loop above and is # only in existence within the scope of this loop. # foreach my $tailsCt ( 0 .. NUM_TOSSES ) { # Rather than using a temporary variable and sprintf you # can just use printf directly and do the calculation in # the argument list. # printf qq{%5d%25d%9.2f\n}, $tailsCt, $collect[ $tailsCt ], $collect[ $tailsCt ] / RUNS * 100; }