aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2024-03-04 00:16:36 +0000
committerGitHub <noreply@github.com>2024-03-04 00:16:36 +0000
commit294419e7a4ddf2ce599ed9b11cd16415381d6ea1 (patch)
treeb128129d47cc7a41dd13cfe98ef2a43afc3a5b3e
parent0478d96b0dfdf673f15eddcde2d6ef2b8d4c85b4 (diff)
parentef81e78d3ed87b36f7c00130874691433f97107e (diff)
downloadperlweeklychallenge-club-294419e7a4ddf2ce599ed9b11cd16415381d6ea1.tar.gz
perlweeklychallenge-club-294419e7a4ddf2ce599ed9b11cd16415381d6ea1.tar.bz2
perlweeklychallenge-club-294419e7a4ddf2ce599ed9b11cd16415381d6ea1.zip
Merge pull request #9686 from MatthiasMuth/muthm-258
Challenge 258 Task 1 and 2 solutions in Perl by Matthias Muth
-rw-r--r--challenge-258/matthias-muth/README.md148
-rw-r--r--challenge-258/matthias-muth/blog.txt1
-rwxr-xr-xchallenge-258/matthias-muth/perl/ch-1.pl24
-rwxr-xr-xchallenge-258/matthias-muth/perl/ch-2.pl30
-rw-r--r--challenge-258/matthias-muth/perl/challenge-258.txt58
5 files changed, 168 insertions, 93 deletions
diff --git a/challenge-258/matthias-muth/README.md b/challenge-258/matthias-muth/README.md
index e483f78d49..05da216c90 100644
--- a/challenge-258/matthias-muth/README.md
+++ b/challenge-258/matthias-muth/README.md
@@ -1,126 +1,88 @@
-# Challenge 256 tasks: Easy Pairs - Easy Merge
-**Challenge 256 solutions in Perl by Matthias Muth**
+# You Only Grep Twice
-## Task 1: Maximum Pairs
+**Challenge 258 solutions in Perl by Matthias Muth**
-> You are given an array of distinct words, `@words`.<br/>
-> Write a script to find the maximum pairs in the given array. The words `$words[i]` and `$words[j]` can be a pair one is reverse of the other.<br/>
+## Task 1: Count Even Digits Number
+
+> You are given a array of positive integers, @ints.<br/>
+> Write a script to find out how many integers have even number of digits.<br/>
> <br/>
> Example 1<br/>
-> Input: @words = ("ab", "de", "ed", "bc")<br/>
-> Output: 1<br/>
-> There is one pair in the given array: "de" and "ed"<br/>
+> Input: @ints = (10, 1, 111, 24, 1000)<br/>
+> Output: 3<br/>
+> There are 3 integers having even digits i.e. 10, 24 and 1000.<br/>
> <br/>
> Example 2<br/>
-> Input: @words = ("aa", "ba", "cd", "ed")<br/>
+> Input: @ints = (111, 1, 11111)<br/>
> Output: 0<br/>
> <br/>
> Example 3<br/>
-> Input: @words = ("uv", "qp", "st", "vu", "mn", "pq"))<br/>
-> Output: 2<br/>
+> Input: @ints = (2, 8, 1024, 256)<br/>
+> Output: 1<br/>
-Ah, an easy one.<br/>
-For each word we check whether we have seen its reverse before, and increment
-our counter if so. Then we remember that we have seen the current word.
+This is a small exercise for using `grep`.<br/>
+We go through all values in the `@ints` array. For each value, we get the number of digits using the `length` function. Perl's type flexibility and implicit type conversion helps us here, in that the `length` returns the number of characters of the current value *as a string*.
-Perl supports us with the `reverse` function to reverse the characters of a string (also to reverse a list, but this is not what we use here).
+We then check whether this number is even, using this as a filter for `grep`.
-```perl
-#!/usr/bin/env perl
-use v5.36;
+When called in scalar context, `grep` returns the number of values that fulfill the criteria, not the list of values itself. As we are only interested in this number, we call `grep` in scalar context explicitly, and we are done.
-sub maximum_pairs( @words ) {
- my $n = 0;
- my %known;
- for ( @words ) {
- ++$n if $known{ reverse $_ };
- $known{$_} = 1;
- }
- return $n;
-}
-
-use Test2::V0 qw( -no_srand );
-is maximum_pairs( "ab", "de", "ed", "bc" ), 1,
- 'Example 1: maximum_pairs( ("ab", "de", "ed", "bc") ) == 1';
-is maximum_pairs( "aa", "ba", "cd", "ed" ), 0,
- 'Example 2: maximum_pairs( ("aa", "ba", "cd", "ed") ) == 0';
-is maximum_pairs( "uv", "qp", "st", "vu", "mn", "pq" ), 2,
- 'Example 3: maximum_pairs( ("uv", "qp", "st", "vu", "mn", "pq") ) == 2';
-done_testing;
-```
-
-If you don't have perl 5.36 (which I highly recommend!), you can use this
-instead:
+Long explanation, short code:
```perl
-use v5.20;
-use warnings;
-use feature 'signatures';
-no warnings 'experimental::signatures';
+use v5.36;
+sub count_even_digits_number( @ints ) {
+ return scalar grep length( $_ ) % 2 == 0, @ints;
+}
```
-Perl 5.20 has been around since 2014, so I guess that chances are high
-that your perl is more recent than that.<br/>
-If not, and you are not able to update your system's perl for any reason,
-I suggest installing [`perlbrew`](https://perlbrew.pl),
-which is an admin-free perl installation management tool.
-## Task 2: Merge Strings
+## Task 2: Sum of Values
-> You are given two strings, `$str1` and `$str2`.<br/>
-> Write a script to merge the given strings by adding in alternative order starting with the first string. If a string is longer than the other then append the remaining at the end.<br/>
+> You are given an array of integers, @int and an integer \$k.<br/>
+> Write a script to find the sum of values whose index binary representation has exactly \$k number of 1-bit set.<br/>
> <br/>
> Example 1<br/>
-> Input: \$str1 = "abcd", \$str2 = "1234"<br/>
-> Output: "a1b2c3d4"<br/>
+> Input: @ints = (2, 5, 9, 11, 3), \$k = 1<br/>
+> Output: 17<br/>
+> Binary representation of index 0 = 0<br/>
+> Binary representation of index 1 = 1<br/>
+> Binary representation of index 2 = 10<br/>
+> Binary representation of index 3 = 11<br/>
+> Binary representation of index 4 = 100<br/>
+> So the indices 1, 2 and 4 have total one 1-bit sets.<br/>
+> Therefore the sum, \$ints[1] + \$ints[2] + \$ints[3] = 17<br/>
> <br/>
> Example 2<br/>
-> Input: \$str1 = "abc", \$str2 = "12345"<br/>
-> Output: "a1b2c345"<br/>
+> Input: @ints = (2, 5, 9, 11, 3), \$k = 2<br/>
+> Output: 11<br/>
> <br/>
> Example 3<br/>
-> Input: \$str1 = "abcde", \$str2 = "123"<br/>
-> Output: "a1b2c3de"<br/>
-
-The idea for this challenge is to turn the two string into lists of characters,
-and then merge the two lists.<br/>
-There are a lot of functions for list manipulations in the `List::Util` core
-module, one of which is `mesh`. It does exactly what we need.
-The only downside is that if the lists are of different lengths, there will be
-`undef` values inserted in the result. But it is easy to `grep` those out
-before assembling the result into a return string.
-At least easier than splitting up the longer list into two parts, and after
-`mesh`ing the first part with the shorter string appending the second part.
-
-`mesh` has been part of `List::Util` since its version 1.56,
-which means has been part of standard Perl since Perl 5.25 (released in 2014).
-
-Its implementation is different from the `mesh` function in the
-`List::MoreUtils` CPAN module, in that it uses array references as parameters, not array variables that are used *by reference* (using prototypes).<br/>
-I prefer the `List::Util` version here,
-because we can directly use anonymous arrays containing the split characters as parameters,
-making it unnecessary to declare and use any array variables.
+> Input: @ints = (2, 5, 9, 11, 3), \$k = 0<br/>
+> Output: 2<br/>
-```perl
-#!/usr/bin/env perl
+This looks very similar. We also can use `grep`to select the values that we process further.<br/>
+But after reading the task again, and also checking the examples, we notice that in the filter, we don't use the numbers in the array, but the *index* of the numbers.
-use v5.36;
+So what we do is to use `grep` again, but this time, we go through all indexes instead of the values, filtering on the number of 1-bits that the index has, and then `map`the filtered indexes back to their array values. Then we can `sum` up those values.
-use List::Util qw( mesh );
+For getting the number of 1-bits in an integer number, probably the most efficient way is to use `unpack` with a `'%'` field prefix to do a checksum of the packed binary representation of our number (see examples in [perldoc](https://perldoc.perl.org/functions/unpack)). So for numbers at least up to 32 bits, this function does a marvelous job:
-sub merge_strings( $str1, $str2 ) {
- return join "",
- grep defined,
- mesh [ split //, $str1 ], [ split //, $str2 ];
+```perl
+use v5.36;
+sub n_bits( $n ) {
+ return unpack "%b*", pack "i", $n;
}
+```
+
+(`use v5.36;` is the shortest way to get function prototypes, which I don't want to miss.)
+
+The rest is straightforward:
-use Test2::V0 qw( -no_srand );
-is merge_strings( "abcd", 1234 ), "a1b2c3d4",
- 'Example 1: merge_strings( ("abcd", 1234) ) == "a1b2c3d4"';
-is merge_strings( "abc", 12345 ), "a1b2c345",
- 'Example 2: merge_strings( ("abc", 12345) ) == "a1b2c345"';
-is merge_strings( "abcde", 123 ), "a1b2c3de",
- 'Example 3: merge_strings( ("abcde", 123) ) == "a1b2c3de"';
-done_testing;
+```perl
+use List::Util qw( sum );
+sub sum_of_values( $ints, $k ) {
+ return sum map $ints->[$_], grep n_bits( $_ ) == $k, 0..$ints->$#*;
+}
```
#### **Thank you for the challenge!**
diff --git a/challenge-258/matthias-muth/blog.txt b/challenge-258/matthias-muth/blog.txt
new file mode 100644
index 0000000000..50c90fa6ea
--- /dev/null
+++ b/challenge-258/matthias-muth/blog.txt
@@ -0,0 +1 @@
+https://github.com/MatthiasMuth/perlweeklychallenge-club/tree/muthm-258/challenge-258/matthias-muth#readme
diff --git a/challenge-258/matthias-muth/perl/ch-1.pl b/challenge-258/matthias-muth/perl/ch-1.pl
new file mode 100755
index 0000000000..860860861b
--- /dev/null
+++ b/challenge-258/matthias-muth/perl/ch-1.pl
@@ -0,0 +1,24 @@
+#!/usr/bin/env perl
+#
+# The Weekly Challenge - Perl & Raku
+# (https://theweeklychallenge.org)
+#
+# Challenge 258 Task 1: Count Even Digits Number
+#
+# Perl solution by Matthias Muth.
+#
+
+use v5.36;
+
+sub count_even_digits_number( @ints ) {
+ return scalar grep length( $_ ) % 2 == 0, @ints;
+}
+
+use Test2::V0 qw( -no_srand );
+is count_even_digits_number( 10, 1, 111, 24, 1000 ), 3,
+ 'Example 1: count_even_digits_number( 10, 1, 111, 24, 1000 ) == 3';
+is count_even_digits_number( 111, 1, 11111 ), 0,
+ 'Example 2: count_even_digits_number( 111, 1, 11111 ) == 0';
+is count_even_digits_number( 2, 8, 1024, 256 ), 1,
+ 'Example 3: count_even_digits_number( 2, 8, 1024, 256 ) == 1';
+done_testing;
diff --git a/challenge-258/matthias-muth/perl/ch-2.pl b/challenge-258/matthias-muth/perl/ch-2.pl
new file mode 100755
index 0000000000..a46bb18134
--- /dev/null
+++ b/challenge-258/matthias-muth/perl/ch-2.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/env perl
+#
+# The Weekly Challenge - Perl & Raku
+# (https://theweeklychallenge.org)
+#
+# Challenge 258 Task 2: Sum of Values
+#
+# Perl solution by Matthias Muth.
+#
+
+use v5.36;
+
+use List::Util qw( sum );
+
+sub n_bits( $n ) {
+ return unpack "%b*", pack "i", $n;
+}
+
+sub sum_of_values( $ints, $k ) {
+ return sum map $ints->[$_], grep n_bits( $_ ) == $k, 0..$ints->$#*;
+}
+
+use Test2::V0 qw( -no_srand );
+is sum_of_values( [2, 5, 9, 11, 3], 1 ), 17,
+ 'Example 1: sum_of_values( [2, 5, 9, 11, 3], 1 ) == 17';
+is sum_of_values( [2, 5, 9, 11, 3], 2 ), 11,
+ 'Example 2: sum_of_values( [2, 5, 9, 11, 3], 2 ) == 11';
+is sum_of_values( [2, 5, 9, 11, 3], 0 ), 2,
+ 'Example 3: sum_of_values( [2, 5, 9, 11, 3], 0 ) == 2';
+done_testing;
diff --git a/challenge-258/matthias-muth/perl/challenge-258.txt b/challenge-258/matthias-muth/perl/challenge-258.txt
new file mode 100644
index 0000000000..ba1f16cedd
--- /dev/null
+++ b/challenge-258/matthias-muth/perl/challenge-258.txt
@@ -0,0 +1,58 @@
+The Weekly Challenge - 258
+Monday, Feb 26, 2024
+
+
+Task 1: Count Even Digits Number
+Submitted by: Mohammad Sajid Anwar
+
+You are given a array of positive integers, @ints.
+Write a script to find out how many integers have even number of digits.
+Example 1
+
+Input: @ints = (10, 1, 111, 24, 1000)
+Output: 3
+
+There are 3 integers having even digits i.e. 10, 24 and 1000.
+
+Example 2
+
+Input: @ints = (111, 1, 11111)
+Output: 0
+
+Example 3
+
+Input: @ints = (2, 8, 1024, 256)
+Output: 1
+
+
+Task 2: Sum of Values
+Submitted by: Mohammad Sajid Anwar
+
+You are given an array of integers, @int and an integer $k.
+Write a script to find the sum of values whose index binary representation has exactly $k number of 1-bit set.
+Example 1
+
+Input: @ints = (2, 5, 9, 11, 3), $k = 1
+Output: 17
+
+Binary representation of index 0 = 0
+Binary representation of index 1 = 1
+Binary representation of index 2 = 10
+Binary representation of index 3 = 11
+Binary representation of index 4 = 100
+
+So the indices 1, 2 and 4 have total one 1-bit sets.
+Therefore the sum, $ints[1] + $ints[2] + $ints[4] = 17
+
+Example 2
+
+Input: @ints = (2, 5, 9, 11, 3), $k = 2
+Output: 11
+
+Example 3
+
+Input: @ints = (2, 5, 9, 11, 3), $k = 0
+Output: 2
+
+
+Last date to submit the solution 23:59 (UK Time) Sunday 3rd March 2024.