diff options
| author | Util <bruce.gray@acm.org> | 2023-03-19 12:48:58 -0500 |
|---|---|---|
| committer | Util <bruce.gray@acm.org> | 2023-03-19 12:48:58 -0500 |
| commit | 50d63fb0a2d2df91c794593d6d1b686032caf732 (patch) | |
| tree | ebb7f80c35da687aa038a77a2a2bb67dbb53ba4a | |
| parent | 0f4a809c0bead5e3fd8bc4616e1c011c9d6fb8a9 (diff) | |
| download | perlweeklychallenge-club-50d63fb0a2d2df91c794593d6d1b686032caf732.tar.gz perlweeklychallenge-club-50d63fb0a2d2df91c794593d6d1b686032caf732.tar.bz2 perlweeklychallenge-club-50d63fb0a2d2df91c794593d6d1b686032caf732.zip | |
Add TWC 208 solutions by Bruce Gray (Raku only).
| -rw-r--r-- | challenge-208/bruce-gray/raku/ch-1.raku | 65 | ||||
| -rw-r--r-- | challenge-208/bruce-gray/raku/ch-2.raku | 20 |
2 files changed, 85 insertions, 0 deletions
diff --git a/challenge-208/bruce-gray/raku/ch-1.raku b/challenge-208/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..79649206b8 --- /dev/null +++ b/challenge-208/bruce-gray/raku/ch-1.raku @@ -0,0 +1,65 @@ +# Four ways-to-do-it; three use `minlist()`. + +# `.min` ignores ties, and `.minpairs` has no `:&by` parameter, so `minlist` is needed. +# minlist( <foo bar baz>, :by{ .substr(1,1) } ) returns <bar baz> +sub minlist ( @a, :&by --> List ) { + return @a[ @a.map(&by).minpairs».key ]; +} + +# Works with more than 2 lists of words! +sub task1a ( @lists-of-words --> List ) { + my %word_source_index; + for @lists-of-words.kv -> $source, @words { + for @words.kv -> $index, $word { + %word_source_index{$word}{$source} //= $index; + } + } + + return %word_source_index.grep({ .value.elems == @lists-of-words.elems }).&minlist( :by{ .value.values.sum } )».key; +} + +sub task1b ( @words1, @words2 --> List ) { + my %word_source_index; + %word_source_index{.value}<1> //= .key for @words1.pairs; + %word_source_index{.value}<2> //= .key for @words2.pairs; + + return %word_source_index.grep({ .value.elems == 2 }).&minlist( :by{ .value.<1 2>.sum } )».key; +} + +sub task1c ( @words1, @words2 --> List ) { + # Reversed to preserve the *first* index of any word duplicated in either array. + my %h1 = @words1.antipairs.reverse; + my %h2 = @words2.antipairs.reverse; + + return ( %h1 ∩ %h2 ).keys.&minlist( :by{ %h1{$_} + %h2{$_} } ); +} + +# Crazy-efficient for early matches, but O(N²) for worst case. +# Instead of `$sum=$i+$j`, this algorithm uses `$j=$sum-$i`. +sub task1d ( @words1, @words2 --> List ) { + for @words1.keys -> $sum { + my @r = gather for @words1.head($sum+1).kv -> $i, $word1 { + my $j = $sum - $i; + my $word2 = @words2[$j]; + + take $word1 if $word1 eq $word2; + } + return @r if @r; + } + return Empty; +} + + +constant @tests = + ( (<Perl Raku Love> , <Raku Perl Hate> ) , <Perl Raku> ), + ( ( <A B C> , <D E F> ) , List.new ), + ( ( <A B C> , <C A B> ) , ('A',) ), +; +use Test; +plan 4 * +@tests; +for @tests -> ( $in, $expected ) { + is-deeply task1a($in ).sort, $expected; + is-deeply task1b($in.[0], $in.[1]).sort, $expected; + is-deeply task1c($in.[0], $in.[1]).sort, $expected; + is-deeply task1d($in.[0], $in.[1]).sort, $expected; +} diff --git a/challenge-208/bruce-gray/raku/ch-2.raku b/challenge-208/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..dae6544055 --- /dev/null +++ b/challenge-208/bruce-gray/raku/ch-2.raku @@ -0,0 +1,20 @@ +sub task2 ( @ns --> List ) { + my @repeated = @ns.repeated; + my @missing = ( (1 .. +@ns) (^) @ns ).keys.sort(+*); + + return ( @repeated == 1 and @missing == 1 ) + ?? ( @repeated.head, @missing.head ) + !! Nil; +} + + +constant @tests = + ( (1,2,2,4) , (2,3) ), + ( (1,2,3,4) , -1 ), + ( (1,2,3,3) , (3,4) ), +; +use Test; +plan +@tests; +for @tests -> ( $in, $expected ) { + is-deeply (task2($in) // -1), $expected; +} |
