in reply to Re^2: Averages in bowling
in thread Averages in bowling

So the average is by bowler? Then you only need two counter variables, not three. If you'd give your vars more meaningful names, it would go much easier. I'm going to try to do this intructively.
  1. What is it you want to do? You want to calculate the average score of every bowler.

  2. That means you need to loop for every bowler:

    for my $bowler (0..3) { ... }

    Better yet, let's not assume we know how many games there are:

    for my $bowler (0..$#scores) { ... }

    We will be working with the scores of a specific bowler, so let's create a shortcut:

    for my $bowler (0..$#scores) { my $bscores = $scores[$bowler]; ... }
  3. Now, we need to calculate the average score of a bowler:

    $averages[$bowler] = int(($bscores->[0] + $bscores->[1] + $bscores->[2])/3);

    That's ok, but it could be better. We could use a loop to remove the redundancy and to avoid assuming we know how many games there are:

    my $sum = 0; for my $game (0..$#$bscores}) { $sum += $bscores->[$game]; } $averages[$bowler] = int($sum/@$bscores);

    We can clean it up a bit by using a foreach loop (since $game is only used as an index into @$bscores):

    my $sum = 0; $sum += $_ foreach @$bscores; $averages[$bowler] = int($sum/@$bscores);
  4. All together now:

    for my $bowler (0..$#scores) { my $bscores = $scores[$bowler]; my $sum = 0; $sum += $_ foreach @$bscores; $averages[$bowler] = int($sum/@$bscores); }
  5. You could even use List::Util to do the sum:

    use List::Util qw( sum ); for my $bowler (0..$#scores) { my $bscores = $scores[$bowler]; $averages[$bowler] = int(sum(@$bscores)/@$bscores); }

    (Why isn't that module part of core?)

Replies are listed 'Best First'.
Re^4: Averages in bowling
by Andrew_Levenson (Hermit) on Mar 21, 2006 at 22:03 UTC
    I fixed it up, and even used your advice to make the program more versatile (i.e. let the user define how many bowlers and games there are as opposed to making it just 4 and 3, respectively.)
    In case you're interested, here's the entire {ugly} script.
    {my @score; my @ave; my @han; my $i=0; my $j=0; my $k=0; my $l=0; my $o=0; my $teamhand;} print "How many bowlers are there?\n"; chomp(my $n=<>); $n-=1; print "\nHow many games did the bowlers play?\n"; chomp(my $m=<>); $m- +=1; for $i(0..$n){ for $j(0..$m){ $l=$i+1; $o=$j+1; print "\nPlease enter bowler $l s score for game $o: "; chomp($score[$i][$j]=<>); } } for $i(0..$n){ undef $k; for $j(0..$m){ $k+=$score[$i][$j]; } push @ave, int($k/($m)); } for $k(0..$n){ if($ave[$k]<=200){ $han[$k]=int((200-$ave[$k])*(.85)); } if($ave[$k]>=200){ $han[$k]=0; } } for $i(0..$n){$teamhand+=$han[$i];} for $i(0..$n){ $j=$i+1; print "\nBowler $j s Average: $ave[$i] Bowler $j s Handicap: $han +[$i]\n"; } print "\nThe team's handicap is: $teamhand\n";


    Thanks again!

      Ugly is right. That's totally unreadable (read as "unmaintainable") because you use nonsense names.

      • Why not call $n $last_bowler?
      • Why not call $m $last_game?
      • Why not call $l $bowler_num?
      • Why not call $o $game_num?
      • Why not call $i $bowler_idx?
      • Why not call $j $game_idx?
      • Why not call $k $bowler_idx?
      • $k and $i have the same purpose, so why don't they have the same name?
      • Where is use strict;?
      • Where is use warnings;?
      • Why undef $k; instead of $k = 0;? It works, but it's weird, since you're relying on undef being equal to 0.
      • Why are your mys so far away from where the variable is used? for my $i (...) { ... } would limit the scope of $i to that loop.
        use strict; and use warnings; are just gone because the program wasn't being further tweaked.
        I removed them when I finished.
        And you're right, I should clean this up a bit.