diff options
| -rw-r--r-- | challenge-189/bruce-gray/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-189/bruce-gray/perl/ch-1.pl | 24 | ||||
| -rwxr-xr-x | challenge-189/bruce-gray/perl/ch-2.pl | 58 | ||||
| -rw-r--r-- | challenge-189/bruce-gray/raku/ch-1.raku | 20 | ||||
| -rw-r--r-- | challenge-189/bruce-gray/raku/ch-2.raku | 39 |
5 files changed, 142 insertions, 0 deletions
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<minstr>; + +sub task1 ( $aref, $target ) { + my @gt = grep { $_ gt $target } @{$aref}; + + return @gt ? minstr(@gt) : $target; +} + + +my @tests = ( + [ [qw<e m u g>], 'b', 'e' ], + [ [qw<d c e f>], 'a', 'c' ], + [ [qw<j a r >], 'o', 'r' ], + [ [qw<d c a f>], 'a', 'c' ], + [ [qw<t g a l>], '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<for_list builtin>; +use builtin qw<indexed>; +use List::UtilsBy qw<max_by min_by>; + +# 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<A C C B >] , [qw<C C> ] ], + [ [qw<A B A C >] , [qw<A B A> ] ], + [ [qw<A C B A B>] , [qw<B A B> ] ], + [ [qw<A A B C B>] , [qw<A A> ] ], + [ [qw<B A B A A>] , [qw<A B A A>] ], + + # Numeric and alpha versions to stress tie-breaking rules: + [ [qw<1 1 2 2 2 2 1 1> ] , [qw<2 2 2 2>] ], + [ [qw<A A B B B B A A> ] , [qw<B B B B>] ], + [ [qw<1 1 1 1 2 2 2 2> ] , [qw<1 1 1 1>] ], + [ [qw<A A A A B B B B> ] , [qw<A A A A>] ], + [ [qw<1 1 1 1 2 3 2 2 2> ] , [qw<1 1 1 1>] ], + [ [qw<A A A A B C B B B> ] , [qw<A A A A>] ], + +); +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 = + ( <e m u g>, 'b', 'e' ), + ( <d c e f>, 'a', 'c' ), + ( <j a r >, 'o', 'r' ), + ( <d c a f>, 'a', 'c' ), + ( <t g a l>, '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. + ( <A C C B > , <C C> ), + ( <A B A C > , <A B A> ), + ( <A C B A B> , <B A B> ), + ( <A A B C B> , <A A> ), + ( <B A B A A> , <A B A A> ), + + # Numeric and alpha versions to stress tie-breaking rules: + ( <1 1 2 2 2 2 1 1> , <2 2 2 2> ), + ( <A A B B B B A A> , <B B B B> ), + ( <1 1 1 1 2 2 2 2> , <1 1 1 1> ), + ( <A A A A B B B B> , <A A A A> ), + ( <1 1 1 1 2 3 2 2 2> , <1 1 1 1> ), + ( <A A A A B C B B B> , <A A A A> ), +; +use Test; +plan +@tests; +for @tests -> ( @array, @expected ) { + is-deeply task2(@array), @expected, "task2(<@array[]>)"; +} |
