diff options
| author | Mohammad Sajid Anwar <Mohammad.Anwar@yahoo.com> | 2023-11-19 22:02:11 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-19 22:02:11 +0000 |
| commit | 4f90cd459b76172b3a3e6a1664fb9a938875b0dd (patch) | |
| tree | 8747b22e5bfbd3aaa695a013c2e2c28d84fd9d20 | |
| parent | b21b72b56d9a29857697d864a69c236fac1ad32d (diff) | |
| parent | 546103a0c143c6806af3910b229b069eab1e2791 (diff) | |
| download | perlweeklychallenge-club-4f90cd459b76172b3a3e6a1664fb9a938875b0dd.tar.gz perlweeklychallenge-club-4f90cd459b76172b3a3e6a1664fb9a938875b0dd.tar.bz2 perlweeklychallenge-club-4f90cd459b76172b3a3e6a1664fb9a938875b0dd.zip | |
Merge pull request #9095 from Util/c243
Add TWC 243 solutions by Bruce Gray (In Raku, and Javascript).
| -rw-r--r-- | challenge-243/bruce-gray/javascript/ch-1.js | 145 | ||||
| -rw-r--r-- | challenge-243/bruce-gray/javascript/ch-2.js | 54 | ||||
| -rw-r--r-- | challenge-243/bruce-gray/raku/ch-1.raku | 16 | ||||
| -rw-r--r-- | challenge-243/bruce-gray/raku/ch-2.raku | 32 |
4 files changed, 247 insertions, 0 deletions
diff --git a/challenge-243/bruce-gray/javascript/ch-1.js b/challenge-243/bruce-gray/javascript/ch-1.js new file mode 100644 index 0000000000..3d798122d9 --- /dev/null +++ b/challenge-243/bruce-gray/javascript/ch-1.js @@ -0,0 +1,145 @@ +#!/usr/bin/env node +'use strict'; + +// Procedural, with manual accumulator +function task1a ( ns ) { + let ret = 0; + + for ( const [i, left] of ns.entries() ) + for ( const right of ns.slice(i+1) ) + if ( left > (right * 2) ) + ret++; + + return ret; +} + +// task1a, with inner loop (for&if) refactored to functional (filter&length). +function task1b ( ns ) { + let ret = 0; + for ( const [i, left] of ns.entries() ) { + ret += ns.slice(i+1).filter((right) => left > (right * 2)).length; + } + return ret; +} + +// task1b, with the filter expression extracted to a named local function. +function task1c ( ns ) { + let ret = 0; + for ( const [i, left] of ns.entries() ) { + + const is_reverse_pair = (right) => left > (right * 2); + + ret += ns.slice(i+1) + .filter(is_reverse_pair) + .length; + } + return ret; +} + +// task1c, with the outer loop refactored to .map(), and accumulator embedded in a .reduce(). +function task1d ( ns ) { + const add = (a, b) => a + b; + + const count_of_reverse_pairs_with_left = ([i, left]) => { + + const is_reverse_pair = (right) => left > (right * 2); + + return ns.slice(i+1) + .filter(is_reverse_pair) + .length; + } + + return [...ns.entries()].map( count_of_reverse_pairs_with_left ).reduce(add, 0); +} + +// Cannot use a faster .reduce directly on Iterator; experimental feature provided by Node. +function task1e ( ns ) { + const count_of_reverse_pairs_with_this_element = (accumumlator, [i, left]) => { + const is_reverse_pair = (right) => left > (right * 2); + + const count = ns.slice(i+1) + .filter(is_reverse_pair) + .length; + + return accumumlator + count; + } + + return [ ...ns.entries() ].reduce(count_of_reverse_pairs_with_this_element, 0); +} + +// task1d with map+reduce merged +function task1f ( ns ) { + // const add = (a, b) => a + b; + + const reverse_pairs = ([i, left]) => { + + const is_reverse_pair = (right) => left > (right * 2); + + return ns.slice(i+1) + .filter(is_reverse_pair) + .length; + } + const sum_reverse_pairs = (a, e) => a + reverse_pairs(e); + + return [ ...ns.entries() ].reduce(sum_reverse_pairs, 0); +} + +// pre-doubled once into a parallel `two_n` array, to reduce recalculations. +function task1g ( ns ) { + const two_n = ns.map( n => 2*n ); + + const reverse_pairs = ([i, left]) => { + + const is_reverse_pair = (right) => left > right; + + return two_n.slice(i+1) + .filter(is_reverse_pair) + .length; + } + const sum_reverse_pairs = (a, e) => a + reverse_pairs(e); + + return [ ...ns.entries() ].reduce(sum_reverse_pairs, 0); +} + +// Extracted "combinations" +function task1h ( ns ) { + const combinations_2 = (arr, func) => { + arr.forEach( (left,i) => { + arr.slice(i+1).map( (right) => func(left, right) ); + }); + } + + let count = 0; + const count_wanted = (L,R) => { if ( L > (R * 2) ) count++ }; + combinations_2(ns, count_wanted); + return count; +} + +const subs = [ + [ 'task1a', task1a ], + [ 'task1b', task1b ], + [ 'task1c', task1c ], + [ 'task1d', task1d ], + [ 'task1e', task1e ], + [ 'task1f', task1f ], + [ 'task1g', task1g ], + [ 'task1h', task1h ], +]; +const tests = [ + [ 2, [1, 3, 2, 3, 1], 'Example 1 from task' ], + [ 3, [2, 4, 3, 5, 1], 'Example 2 from task' ], + [ 0, [] , 'Null array' ], +]; +let test_number = 0; +function is ( got, expected, desc ) { + test_number++; + const ok_msg = (got === expected) ? "ok" : "not ok"; + const description = (typeof desc !== 'undefined') ? ` - ${desc}` : ''; + console.log(`${ok_msg} ${test_number}${description}`); +} +for ( const [ sub_name, task1_coderef ] of subs ) { + for ( const [ expected, input, test_name ] of tests ) { + const got = task1_coderef(input); + is( got, expected, `${sub_name}: ${test_name}`); + } +} diff --git a/challenge-243/bruce-gray/javascript/ch-2.js b/challenge-243/bruce-gray/javascript/ch-2.js new file mode 100644 index 0000000000..c5664a5c35 --- /dev/null +++ b/challenge-243/bruce-gray/javascript/ch-2.js @@ -0,0 +1,54 @@ +// Procedural +function task2a ( ns ) { + let ret = 0; + for ( const x of ns ) { + for ( const y of ns ) { + ret += Math.floor( x / y ); + } + } + return ret; +} + +// Functional, both using extracted code for Cartesian product. +const cartesian = + (...top_level_arrays) => top_level_arrays.reduce( + (accum, an_array) => accum.flatMap( + (element1) => an_array.map( + (element2) => [element1, element2].flat() +))); + +// .map(), then sum via .reduce . +function task2b (ns) { + return cartesian(ns, ns) + .map(([x,y]) => Math.floor(x/y)) + .reduce(((a,b) => a+b),0); +} + +// Do the summing *and* mapping during the .reduce . +const task2c = (ns) => cartesian(ns, ns).reduce(((a,[x,y]) => a+Math.floor(x/y)),0); + + + +let test_number = 0; +function is ( got, expected, desc ) { + test_number++; + const ok_msg = (got === expected) ? "ok" : "not ok"; + const description = (typeof desc !== 'undefined') ? ` - ${desc}` : ''; + console.log(`${ok_msg} ${test_number}${description}`); +} +const subs = [ + [ 'task2a', task2a ], + [ 'task2b', task2b ], + [ 'task2c', task2c ], +]; +const tests = [ + [ 10, [2, 5, 9] , 'Example 1 from task'], + [ 49, [7,7,7,7,7,7,7], 'Example 2 from task'], + [ 10, [2, 5, 9] , 'Null array'], +]; +for ( const [ sub_name, task2_coderef ] of subs ) { + for ( const [ expected, input, test_name ] of tests ) { + const got = task2_coderef(input); + is( got, expected, `${sub_name}: ${test_name}`); + } +} diff --git a/challenge-243/bruce-gray/raku/ch-1.raku b/challenge-243/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..fee01833c8 --- /dev/null +++ b/challenge-243/bruce-gray/raku/ch-1.raku @@ -0,0 +1,16 @@ +sub task1 ( @ns ) { + sub is_reverse_pair ( [$left, $right] ) { $left > ($right * 2) } + + return +grep &is_reverse_pair, + combinations(@ns, 2); +} + + +constant @tests = + ( 2, (1, 3, 2, 3, 1) ), + ( 3, (2, 4, 3, 5, 1) ), +; +use Test; plan +@tests; +for @tests -> ($expected, @ns) { + is task1(@ns), $expected; +} diff --git a/challenge-243/bruce-gray/raku/ch-2.raku b/challenge-243/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..b7d2751cab --- /dev/null +++ b/challenge-243/bruce-gray/raku/ch-2.raku @@ -0,0 +1,32 @@ +# Note that `div` can take the place of `floor after division` +# only because the task specifies integers. +# https://docs.raku.org/language/operators#infix_div +# https://docs.raku.org/language/operators#infix_X +# https://docs.raku.org/language/operators#Cross_metaoperators +sub task2_simple ( @ns ) { + return sum( @ns Xdiv @ns ); +} + +constant &task2_inscrutable = { [+] [Xdiv] @^ns xx 2 }; + +# For 10_000 element array (100 duplicates of a line of 100 random 2-digit numbers): +# 3 seconds for task2_faster, vs 42 seconds for &task2_simple. +sub task2_faster ( @ns ) { + my @p = @ns.Bag; + + return sum map { [*] |$_».value, |[div] $_».key }, ( @p X @p ); +} + + + +constant @subs = :&task2_simple, :&task2_inscrutable, :&task2_faster; +constant @tests = + ( 10, (2, 5, 9) ), + ( 49, (7, 7, 7, 7, 7, 7, 7) ), +; +use Test; plan +@subs * +@tests; +for @subs -> ( :key($sub_name), :value($task2) ) { + for @tests.kv -> $i, ($expected, @ns) { + is $task2.(@ns), $expected, "$sub_name.fmt('%-18s'): Example {$i+1}"; + } +} |
