Camel
Peter
Peter Campbell Smith

Stream and points

Weekly challenge 122 — 19 July 2021

Week 122: 19 Jul 2021

Task 2

Task — Basketball points

You are given a final score $score. You can score 1 point, 2 points or 3 points in basketball.

Write a script to find out the different ways you can score $score.

Examples


Example 1
Input: $S = 4
Output: 1 1 1 1
        1 1 2
        1 2 1
        1 3
        2 1 1
        2 2
        3 1

Example 2:
Input: $S = 5
Output: 1 1 1 1 1
        1 1 1 2
        1 1 2 1
        1 1 3
        1 2 1 1
        1 2 2
        1 3 1
        2 1 1 1
        2 1 2
        2 2 1
        2 3
        3 1 1
        3 2

Analysis

Basketball scores can be quite large numbers, so the number of possible patterns of points won can be huge: for example, in a recent game Newcastle Eagles scored 99 against the Surrey 89ers 72.

The 99 score could be anything from 99 scores of 1 down to 33 scores of 3. So we might be thinking of looking at all the permutations of 99 numbers in the range 0 to 3 and discarding those where the sum exceeded 99. But there are more than 10**155 such permutations, so that's not practical.

Instead, I have gone for a recursive solution. Recusrion is relatively slow in Perl and the code is not always easy to follow (or to write), but as we're not looking at scores of 99 it should work.

The principle is this. The subroutine next_point takes 3 inputs:

  • $score, which is the score so far
  • $target, which is the end score we are investigating, say 5
  • $so_far, which is a text string of the scores so far

So initially we call next_point(0, 5, ''). We try adding 1, 2 or 3 points to $score, and if:

  • $score == $target we record this as a candidate answer
  • $score > $target we return because this can't be the path to an allowed total score
  • $score < $target we append the current score to $so_far and recursively call next_point to try adding the score of the next play

That works in milliseonds for a score up to 10, in a few seconds for 20 and 45 seconds for 25, but most of that time is spent outputting the numbers.

And we can with virtual certainty assert that the order in which the points were scored in the Newcastle/Surrey game had never happened before and will never happen again!

Try it 

Try running the script with any input:



example: 5 — max of 10 please

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2021-07-19
use utf8;     # Week 122 - task 2 - Basketball points
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

basketball_points(1);
basketball_points(5);
basketball_points(8);

sub basketball_points {
    
    my ($points, $max, $k, $this);
    
    # initialise
    $points = shift;
    
    say qq[\nInput:  $points\nOutput: ];
    next_point(0, $points, '       ');
}

sub next_point  {
    
    my ($score, $target, $this_point, $so_far, $score_in, $score_this);
    
    # initialise
    ($score, $target, $so_far) = @_;

    # try adding 1, 2 or 3
    for $this_point (1, 2, 3) {
        $score_this = $score + $this_point;
        
        # found a possible, report it
        if ($score_this == $target) {
            say qq[$so_far $this_point];
            return;
        
        # still below target so add more
        } elsif ($score_this < $target) {
            next_point($score_this + 0, $target, qq[$so_far $this_point] . '');
            
        # above target so give up
        } else {
            return;
        }
    }
}

last updated 2026-03-07 — 17 lines of code

Output


Input:  1
Output:
        1

Input:  5
Output:
        1 1 1 1 1
        1 1 1 2
        1 1 2 1
        1 1 3
        1 2 1 1
        1 2 2
        1 3 1
        2 1 1 1
        2 1 2
        2 2 1
        2 3
        3 1 1
        3 2

Input:  8
Output:
        1 1 1 1 1 1 1 1
        1 1 1 1 1 1 2
        1 1 1 1 1 2 1
        1 1 1 1 1 3
        1 1 1 1 2 1 1
        1 1 1 1 2 2
        1 1 1 1 3 1
        1 1 1 2 1 1 1
        1 1 1 2 1 2
        1 1 1 2 2 1
        1 1 1 2 3
        1 1 1 3 1 1
        1 1 1 3 2
        1 1 2 1 1 1 1
        1 1 2 1 1 2
        1 1 2 1 2 1
        1 1 2 1 3
        1 1 2 2 1 1
        1 1 2 2 2
        1 1 2 3 1
        1 1 3 1 1 1
        1 1 3 1 2
        1 1 3 2 1
        1 1 3 3
        1 2 1 1 1 1 1
        1 2 1 1 1 2
        1 2 1 1 2 1
        1 2 1 1 3
        1 2 1 2 1 1
        1 2 1 2 2
        1 2 1 3 1
        1 2 2 1 1 1
        1 2 2 1 2
        1 2 2 2 1
        1 2 2 3
        1 2 3 1 1
        1 2 3 2
        1 3 1 1 1 1
        1 3 1 1 2
        1 3 1 2 1
        1 3 1 3
        1 3 2 1 1
        1 3 2 2
        1 3 3 1
        2 1 1 1 1 1 1
        2 1 1 1 1 2
        2 1 1 1 2 1
        2 1 1 1 3
        2 1 1 2 1 1
        2 1 1 2 2
        2 1 1 3 1
        2 1 2 1 1 1
        2 1 2 1 2
        2 1 2 2 1
        2 1 2 3
        2 1 3 1 1
        2 1 3 2
        2 2 1 1 1 1
        2 2 1 1 2
        2 2 1 2 1
        2 2 1 3
        2 2 2 1 1
        2 2 2 2
        2 2 3 1
        2 3 1 1 1
        2 3 1 2
        2 3 2 1
        2 3 3
        3 1 1 1 1 1
        3 1 1 1 2
        3 1 1 2 1
        3 1 1 3
        3 1 2 1 1
        3 1 2 2
        3 1 3 1
        3 2 1 1 1
        3 2 1 2
        3 2 2 1
        3 2 3
        3 3 1 1
        3 3 2


 

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