diff options
| author | Mohammad Sajid Anwar <Mohammad.Anwar@yahoo.com> | 2024-03-04 00:16:36 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-04 00:16:36 +0000 |
| commit | 294419e7a4ddf2ce599ed9b11cd16415381d6ea1 (patch) | |
| tree | b128129d47cc7a41dd13cfe98ef2a43afc3a5b3e | |
| parent | 0478d96b0dfdf673f15eddcde2d6ef2b8d4c85b4 (diff) | |
| parent | ef81e78d3ed87b36f7c00130874691433f97107e (diff) | |
| download | perlweeklychallenge-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.md | 148 | ||||
| -rw-r--r-- | challenge-258/matthias-muth/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-258/matthias-muth/perl/ch-1.pl | 24 | ||||
| -rwxr-xr-x | challenge-258/matthias-muth/perl/ch-2.pl | 30 | ||||
| -rw-r--r-- | challenge-258/matthias-muth/perl/challenge-258.txt | 58 |
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. |
