━━━━━━━━━━━━━━━ CHALLENGE 122 Andinus ━━━━━━━━━━━━━━━ 2021-07-21 Table of Contents ───────────────── Task 1 - Average of Stream Task 2 - Basketball Points 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 ──── • Program: 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 ─ • Program: `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 ──── • Program: `(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.