UP / HOME

Challenge 122

Table of Contents

Task 1 - Average of Stream

You are given a stream of numbers, @N.

Write a script to print the average of the stream at every point.

Example:

Input: @N = (10, 20, 30, 40, 50, 60, 70, 80, 90, ...)
Output:      10, 15, 20, 25, 30, 35, 40, 45, 50, ...

Average of first number is 10.
Average of first 2 numbers (10+20)/2 = 15
Average of first 3 numbers (10+20+30)/3 = 20
Average of first 4 numbers (10+20+30+40)/4 = 25 and so on.

Raku

The subroutine avg takes a list of numbers and returns their average. We just loop over keys of @nums and print the average upto each point.

#| return average of lists.
sub avg(*@list) { (sum @list) / @list.elems; }

#| average of stream at every point.
sub MAIN(*@nums where {$_.all ~~ Int}) {
    put @nums.keys.map({avg @nums[0..$_]});
}

C

argv holds the input & argc holds the number of inputs. We loop over argv and convert each input to an integer and add it to sum which holds the sum of inputs upto that point and print sum / idx, idx being the index of input.

long sum = 0;
for (int idx = 1; idx < argc; idx++) {
    int num;
    const char *errstr;
    num = strtonum(argv[idx], INT_MIN, INT_MAX, &errstr);
    if (errstr != NULL)
        errx(1, "number is %s: %s", errstr, argv[idx]);

    sum += num;
    printf("%ld ", sum / idx);
 }
printf("\n");

Task 2 - Basketball Points

You are given a score $S.

You can win basketball points e.g. 1 point, 2 points and 3 points.

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

Example:

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

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

Raku

(0, 1, 2, 3) xx $score creates the list 0..3, $score number of times. And [X] creates cross product from those lists.

  • Note: It's multipled $score number of times because (1) xx $score is the maximum upto which we get $score, after that the sum will exceed $score, we do have 0's there which means we'll get more matches but we've already covered those cases.

Say the score is 3. We have 3 lists like these:

0 0 0
1 1 1
2 2 2
3 3 3

And cross product will return:

0, 0, 0
0, 0, 1
0, 0, 2
0, 0, 3
0, 1, 0
...
3, 3, 3

We loop over what the cross product returns and take the list if the sum of all elements equals to the score.

#| scoring basketball points
unit sub MAIN(Int $score);

.put for gather for [X] ((0, 1, 2, 3) xx $score) -> @scores {
    take @scores if ([+] @scores) == $score;
}.map(*.grep(* !== 0).join).unique.map(*.comb);

After we gather the lists of scores, remove 0's from there and then we remove duplicate entries. Duplicates entries are removed by converting them to string, using unique method and converting them back to Int.

These entries occur because cross product includes them multiple times. For example, for a score of 3: Cross product will return 0 1 2 and 1 2 0, both of which will satisty the condition and we'll gather them, after removing the 0's, they become duplicates.

Andinus / 2021-07-21 / Modified: 2021-09-13 Mon 15:38 Emacs 27.2 (Org mode 9.4.4)