From e4fe9c8924665c629c30c722b90d4aaf0411e844 Mon Sep 17 00:00:00 2001 From: Util Date: Sun, 6 Nov 2022 15:00:33 -0600 Subject: Add TWC 189 solutions (Perl and Raku) and blog URL by Bruce Gray. --- challenge-189/bruce-gray/blog.txt | 1 + challenge-189/bruce-gray/perl/ch-1.pl | 24 ++++++++++++++ challenge-189/bruce-gray/perl/ch-2.pl | 58 +++++++++++++++++++++++++++++++++ challenge-189/bruce-gray/raku/ch-1.raku | 20 ++++++++++++ challenge-189/bruce-gray/raku/ch-2.raku | 39 ++++++++++++++++++++++ 5 files changed, 142 insertions(+) create mode 100644 challenge-189/bruce-gray/blog.txt create mode 100755 challenge-189/bruce-gray/perl/ch-1.pl create mode 100755 challenge-189/bruce-gray/perl/ch-2.pl create mode 100644 challenge-189/bruce-gray/raku/ch-1.raku create mode 100644 challenge-189/bruce-gray/raku/ch-2.raku diff --git a/challenge-189/bruce-gray/blog.txt b/challenge-189/bruce-gray/blog.txt new file mode 100644 index 0000000000..61dc741db9 --- /dev/null +++ b/challenge-189/bruce-gray/blog.txt @@ -0,0 +1 @@ +http://blogs.perl.org/users/bruce_gray/2022/11/twc-189-saving-your-degree-by-great-character.html diff --git a/challenge-189/bruce-gray/perl/ch-1.pl b/challenge-189/bruce-gray/perl/ch-1.pl new file mode 100755 index 0000000000..078217d02b --- /dev/null +++ b/challenge-189/bruce-gray/perl/ch-1.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +use v5.36; +use List::Util qw; + +sub task1 ( $aref, $target ) { + my @gt = grep { $_ gt $target } @{$aref}; + + return @gt ? minstr(@gt) : $target; +} + + +my @tests = ( + [ [qw], 'b', 'e' ], + [ [qw], 'a', 'c' ], + [ [qw], 'o', 'r' ], + [ [qw], 'a', 'c' ], + [ [qw], 'v', 'v' ], +); +use Test::More; +plan tests => 0+@tests; +for (@tests) { + my ( $aref, $target, $expected ) = @{$_}; + is task1($aref, $target), $expected, "task1(qw<@{$aref}>)"; +} diff --git a/challenge-189/bruce-gray/perl/ch-2.pl b/challenge-189/bruce-gray/perl/ch-2.pl new file mode 100755 index 0000000000..0c15094764 --- /dev/null +++ b/challenge-189/bruce-gray/perl/ch-2.pl @@ -0,0 +1,58 @@ +#!/usr/bin/env perl +use v5.36; +use experimental qw; +use builtin qw; +use List::UtilsBy qw; + +# See blog post for shorter code using List::Categorize. +sub task2 ( @a ) { + my %h; + for my ($k, $v) (indexed @a) { + my $href = ( $h{$v} //= {} ); + + $href->{KEY } = $v; + $href->{COUNT} += 1; + $href->{FIRST} //= $k; + $href->{LAST } = $k; + } + $_->{SPAN} = $_->{LAST} - $_->{FIRST} + 1 for values %h; + + my $best = min_by { $_->{FIRST} } + min_by { $_->{SPAN } } + max_by { $_->{COUNT} } + values %h; + + return [ @a[ $best->{FIRST} .. $best->{LAST} ] ]; +} + + +my @tests = ( + # From TWC examples: + [ [ 1, 3, 3, 2 ] , [ 3, 3 ] ], + [ [ 1, 2, 1, 3 ] , [ 1, 2, 1 ] ], + [ [ 1, 3, 2, 1, 2 ] , [ 2, 1, 2 ] ], + [ [ 1, 1, 2, 3, 2 ] , [ 1, 1 ] ], + [ [ 2, 1, 2, 1, 1 ] , [ 1, 2, 1, 1 ] ], + + # TWC examples translated to alpha, for easier debugging. + [ [qw] , [qw ] ], + [ [qw] , [qw ] ], + [ [qw] , [qw ] ], + [ [qw] , [qw ] ], + [ [qw] , [qw] ], + + # Numeric and alpha versions to stress tie-breaking rules: + [ [qw<1 1 2 2 2 2 1 1> ] , [qw<2 2 2 2>] ], + [ [qw ] , [qw] ], + [ [qw<1 1 1 1 2 2 2 2> ] , [qw<1 1 1 1>] ], + [ [qw ] , [qw] ], + [ [qw<1 1 1 1 2 3 2 2 2> ] , [qw<1 1 1 1>] ], + [ [qw ] , [qw] ], + +); +use Test::More; +plan tests => 0+@tests; +for (@tests) { + my ( $in_aref, $expected_aref ) = @{$_}; + is_deeply task2(@{$in_aref}), $expected_aref, "task2(qw<@{$in_aref}>)"; +} diff --git a/challenge-189/bruce-gray/raku/ch-1.raku b/challenge-189/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..8326be5886 --- /dev/null +++ b/challenge-189/bruce-gray/raku/ch-1.raku @@ -0,0 +1,20 @@ +sub task1 ( @a, Str $target --> Str ) { + return .elems ?? .min !! $target given @a.grep( * gt $target ); + + # Single-pass too-clever alternative: + # return @a.min({ $_ !gt $target, $_ }) max $target; +} + + +my @tests = + ( , 'b', 'e' ), + ( , 'a', 'c' ), + ( , 'o', 'r' ), + ( , 'a', 'c' ), + ( , 'v', 'v' ), + ; +use Test; +plan +@tests; +for @tests -> ( @array, $target, $expected ) { + is task1( @array, $target), $expected, "task1(<@array[]>)"; +} diff --git a/challenge-189/bruce-gray/raku/ch-2.raku b/challenge-189/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..c0612139cc --- /dev/null +++ b/challenge-189/bruce-gray/raku/ch-2.raku @@ -0,0 +1,39 @@ +sub task2 ( @a ) { + my $best = + @a.pairs # index => element + .classify( {.value}, :as{.key} ) # element_A => [Ai0, Ai1, … Ai_last], … + .map({ .value }) # [Ai0, Ai1, … Ai_last], [Bi0, Bi1, … Bi_last], … + .max({ .elems, -(.tail - .head + 1), -.head }); # Highest degree with lowest slice_size + + return @a[ $best.head .. $best.tail ]; +} + + +my @tests = + # From TWC examples: + ( (1, 3, 3, 2) , (3, 3) ), + ( (1, 2, 1, 3) , (1, 2, 1) ), + ( (1, 3, 2, 1, 2) , (2, 1, 2) ), + ( (1, 1, 2, 3, 2) , (1, 1) ), + ( (2, 1, 2, 1, 1) , (1, 2, 1, 1) ), + + # TWC examples translated to alpha, for easier debugging. + ( , ), + ( , ), + ( , ), + ( , ), + ( , ), + + # Numeric and alpha versions to stress tie-breaking rules: + ( <1 1 2 2 2 2 1 1> , <2 2 2 2> ), + ( , ), + ( <1 1 1 1 2 2 2 2> , <1 1 1 1> ), + ( , ), + ( <1 1 1 1 2 3 2 2 2> , <1 1 1 1> ), + ( , ), +; +use Test; +plan +@tests; +for @tests -> ( @array, @expected ) { + is-deeply task2(@array), @expected, "task2(<@array[]>)"; +} -- cgit