aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-02-08 19:37:42 +0000
committerGitHub <noreply@github.com>2025-02-08 19:37:42 +0000
commit07276cdf06f7ac9646bc88c5c417191894c4ef53 (patch)
tree37578ce177b11a62a09c683d627d3d0208c9aff3
parent9da701c4cdcd5e30f92fc90201187fee65604a8a (diff)
parentd90b8ac31ce7f559d252c6f39032b2d388bb2a9e (diff)
downloadperlweeklychallenge-club-07276cdf06f7ac9646bc88c5c417191894c4ef53.tar.gz
perlweeklychallenge-club-07276cdf06f7ac9646bc88c5c417191894c4ef53.tar.bz2
perlweeklychallenge-club-07276cdf06f7ac9646bc88c5c417191894c4ef53.zip
Merge pull request #11540 from boblied/w307
Week 307 solutions
-rw-r--r--challenge-307/bob-lied/README6
-rw-r--r--challenge-307/bob-lied/perl/ch-1.pl76
-rw-r--r--challenge-307/bob-lied/perl/ch-2.pl128
3 files changed, 207 insertions, 3 deletions
diff --git a/challenge-307/bob-lied/README b/challenge-307/bob-lied/README
index 3a6c40ed45..b3605f1ed5 100644
--- a/challenge-307/bob-lied/README
+++ b/challenge-307/bob-lied/README
@@ -1,4 +1,4 @@
-Solutions to weekly challenge 306 by Bob Lied
+Solutions to weekly challenge 307 by Bob Lied
-https://perlweeklychallenge.org/blog/perl-weekly-challenge-306/
-https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-306/bob-lied
+https://perlweeklychallenge.org/blog/perl-weekly-challenge-307/
+https://github.com/boblied/perlweeklychallenge-club/tree/master/challenge-307/bob-lied
diff --git a/challenge-307/bob-lied/perl/ch-1.pl b/challenge-307/bob-lied/perl/ch-1.pl
new file mode 100644
index 0000000000..5cfc13335a
--- /dev/null
+++ b/challenge-307/bob-lied/perl/ch-1.pl
@@ -0,0 +1,76 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# Copyright (c) 2025, Bob Lied
+#=============================================================================
+# ch-1.pl Perl Weekly Challenge 307 Task 1 Check Order
+#=============================================================================
+# You are given an array of integers, @ints.
+# Write a script to re-arrange the given array in an increasing order and
+# return the indices where it differs from the original array.
+# Example 1 Input: @ints = (5, 2, 4, 3, 1)
+# Output: (0, 2, 3, 4)
+# Before: (5, 2, 4, 3, 1)
+# After : (1, 2, 3, 4, 5)
+# Difference at indices: (0, 2, 3, 4)
+# Example 2 Input: @ints = (1, 2, 1, 1, 3)
+# Output: (1, 3)
+# Before: (1, 2, 1, 1, 3)
+# After : (1, 1, 1, 2, 3)
+# Difference at indices: (1, 3)
+# Example 3 Input: @ints = (3, 1, 3, 2, 3)
+# Output: (0, 1, 3)
+# Before: (3, 1, 3, 2, 3)
+# After : (1, 2, 3, 3, 3)
+# Difference at indices: (0, 1, 3)
+#=============================================================================
+
+use v5.40;
+
+
+use Getopt::Long;
+my $Verbose = false;
+my $DoTest = false;
+my $Benchmark = 0;
+
+GetOptions("test" => \$DoTest, "verbose" => \$Verbose, "benchmark:i" => \$Benchmark);
+my $logger;
+{
+ use Log::Log4perl qw(:easy);
+ Log::Log4perl->easy_init({ level => ($Verbose ? $DEBUG : $INFO ),
+ layout => "%d{HH:mm:ss.SSS} %p{1} %m%n" });
+ $logger = Log::Log4perl->get_logger();
+}
+#=============================================================================
+
+exit(!runTest()) if $DoTest;
+exit( runBenchmark($Benchmark) ) if $Benchmark;
+
+say '(', join(', ', checkOrder(@ARGV)->@*), ')';
+
+#=============================================================================
+sub checkOrder(@ints)
+{
+ my @sorted = sort { $a <=> $b } @ints;
+ return [ grep { $ints[$_] != $sorted[$_] } 0 .. $#ints ];
+}
+
+sub runTest
+{
+ use Test2::V0;
+
+ is( checkOrder(5,2,4,3,1), [0,2,3,4], "Example 1");
+ is( checkOrder(1,2,1,1,3), [1,3 ], "Example 2");
+ is( checkOrder(3,1,3,2,3), [0,1,3 ], "Example 3");
+
+ done_testing;
+}
+
+sub runBenchmark($repeat)
+{
+ use Benchmark qw/cmpthese/;
+
+ cmpthese($repeat, {
+ label => sub { },
+ });
+}
diff --git a/challenge-307/bob-lied/perl/ch-2.pl b/challenge-307/bob-lied/perl/ch-2.pl
new file mode 100644
index 0000000000..5b5a7c84a9
--- /dev/null
+++ b/challenge-307/bob-lied/perl/ch-2.pl
@@ -0,0 +1,128 @@
+#!/usr/bin/env perl
+# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu:
+#=============================================================================
+# Copyright (c) 2025, Bob Lied
+#=============================================================================
+# ch-2.pl Perl Weekly Challenge 307 Task 2 Find Anagrams
+#=============================================================================
+# You are given a list of words, @words.
+# Write a script to find any two consecutive words and if they are anagrams,
+# drop the first word and keep the second. You continue this until there is
+# no more anagrams in the given list and return the count of final list.
+# Example 1 Input: @words = ("acca", "dog", "god", "perl", "repl")
+# Output: 3
+# Step 1: "dog" and "god" are anagrams, so drop "dog" and keep "god"
+# => ("acca", "god", "perl", "repl")
+# Step 2: "perl" and "repl" are anagrams, so drop "perl" and keep "repl"
+# => ("acca", "god", "repl")
+#
+# Example 2 Input: @words = ("abba", "baba", "aabb", "ab", "ab")
+# Output: 2
+# Step 1: "abba" and "baba" are anagrams, so drop "abba" and keep "baba"
+# => ("baba", "aabb", "ab", "ab")
+# Step 2: "baba" and "aabb" are anagrams, so drop "baba" and keep "aabb"
+# => ("aabb", "ab", "ab")
+# Step 3: "ab" and "ab" are anagrams, so drop "ab" and keep "ab"
+# => ("aabb", "ab")
+#=============================================================================
+
+use v5.40;
+
+
+use Getopt::Long;
+my $Verbose = false;
+my $DoTest = false;
+my $Benchmark = 0;
+
+GetOptions("test" => \$DoTest, "verbose" => \$Verbose, "benchmark:i" => \$Benchmark);
+my $logger;
+{
+ use Log::Log4perl qw(:easy);
+ Log::Log4perl->easy_init({ level => ($Verbose ? $DEBUG : $INFO ),
+ layout => "%d{HH:mm:ss.SSS} %p{1} %m%n" });
+ $logger = Log::Log4perl->get_logger();
+}
+#=============================================================================
+
+exit(!runTest()) if $DoTest;
+exit( runBenchmark($Benchmark) ) if $Benchmark;
+
+say findAnagram_general(@ARGV);
+
+#=============================================================================
+use Memoize;
+memoize("canonical");
+sub canonical($word)
+{
+ join "", sort split //, $word
+}
+
+sub findAnagram(@words)
+{
+ my @out = ( $words[0] );
+ for my $i ( 0 .. $#words-1 )
+ {
+ if ( canonical($words[$i]) eq canonical($words[$i+1]) )
+ {
+ $out[-1] = $words[$i+1];
+ }
+ else
+ {
+ push @out, $words[$i+1]
+ }
+ }
+ return scalar(@out);
+}
+
+sub fa(@words)
+{
+ my @out = ( my $first = shift @words );
+ while ( defined(my $second = shift @words) )
+ {
+ if ( canonical($first) eq canonical($second) )
+ {
+ $out[-1] = $second;
+ }
+ else
+ {
+ push @out, $second;
+ }
+ $first = $second;
+ }
+ return scalar(@out);
+}
+
+# If the anagrams can appear anywhere, it amounts to finding all the unique ones.
+# Despite the hashing overhead, this is twice as fast as the loops over pairs.
+sub findAnagram_general(@words)
+{
+ my %base;
+ $base{ canonical($_) }++ for @words;
+ return scalar %base;
+
+}
+
+sub runTest
+{
+ use Test2::V0;
+
+ is( findAnagram("acca", "dog", "god", "perl", "repl"), 3, "Example 1");
+ is( findAnagram("abba", "baba", "aabb", "ab", "ab" ), 2, "Example 2");
+
+ is( fa("acca", "dog", "god", "perl", "repl"), 3, "Example 1");
+ is( fa("abba", "baba", "aabb", "ab", "ab" ), 2, "Example 2");
+
+ done_testing;
+}
+
+sub runBenchmark($repeat)
+{
+ use Benchmark qw/cmpthese/;
+ my @words = ( "aa" .. "iz", 'aa' .. 'iz');
+
+ cmpthese($repeat, {
+ forloop => sub { findAnagram(@words) },
+ shifting => sub { fa(@words) },
+ general => sub { findAnagram_general(@words) },
+ });
+}