aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2023-04-30 10:12:16 +0100
committerGitHub <noreply@github.com>2023-04-30 10:12:16 +0100
commitd0e2c9219d6d18ff356fa128be77779f67c91f7b (patch)
tree71aff16c815c0f1f711e51072f39cb3882cc247f
parent24fb23a0514e036309912b139294d867bf918b57 (diff)
parent8591be4ff4e162505935019238c2f2a43352b7a7 (diff)
downloadperlweeklychallenge-club-d0e2c9219d6d18ff356fa128be77779f67c91f7b.tar.gz
perlweeklychallenge-club-d0e2c9219d6d18ff356fa128be77779f67c91f7b.tar.bz2
perlweeklychallenge-club-d0e2c9219d6d18ff356fa128be77779f67c91f7b.zip
Merge pull request #7979 from boblied/w214
W214
-rw-r--r--challenge-213/bob-lied/blog.txt1
-rw-r--r--challenge-214/bob-lied/README6
-rw-r--r--challenge-214/bob-lied/blog.txt1
-rw-r--r--challenge-214/bob-lied/perl/ch-1.pl84
-rw-r--r--challenge-214/bob-lied/perl/ch-2.pl134
5 files changed, 223 insertions, 3 deletions
diff --git a/challenge-213/bob-lied/blog.txt b/challenge-213/bob-lied/blog.txt
new file mode 100644
index 0000000000..3288347232
--- /dev/null
+++ b/challenge-213/bob-lied/blog.txt
@@ -0,0 +1 @@
+https://dev.to/boblied/pwc-213-a-fun-sort-and-a-run-short-41d5
diff --git a/challenge-214/bob-lied/README b/challenge-214/bob-lied/README
index ca4d14b3b4..4f6ce65387 100644
--- a/challenge-214/bob-lied/README
+++ b/challenge-214/bob-lied/README
@@ -1,4 +1,4 @@
-Solutions to weekly challenge 213 by Bob Lied
+Solutions to weekly challenge 214 by Bob Lied
-https://perlweeklychallenge.org/blog/perl-weekly-challenge-213/
-https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-213/bob-lied
+https://perlweeklychallenge.org/blog/perl-weekly-challenge-214/
+https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-214/bob-lied
diff --git a/challenge-214/bob-lied/blog.txt b/challenge-214/bob-lied/blog.txt
new file mode 100644
index 0000000000..17c030c202
--- /dev/null
+++ b/challenge-214/bob-lied/blog.txt
@@ -0,0 +1 @@
+https://dev.to/boblied/pwc-214-1-rank-score-2-collect-points-3-4-profit-4adh
diff --git a/challenge-214/bob-lied/perl/ch-1.pl b/challenge-214/bob-lied/perl/ch-1.pl
new file mode 100644
index 0000000000..ef028763ac
--- /dev/null
+++ b/challenge-214/bob-lied/perl/ch-1.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# ch-1.pl Perl Weekly Challenge 214 Task 1 Rank Score
+#=============================================================================
+# Copyright (c) 2023, Bob Lied
+#=============================================================================
+# You are given a list of scores (>=1).
+# Write a script to rank each score in descending order. First three will get
+# medals i.e. G (Gold), S (Silver) and B (Bronze). Rest will just get the
+# ranking number.
+# Using the standard model of giving equal scores equal rank,
+# then advancing that number of ranks.
+# Example 1 Input: @scores = (1,2,4,3,5) Output: (5,4,S,B,G)
+# Example 2 Input: @scores = (8,5,6,7,4) Output: (G,4,B,S,5)
+# Example 3 Input: @list = (3,5,4,2) Output: (B,G,S,4)
+# Example 4 Input: @scores = (2,5,2,1,7,5,1) Output: (4,S,4,6,G,S,6)
+#=============================================================================
+
+use v5.36;
+
+use FindBin qw($Bin);
+use lib "$FindBin::Bin";
+
+use Getopt::Long;
+my $Verbose = 0;
+my $DoTest = 0;
+
+GetOptions("test" => \$DoTest, "verbose" => \$Verbose);
+exit(!runTest()) if $DoTest;
+
+say "(", join(",", rankScore(@ARGV)->@*), ")";
+
+sub rankScore(@scoreList)
+{
+ return [] unless @scoreList;
+
+ # Record position of each score if it was sorted descending.
+ # Example: [0] [1] [2] [3] [4]
+ # @scoreList = ( 1 2 4 3 5 )
+ # --> @position = ( 4 3 1 2 0 )
+ my @position = sort { $scoreList[$b] <=> $scoreList[$a] } 0 .. $#scoreList;
+
+ # The colors or places that will be assigned.
+ my @rank = ( qw(G S B), 4 .. (@scoreList) );
+ my $r = 0; # Index into @rank
+
+ # In a copy of the scores, replace each score by its medal or rank.
+ my @ranked = @scoreList;
+
+ # The first position is always gold.
+ my $place = $position[0];
+ $ranked[ $place ] = $rank[$r];
+
+ # Move through consecutive pairs of positions to see when to switch
+ # rank colors.
+ for my $index ( 1 .. $#position )
+ {
+ my $next = $position[$index];
+ if ( $scoreList[$next] < $scoreList[$place] )
+ {
+ # Lower score, so advance rank
+ $r = $index;
+ }
+ $ranked[$next] = $rank[$r];
+ $place = $next;
+ }
+ return \@ranked;
+}
+
+sub runTest
+{
+ use Test2::V0;
+
+ is( rankScore(1,2,4,3,5), [ qw(5 4 S B G) ], "Example 1");
+ is( rankScore(8,5,6,7,4), [ qw(G 4 B S 5) ], "Example 2");
+ is( rankScore(3,5,4,2), [ qw(B G S 4) ], "Example 3");
+ is( rankScore(2,5,2,1,7,5,1), [ qw(4 S 4 6 G S 6) ], "Example 4");
+ is( rankScore(2,7,7,1,7,5,1), [ qw(5 G G 6 G 4 6) ], "Gold only");
+ is( rankScore(3,5 ), [ qw(S G ) ], "Two players");
+
+ done_testing;
+}
+
diff --git a/challenge-214/bob-lied/perl/ch-2.pl b/challenge-214/bob-lied/perl/ch-2.pl
new file mode 100644
index 0000000000..c1260bb297
--- /dev/null
+++ b/challenge-214/bob-lied/perl/ch-2.pl
@@ -0,0 +1,134 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# ch-2.pl Perl Weekly Challenge 214 Task 2 Collect Points
+#=============================================================================
+# Copyright (c) 2023, Bob Lied
+#=============================================================================
+# You are given a list of numbers.
+# You will perform a series of removal operations. For each operation, you
+# remove from the list N (one or more) equal and consecutive numbers, and add
+# to your score N × N. Determine the maximum possible score.
+# Example 1: Input: @numbers = (2,4,3,3,3,4,5,4,2) Output: 23
+# We see three 3's next to each other so let us remove that first and
+# collect 3 x 3 points. So now the list is (2,4,4,5,4,2).
+# Let us now remove 5 so that all 4's can be next to each other and
+# collect 1 x 1 point. So now the list is (2,4,4,4,2).
+# Time to remove three 4's and collect 3 x 3 points. Now the list is (2,2).
+# Finally remove both 2's and collect 2 x 2 points.
+# So the total points collected is 9 + 1 + 9 + 4 => 23.
+# Example 2: Input: @numbers = (1,2,2,2,2,1) Output: 20
+# Remove four 2's first and collect 4 x 4 points. Now the list is (1,1).
+# Finally remove the two 1's and collect 2 x 2 points.
+# So the total points collected is 16 + 4 => 20.
+# Example 3: Input: @numbers = (1) Output: 1
+# Example 4: Input: @numbers = (2,2,2,1,1,2,2,2) Output: 40
+# Remove two 1's = 2 x 2 points. Now the list is (2,2,2,2,2,2).
+# Then reomove six 2's = 6 x 6 points.
+#=============================================================================
+
+use v5.36;
+
+use Getopt::Long;
+my $Verbose = 0;
+my $DoTest = 0;
+
+GetOptions("test" => \$DoTest, "verbose" => \$Verbose);
+exit(!runTest()) if $DoTest;
+
+say collectPoints(@ARGV);
+
+# Return pairs of [offset, length] for each span of equal values in list
+sub findSpan($list)
+{
+ my $listLength = @$list;
+ if ( $listLength == 0 ) { return [] }
+ elsif ( $listLength == 1 ) { return [ [0, 1] ] }
+
+ my @span;
+
+ my $beg = my $end = 0;
+ my $len = 1;
+ while ( $end < $listLength )
+ {
+ while ( $end < $list->$#* && $list->[$end+1] == $list->[$end] )
+ {
+ $end++;
+ $len++;
+ }
+ push @span, [ $beg, $len ];
+ $beg = ++$end;
+ $len = 1;
+ }
+ return \@span;
+}
+
+# Recursive function to do depth-first searches for best score
+sub _collect($list, $scoreSoFar, $indent)
+{
+ say "$indent _collect[ $list->@* ], $scoreSoFar" if $Verbose;
+
+ my $numLen = @$list;
+ if ( $numLen == 0 ) { return $scoreSoFar; }
+ elsif ( $numLen == 1 ) { return $scoreSoFar + 1; }
+ elsif ( $numLen == 2 )
+ {
+ return $scoreSoFar + ($list->[0] == $list->[1] ? 4 : 2 );
+ }
+
+ my $spanList = findSpan($list);
+
+ my $bestScore = 0;
+ for my $span ( @$spanList )
+ {
+ my ($beg, $length) = $span->@*;
+ my $score = $length * $length;
+
+ # Remove the span from the list and recurse
+ my @copy = $list->@*;
+ if ( $Verbose )
+ {
+ my @rmv = $list->@[$beg .. $beg+$length-1];
+ splice(@copy, $beg, $length, ('*')x$length);
+ say "$indent RMV [@rmv], copy=[@copy] score=$score";
+ }
+
+ splice(@copy, $beg, $length);
+
+ $score = _collect(\@copy, $score, " $indent");
+ if ( $score > $bestScore )
+ {
+ $bestScore = $score;
+ say "$indent BEST: $bestScore" if $Verbose;
+ }
+ }
+ return $scoreSoFar + $bestScore;
+}
+
+sub collectPoints(@numbers)
+{
+ return _collect(\@numbers, 0, "");
+}
+
+sub runTest
+{
+ use Test2::V0;
+
+ is( findSpan( [9] ), [ [0,1] ], "findSpan singleton");
+ is( findSpan( [4,5,6] ), [ [0,1],[1,1],[2,1] ], "unique");
+ is( findSpan( [4,4,5,6] ), [ [0,2],[2,1],[3,1] ], "leading span");
+ is( findSpan( [4,5,6,6] ), [ [0,1],[1,1],[2,2] ], "trailing span");
+ is( findSpan( [4,5,5,6] ), [ [0,1],[1,2],[3,1] ], "middle span");
+
+ is( collectPoints(2), 1, "Singleton");
+ is( collectPoints(2,3), 2, "Small");
+ is( collectPoints(2,2), 4, "Pair");
+ is( collectPoints(2,2,2), 9, "Triplet");
+ is( collectPoints(2,4,3,3,3,4,5,4,2), 23, "Example 1");
+ is( collectPoints(1,2,2,2,2,1 ), 20, "Example 2");
+ is( collectPoints(1 ), 1, "Example 3");
+ is( collectPoints(2,2,2,1,1,2,2,2 ), 40, "Example 4");
+
+ done_testing;
+}
+