I recently wrote a program to score two different race series for my running club. Of course Ruby was a natural fit because it makes processing the textual data and arrays of scores so easy. I love it!
The problem is fairly straight forward for computer data processing, though it would be tedious by hand. The rules include the following:
Skipping ahead to the part of the problem where a member's total score withing a division (age group or overall) needs to be determined, imagine a SeriesRunner class with an @race_point variable that is an array of points (0-10) that member may have earned for a particular race. Or nil if they didn't run it at all.
irb(main):001:0> @race_points = [ nil, 9, 8, nil, 6, 7, nil, 8, 10, 6, 10] => [nil, 9, 8, nil, 6, 7, nil, 8, 10, 6, 10]
Counting the races run is simple:
irb(main):002:0> @race_points.compact.count => 8
And scoring them is pretty easy too. Essentially we need to add up the the best N results ordered from greatest to least:
irb(main):003:0> @race_points.compact.sort.reverse.slice(0...6).inject(:+) => 52
Let's break that down and process it piece-by-piece to see how it works.
First, get rid of the nils (races not run):
irb(main):004:0> a=@race_points.compact => [9, 8, 6, 7, 8, 10, 6, 10]
Then, sort them largest to smallest:
irb(main):005:0> b=a.sort => [6, 6, 7, 8, 8, 9, 10, 10] irb(main):006:0> c=b.reverse => [10, 10, 9, 8, 8, 7, 6, 6]
Then, take the largest n for the number of races that count (6 in this case):
irb(main):007:0> d=c.slice(0...6) => [10, 10, 9, 8, 8, 7] irb(main):008:0> # but what if the intended slice is bigger? irb(main):009:0* dd=c.slice(0...60) => [10, 10, 9, 8, 8, 7, 6, 6]
Finally, add them up:
irb(main):010:0> e=d.inject(:+) => 52
See? Super-easy. It took far longer to write this explanation than to program it.