Camel
Peter
Peter Campbell Smith

Grouping and scoring

Weekly challenge 336 — 25 August 2025

Week 336: 25 Aug 2025

Task 2

Task — Final score

You are given an array of scores by a team. Write a script to find the total score of the given team. The score can be any integer, +, C or D. The + adds the sum of previous two scores. The score C invalidates the previous score. The score D will double the previous score.

Examples


Example 1
Input: @scores = ('5','2','C','D','+')
Output: 30
Round 1: 5
Round 2: 5 + 2
Round 3: 5 (invalidate the previous score 2)
Round 4: 5 + 10 (double the previous score 5)
Round 5: 5 + 10 + 15 (sum of previous two scores)
Total Scores: 30


Example 2
Input: @scores = ('5','-2','4','C','D','9','+','+')
Output: 27
Round 1: 5
Round 2: 5 + (-2)
Round 3: 5 + (-2) + 4
Round 4: 5 + (-2) (invalidate the previous score 4)
Round 5: 5 + (-2) + (-4) (double the previous score -2)
Round 6: 5 + (-2) + (-4) + 9
Round 7: 5 + (-2) + (-4) + 9 + 5 (sum of previous two 
   scores)
Round 8: 5 + (-2) + (-4) + 9 + 5 + 14 (sum of previous 
   two scores)
Total Scores: 27


Example 3
Input: @scores = ('7','D','D','C','+','3')
Output: 45
Round 1: 7
Round 2: 7 + 14 (double the previous score 7)
Round 3: 7 + 14 + 28 (double the previous score 14)
Round 4: 7 + 14 (invalidate the previous score 28)
Round 5: 7 + 14 + 21 (sum of previous two scores)
Round 6: 7 + 14 + 21 + 3
Total Scores: 45


Example 4
Input: @scores = ('-5','-10','+','D','C','+')
Output: -55
Round 1: (-5)
Round 2: (-5) + (-10)
Round 3: (-5) + (-10) + (-15) (sum of previous two scores)
Round 4: (-5) + (-10) + (-15) + (-30) (double the 
   previous score -15)
Round 5: (-5) + (-10) + (-15) (invalidate the previous 
   score -30)
Round 6: (-5) + (-10) + (-15) + (-25) (sum of previous 
   two scores)
Total Scores: -55


Example 5
Input: @scores = ('3','6','+','D','C','8','+','D','-2',
   'C','+')
Output: 128
Round  1: 3
Round  2: 3 + 6
Round  3: 3 + 6 + 9 (sum of previous two scores)
Round  4: 3 + 6 + 9 + 18 (double the previous score 9)
Round  5: 3 + 6 + 9 (invalidate the previous score 18)
Round  6: 3 + 6 + 9 + 8
Round  7: 3 + 6 + 9 + 8 + 17 (sum of previous two scores)
Round  8: 3 + 6 + 9 + 8 + 17 + 34 (double the previous 
   score 17)
Round  9: 3 + 6 + 9 + 8 + 17 + 34 + (-2)
Round 10: 3 + 6 + 9 + 8 + 17 + 34 (invalidate the 
   previous score -2)
Round 11: 3 + 6 + 9 + 8 + 17 + 34 + 51 (sum of previous 
   two scores)
Total Scores: 128

Analysis

After a bit of thought I decide that two scans through the data was the way to go.

In the first scan we delete any 'C' element and the element preceding it.

In the second scan we update in place any element containing 'D' or '+' according to the stated rules.

We then total the array, and that's the answer.

We aren't told what to do if the first element isn't numeric, or if '+' appears in the second, so I have reported these as bad data. This also applies if the 'C' elements leave the array empty (eg '1', 'C', '2', 'C').

Try it 

Try running the script with any input:



example: 1, 2, 3, C, 4, D, +

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2025-08-25
use utf8;     # Week 336 - task 2 - Final score
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

final_score('5', '2', 'C', 'D', '+');
final_score('5', '-2', '4', 'C', 'D', '9', '+', '+');
final_score('7', 'D', 'D', 'C', '+', '3');
final_score('-5', '-10', '+', 'D', 'C', '+');
final_score('3', '6', '+', 'D', 'C', '8', '+', 'D', '-2', 'C', '+');
final_score('C', '1', '2');
final_score('D', '1', '2');
final_score('+', '1', '2');
final_score('1', '+', '2');
final_score('1', 'C', '2', 'C');

sub final_score {
    
    my (@scores, $total, $prev1, $prev2, $score, $i);
    
    say qq[\nInput:  ('] . join(qq[', '], @_) . q[')];  
    
    # get rid of C and scores preceding a C
    $scores[0] = $_[0];
    for ($i = 1; $i < scalar @_; $i ++) {
        if ($_[$i] eq 'C') {
            pop @scores;
        } else {
            push @scores, $_[$i];
        }
    }
    
    # bad input
    if (scalar @scores == 0 or $scores[0] !~ m|^-?\d+$| or $scores[1] eq '+') {
        say qq[Output: bad data];
        return;
    }

    # handle D and +
    for $i (1 .. $#scores) {
        if ($scores[$i] eq '+' and $i >= 2) { 
            $scores[$i] = $scores[$i - 1] + $scores[$i - 2];
        } elsif ($scores[$i] eq 'D') { 
            $scores[$i] = $scores[$i - 1] * 2;
        }
    }
    $total += $_ for @scores;
    say qq[Output: $total];
}

Output


Input:  ('5', '2', 'C', 'D', '+')
Output: 30

Input:  ('5', '-2', '4', 'C', 'D', '9', '+', '+')
Output: 27

Input:  ('7', 'D', 'D', 'C', '+', '3')
Output: 45

Input:  ('-5', '-10', '+', 'D', 'C', '+')
Output: -55

Input:  ('3', '6', '+', 'D', 'C', '8', '+', 'D', '-2',
   'C', '+')
Output: 128

Input:  ('C', '1', '2')
Output: bad data

Input:  ('D', '1', '2')
Output: bad data

Input:  ('+', '1', '2')
Output: bad data

Input:  ('1', '+', '2')
Output: bad data

Input:  ('1', 'C', '2', 'C')
Output: bad data

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain