diff options
| -rw-r--r-- | challenge-244/bob-lied/README | 6 | ||||
| -rw-r--r-- | challenge-244/bob-lied/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-244/bob-lied/perl/ch-1.pl | 112 | ||||
| -rw-r--r-- | challenge-244/bob-lied/perl/ch-2.pl | 76 |
4 files changed, 192 insertions, 3 deletions
diff --git a/challenge-244/bob-lied/README b/challenge-244/bob-lied/README index 342076e011..da2fb43649 100644 --- a/challenge-244/bob-lied/README +++ b/challenge-244/bob-lied/README @@ -1,4 +1,4 @@ -Solutions to weekly challenge 243 by Bob Lied +Solutions to weekly challenge 244 by Bob Lied -https://perlweeklychallenge.org/blog/perl-weekly-challenge-243/ -https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-243/bob-lied +https://perlweeklychallenge.org/blog/perl-weekly-challenge-244/ +https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-244/bob-lied diff --git a/challenge-244/bob-lied/blog.txt b/challenge-244/bob-lied/blog.txt new file mode 100644 index 0000000000..4e58ba1f05 --- /dev/null +++ b/challenge-244/bob-lied/blog.txt @@ -0,0 +1 @@ +https://dev.to/boblied/let-me-count-the-ways-pwc-244-count-smaller-583l diff --git a/challenge-244/bob-lied/perl/ch-1.pl b/challenge-244/bob-lied/perl/ch-1.pl new file mode 100644 index 0000000000..5e878a93ba --- /dev/null +++ b/challenge-244/bob-lied/perl/ch-1.pl @@ -0,0 +1,112 @@ +#!/usr/bin/env perl +# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu: +#============================================================================= +# ch-1.pl Perl Weekly Challenge 244 Task 1 Count Smaller +#============================================================================= +# Copyright (c) 2023, Bob Lied +#============================================================================= +# You are given an array of integers. +# Write a script to calculate the number of integers smaller than +# the integer at each index. +# Example 1 Input: @int = (8, 1, 2, 2, 3) +# Output: (4, 0, 1, 1, 3) +# For index = 0, count of elements less 8 is 4. +# For index = 1, count of elements less 1 is 0. +# For index = 2, count of elements less 2 is 1. +# For index = 3, count of elements less 2 is 1. +# For index = 4, count of elements less 3 is 3. +# Example 2 Input: @int = (6, 5, 4, 8) +# Output: (2, 1, 0, 3) +# Example 3 Input: @int = (2, 2, 2) +# Output: (0, 0, 0) +#============================================================================= + +use v5.38; +use builtin qw/true false/; no warnings "experimental::builtin"; + +use Getopt::Long; +my $Verbose = 0; +my $DoTest = 0; +my $DoBenchmark = 0; + +GetOptions("test" => \$DoTest, "verbose" => \$Verbose, "benchmark:i" => \$DoBenchmark); +exit( !runTest() ) if $DoTest; +exit( runBenchmark($DoBenchmark) ) if $DoBenchmark; + +say "(", join(",", countSmaller_C(\@ARGV)->@*), ")"; + +sub countSmaller_A($nums) +{ + my @sorted = sort { $a <=> $b } $nums->@*; + my @smaller = (); + for my $i ( $nums->@* ) + { + my $count = 0; + for my $j ( @sorted ) + { + last if $j >= $i; + $count++ + } + push @smaller, $count; + } + return \@smaller; +} + +sub countSmaller_B($nums) +{ + use List::Util qw/sum0/; + my %freq; + $freq{$_}++ for $nums->@*; + + return [ map { my $i = $_; sum0 @freq{ grep { $_ < $i } keys %freq } } $nums->@* ]; +} + +sub countSmaller_C($nums) +{ + my @sorted = sort { $a <=> $b } $nums->@*; + + my %smaller; + my $lessCount = 0; + while ( defined(my $i = shift @sorted) ) + { + if ( ! exists $smaller{$i} ) + { + $smaller{$i} = $lessCount; + } + $lessCount++ + } + + return [ @smaller{$nums->@*} ]; +} + +sub runTest +{ + use Test2::V0; + + is( countSmaller_A([8,1,2,2,3]), [4,0,1,1,3], "A Example 1"); + is( countSmaller_A([6,5,4,8 ]), [2,1,0,3 ], "A Example 2"); + is( countSmaller_A([2,2,2 ]), [0,0,0 ], "A Example 3"); + + is( countSmaller_B([8,1,2,2,3]), [4,0,1,1,3], "B Example 1"); + is( countSmaller_B([6,5,4,8 ]), [2,1,0,3 ], "B Example 2"); + is( countSmaller_B([2,2,2 ]), [0,0,0 ], "B Example 3"); + + is( countSmaller_C([8,1,2,2,3]), [4,0,1,1,3], "C Example 1"); + is( countSmaller_C([6,5,4,8 ]), [2,1,0,3 ], "C Example 2"); + is( countSmaller_C([2,2,2 ]), [0,0,0 ], "C Example 3"); + is( countSmaller_C([0,1,2,3,4]), [0,1,2,3,4], "C Example x"); + + done_testing; +} + +sub runBenchmark($repeat) +{ + use Benchmark qw/cmpthese/; + my @data = map { int(rand(100)) } 1..100; + + cmpthese($repeat, { + "simple " => sub { countSmaller_A(\@data) }, + "frequency" => sub { countSmaller_B(\@data) }, + "one pass " => sub { countSmaller_C(\@data) }, + }); +} diff --git a/challenge-244/bob-lied/perl/ch-2.pl b/challenge-244/bob-lied/perl/ch-2.pl new file mode 100644 index 0000000000..4cc3783ca8 --- /dev/null +++ b/challenge-244/bob-lied/perl/ch-2.pl @@ -0,0 +1,76 @@ +#!/usr/bin/env perl +# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu: +#============================================================================= +# ch-2.pl Perl Weekly Challenge 244 Task 2 Group Hero +#============================================================================= +# Copyright (c) 2023, Bob Lied +#============================================================================= +# You are given an array of integers representing the strength. +# Write a script to return the sum of the powers of all possible +# combinations; power is defined as the square of the largest number +# in a sequence, multiplied by the smallest. +# Example 1 Input: @nums = (2, 1, 4) +# Output: 141 +# Group 1: (2) => square(max(2)) * min(2) => 4 * 2 => 8 +# Group 2: (1) => square(max(1)) * min(1) => 1 * 1 => 1 +# Group 3: (4) => square(max(4)) * min(4) => 16 * 4 => 64 +# Group 4: (2,1) => square(max(2,1)) * min(2,1) => 4 * 1 => 4 +# Group 5: (2,4) => square(max(2,4)) * min(2,4) => 16 * 2 => 32 +# Group 6: (1,4) => square(max(1,4)) * min(1,4) => 16 * 1 => 16 +# Group 7: (2,1,4) => square(max(2,1,4)) * min(2,1,4) => 16 * 1 => 16 +# +# Sum: 8 + 1 + 64 + 4 + 32 + 16 + 16 => 141 +#============================================================================= + +use v5.38; +use builtin qw/true false/; no warnings "experimental::builtin"; + +use Getopt::Long; +my $Verbose = 0; +my $DoTest = 0; + +GetOptions("test" => \$DoTest, "verbose" => \$Verbose); +exit(!runTest()) if $DoTest; + +say groupHero(@ARGV); + +sub power(@n) +{ + use List::MoreUtils qw/minmax/; + + my ($min, $max); + if ( @n == 0 ) { return 0; } + elsif ( @n == 1 ) { ($min, $max) = ($n[0], $n[0]) } + else { ($min, $max) = minmax(@n) } + return $max * $max * $min; +} + +sub groupHero($nums) +{ + use Algorithm::Combinatorics qw/combinations/; + + my $sum = 0; + for my $k ( 1 .. scalar(@$nums) ) + { + for my $c ( combinations($nums, $k) ) + { + $sum += power( $c->@* ); + } + } + return $sum; +} + +sub runTest +{ + use Test2::V0; + + is( power( ), 0, "Power empty"); + is( power(2), 8, "Power 1 number"); + is( power(5,3), 75, "Power 2 numbers"); + is( power(5,4,3), 75, "Power 3 numbers"); + is( power(9, 5, 7, 1), 81, "Power 4 numbers"); + + is( groupHero([2,1,4]), 141, "Example 1"); + + done_testing; +} |
