aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-284/bob-lied/README6
-rw-r--r--challenge-284/bob-lied/perl/ch-1.pl60
-rw-r--r--challenge-284/bob-lied/perl/ch-2.pl106
3 files changed, 169 insertions, 3 deletions
diff --git a/challenge-284/bob-lied/README b/challenge-284/bob-lied/README
index 56099381f7..7aa2a6dd8a 100644
--- a/challenge-284/bob-lied/README
+++ b/challenge-284/bob-lied/README
@@ -1,4 +1,4 @@
-Solutions to weekly challenge 283 by Bob Lied
+Solutions to weekly challenge 284 by Bob Lied
-https://perlweeklychallenge.org/blog/perl-weekly-challenge-283/
-https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-283/bob-lied
+https://perlweeklychallenge.org/blog/perl-weekly-challenge-284/
+https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-284/bob-lied
diff --git a/challenge-284/bob-lied/perl/ch-1.pl b/challenge-284/bob-lied/perl/ch-1.pl
new file mode 100644
index 0000000000..ee4019e01f
--- /dev/null
+++ b/challenge-284/bob-lied/perl/ch-1.pl
@@ -0,0 +1,60 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# Copyright (c) 2024, Bob Lied
+#=============================================================================
+# ch-1.pl Perl Weekly Challenge 284 Task 1 Lucky Integer
+#=============================================================================
+# You are given an array of integers, @ints.
+# Write a script to find the lucky integer if found otherwise return -1.
+# If there are more than one then return the largest.
+# A lucky integer is an integer that has a frequency in the array equal
+# to its value.
+# Example 1 Input: @ints = (2, 2, 3, 4)
+# Output: 2
+# Example 2 Input: @ints = (1, 2, 2, 3, 3, 3)
+# Output: 3
+# Example 3 Input: @ints = (1, 1, 1, 3)
+# Output: -1
+#=============================================================================
+
+use v5.40;
+use List::Util qw/max/;
+
+use Getopt::Long;
+my $Verbose = false;
+my $DoTest = false;
+my $Benchmark = 0;
+
+GetOptions("test" => \$DoTest, "verbose" => \$Verbose, "benchmark:i" => \$Benchmark);
+exit(!runTest()) if $DoTest;
+exit( runBenchmark($Benchmark) ) if $Benchmark;
+
+say lucky(@ARGV);
+
+sub lucky(@ints)
+{
+ my %freq;
+ $freq{$_}++ for @ints;
+ max -1, grep { $freq{$_} == $_ } keys %freq;
+}
+
+sub runTest
+{
+ use Test2::V0;
+
+ is( lucky(2, 2, 3, 4 ), 2, "Example 1");
+ is( lucky(1, 2, 2, 3, 3, 3), 3, "Example 2");
+ is( lucky(1, 1, 1, 3 ), -1, "Example 2");
+
+ done_testing;
+}
+
+sub runBenchmark($repeat)
+{
+ use Benchmark qw/cmpthese/;
+
+ cmpthese($repeat, {
+ label => sub { },
+ });
+}
diff --git a/challenge-284/bob-lied/perl/ch-2.pl b/challenge-284/bob-lied/perl/ch-2.pl
new file mode 100644
index 0000000000..81eaad7ffa
--- /dev/null
+++ b/challenge-284/bob-lied/perl/ch-2.pl
@@ -0,0 +1,106 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# Copyright (c) 2024, Bob Lied
+#=============================================================================
+# ch-2.pl Perl Weekly Challenge 284 Task 2 Relativre Sort
+#=============================================================================
+# You are given two list of integers, @list1 and @list2. The elements
+# in the @list2 are distinct and also in the @list1.
+# Write a script to sort the elements in the @list1 such that the relative
+# order of items in @list1 is same as in the @list2. Elements that is
+# missing in @list2 should be placed at the end of @list1 in ascending order.
+# Example 1 Input: @list1 = (2, 3, 9, 3, 1, 4, 6, 7, 2, 8, 5)
+# @list2 = (2, 1, 4, 3, 5, 6)
+# Output: (2, 2, 1, 4, 3, 3, 5, 6, 7, 8, 9)
+# Example 2 Input: @list1 = (3, 3, 4, 6, 2, 4, 2, 1, 3)
+# @list2 = (1, 3, 2)
+# Output: (1, 3, 3, 3, 2, 2, 4, 4, 6)
+# Example 3 Input: @list1 = (3, 0, 5, 0, 2, 1, 4, 1, 1)
+# @list2 = (1, 0, 3, 2)
+# Output: (1, 1, 1, 0, 0, 3, 2, 4, 5)
+#=============================================================================
+
+use v5.40;
+use List::MoreUtils qw/part/;
+
+use Getopt::Long;
+my $Verbose = false;
+my $DoTest = false;
+my $Benchmark = 0;
+
+GetOptions("test" => \$DoTest, "verbose" => \$Verbose, "benchmark:i" => \$Benchmark);
+exit(!runTest()) if $DoTest;
+exit( runBenchmark($Benchmark) ) if $Benchmark;
+
+sub strToList($str)
+{
+ [ split(" ", ($str =~ s/\D+/ /gr)) ]
+}
+say "(", join(", ", relsort( strToList($ARGV[0]), strToList($ARGV[1]))->@*), ")";
+
+sub relsort($list1, $list2)
+{
+ # Invert list2 so that it maps a number to its order
+ my %order;
+ my $place = 0;
+ $order{$_} = $place++ for $list2->@*;
+
+ # Partition list1 into two parts:
+ # p[0] -- those that don't exist in list2
+ # p[1] -- those that exist in list2
+ my @p = List::MoreUtils::part { exists $order{$_} } $list1->@*;
+
+ my @result;
+ if ( defined $p[1] )
+ {
+ push @result, sort { $order{$a} <=> $order{$b} } $p[1]->@*;
+ }
+ if ( defined $p[0] )
+ {
+ push @result, sort { $a <=> $b } $p[0]->@*;
+ }
+ return \@result;
+}
+
+sub runTest
+{
+ use Test2::V0;
+ my @list1; my @list2; my @output;
+
+ @list1 = (2, 3, 9, 3, 1, 4, 6, 7, 2, 8, 5);
+ @list2 = (2, 1, 4, 3, 5, 6);
+ @output = (2, 2, 1, 4, 3, 3, 5, 6, 7, 8, 9);
+ is( relsort(\@list1, \@list2), \@output, "Example 1");
+
+ @list1 = (3, 3, 4, 6, 2, 4, 2, 1, 3);
+ @list2 = (1, 3, 2);
+ @output = (1, 3, 3, 3, 2, 2, 4, 4, 6);
+ is( relsort(\@list1, \@list2), \@output, "Example 2");
+
+ @list1 = (3, 0, 5, 0, 2, 1, 4, 1, 1);
+ @list2 = (1, 0, 3, 2);
+ @output = (1, 1, 1, 0, 0, 3, 2, 4, 5);
+ is( relsort(\@list1, \@list2), \@output, "Example 3");
+
+ @list1 = ( 1 .. 5 );
+ @list2 = ( 5, 4, 3, 2, 1 );
+ @output = ( 5, 4, 3, 2, 1 );
+ is( relsort(\@list1, \@list2), \@output, "No leftovers");
+
+ @list1 = ( 1 .. 5 );
+ @list2 = ( 7 .. 9 );
+ @output = ( 1 .. 5 );
+ is( relsort(\@list1, \@list2), \@output, "All leftovers");
+
+ done_testing;
+}
+
+sub runBenchmark($repeat)
+{
+ use Benchmark qw/cmpthese/;
+
+ cmpthese($repeat, {
+ label => sub { },
+ });
+}