diff options
| author | Matthias Muth <matthias.muth@gmx.de> | 2023-02-14 07:05:00 +0100 |
|---|---|---|
| committer | Matthias Muth <matthias.muth@gmx.de> | 2023-02-14 11:53:48 +0100 |
| commit | 9249fa6ab7b80f320cdac6386f92f4709707436e (patch) | |
| tree | b61f629c3797101d16f5fc1916ecc817a384f689 | |
| parent | 6051a217ebf6f4804bf3015fc670971a489aecb0 (diff) | |
| download | perlweeklychallenge-club-9249fa6ab7b80f320cdac6386f92f4709707436e.tar.gz perlweeklychallenge-club-9249fa6ab7b80f320cdac6386f92f4709707436e.tar.bz2 perlweeklychallenge-club-9249fa6ab7b80f320cdac6386f92f4709707436e.zip | |
Challenge 204 solutions by Matthias Muth.
| -rw-r--r-- | challenge-204/matthias-muth/README.md | 79 | ||||
| -rwxr-xr-x | challenge-204/matthias-muth/perl/ch-1-verbose.pl | 29 | ||||
| -rwxr-xr-x | challenge-204/matthias-muth/perl/ch-1.pl | 18 | ||||
| -rwxr-xr-x | challenge-204/matthias-muth/perl/ch-2.pl | 76 |
4 files changed, 202 insertions, 0 deletions
diff --git a/challenge-204/matthias-muth/README.md b/challenge-204/matthias-muth/README.md new file mode 100644 index 0000000000..d88872a1d0 --- /dev/null +++ b/challenge-204/matthias-muth/README.md @@ -0,0 +1,79 @@ +## Task 1: Monotonic Array + +Given an array of integers, the script is supposed to find out if the given +array is Monotonic, and print 1 if it is, and 0 otherwise. + +My solution uses List::Util's `reduce` function, once to check for +monotone increasing and once for monotone decreasing. + +In `reduce`, the code block is executed first for the first two elements of the +parameter list, then for its result and the third element, and so on for all +elements. +The idea is to pass on a kind of _status_ to the next code block execution +to indicate whether so far, all numbers have been monotone increasing +(or decreasing in the other call) or whether there was a mismatch. +That's easy -- we pass `undef` as a result once the chain is broken, +and once we have an `undef` we keep it until the end. +If all is still good, we pass the current value for comparison +with the next element in the next round. + +This looks like this: + +```perl +sub monotonic { + return 1 + if reduce { ( defined $a && $a <= $b ) ? $b : undef } @_ + or reduce { ( defined $a && $a >= $b ) ? $b : undef } @_; + return 0; +} +``` + +I know that we waste some runtime by walking through all elements even once +we have found a mismatch, but I really like the conciseness of this solution +(it might be just for me personally, but I find it 'elegant'). + +## Task 2: Reshape matrix + +Given a matrix ( _m_ x _n_ ) and two integers (_r_ and _c_), the script shall +reshape the given matrix in form ( _r_ x _c_ ) with the original values of the +given matrix. If it can’t reshape it shall print 0. + +My approach is to create one linear array that contains all the elements of the +original matrix. Then assign the first _c_ elements to a new row of the +resulting matrix, while deleting them from the linear array. +The `slice`function offers itself +perfectly for doing ths in one step. +Repeat until the linear array is used up. + +This will result in a nice matrix only when we have exactly _r_ x _c_ elements, +so we check this condition first. + +Using _signatures_, this function does the job: + +```perl +sub reshape( $matrix, $r, $c ) { + my @all_elements = map @$_, @$matrix; + return undef + unless @all_elements == $r * $c; + my $reshaped = []; + push @$reshaped, [ splice @all_elements, 0, $c, () ] + while @all_elements; + return $reshaped; +} +``` + +Note that the function returns `undef` on failure. It is left up to the +caller to transform this into `0` for output. +I found this a better style, keeping the implementation part more +'Perl'ish and also making it easier to interpret the result for the caller. +Good to have everything output-related in just one place then. + +I have put a description of the examples into the script's _\_\_DATA\_\__ +section in a nice, readable form, together with their expected output. +The rest of the script reads the examples, runs one loop for +the example output and then another for running the test cases using +_Test::More_. +Perl has been my favorite language for doing this type of +'free-text-to-data-structures' transformation for a long time. + +It was fun to take part in the challenge! diff --git a/challenge-204/matthias-muth/perl/ch-1-verbose.pl b/challenge-204/matthias-muth/perl/ch-1-verbose.pl new file mode 100755 index 0000000000..56fc669a70 --- /dev/null +++ b/challenge-204/matthias-muth/perl/ch-1-verbose.pl @@ -0,0 +1,29 @@ +#!/usr/bin/env perl + +use feature qw( say ); + +use Data::Dump qw( pp ); +use List::Util qw( reduce ); + +sub monotonic { + say "monotonic( @_ )"; + return 1 + if reduce { + my $result = ( defined $a && $a <= $b ) ? $b : undef; + say "comparing ", pp( $a ), " <= ", pp( $b ), ": ", pp( $result ); + $result; + } @_ + or reduce { + my $result = ( defined $a && $a >= $b ) ? $b : undef; + say "comparing ", pp( $a ), " >= ", pp( $b ), ": ", pp( $result ); + $result; + } @_; + return 0; +} + +use Test::More; + +is monotonic( 1, 2, 2, 3 ), 1, "monotonic( 1, 2, 2, 3 ) == 1"; +is monotonic( 1, 3, 2 ), 0, "monotonic( 1, 3, 2 ) == 0"; +is monotonic( 6, 5, 5, 4 ), 1, "monotonic( 6, 5, 5, 4 ) == 1"; +done_testing; diff --git a/challenge-204/matthias-muth/perl/ch-1.pl b/challenge-204/matthias-muth/perl/ch-1.pl new file mode 100755 index 0000000000..e8053e4578 --- /dev/null +++ b/challenge-204/matthias-muth/perl/ch-1.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl + +use List::Util qw( reduce ); + +sub monotonic { + return 1 + if reduce { ( defined $a && $a <= $b ) ? $b : undef } @_ + or reduce { ( defined $a && $a >= $b ) ? $b : undef } @_; + return 0; +} + +use Test::More; + +is monotonic( 1, 2, 2, 3 ), 1, "monotonic( 1, 2, 2, 3 ) == 1"; +is monotonic( 1, 3, 2 ), 0, "monotonic( 1, 3, 2 ) == 0"; +is monotonic( 6, 5, 5, 4 ), 1, "monotonic( 6, 5, 5, 4 ) == 1"; + +done_testing; diff --git a/challenge-204/matthias-muth/perl/ch-2.pl b/challenge-204/matthias-muth/perl/ch-2.pl new file mode 100755 index 0000000000..286e3b7759 --- /dev/null +++ b/challenge-204/matthias-muth/perl/ch-2.pl @@ -0,0 +1,76 @@ +#!/usr/bin/env perl + +use v5.26; +use warnings; +use feature qw( signatures ); +no warnings qw( experimental::signatures ); + +sub reshape( $matrix, $r, $c ) { + my @all_elements = map @$_, @$matrix; + return undef + unless @all_elements == $r * $c; + my $reshaped = []; + push @$reshaped, [ splice @all_elements, 0, $c, () ] + while @all_elements; + return $reshaped; +} + +my @tests; +my ( $test, $matrix, $r, $c, $expected ) = ( "", [], 0, 0, undef ); +while ( <DATA> ) { + /^(?!expect)\S{2,}.*/ and do { $test = $&; next }; + /^\[.*/ and do { push @$matrix, [ /\d+/g ]; next }; + /^r (\d+)/ and do { $r = $1; next }; + /^c (\d+)/ and do { $c = $1; next }; + /^expect (.*)/ and do { + $expected = $1; + push @tests, [ $test, $matrix, $r, $c, $expected ]; + ( $test, $matrix, $r, $c, $expected ) = ( "", [], 0, 0, undef ); + next; + }; +} + +for ( @tests ) { + my ( $test, $matrix, $r, $c, $expected ) = @$_; + my $reshaped = reshape( $matrix, $r, $c ); + say $test; + say "[ @$_ ]" + for @$matrix; + say "r $r"; + say "c $c"; + say $_ ? "[ @$_ ]" : 0 + for $reshaped && @$reshaped; + say ""; +} + +use Test::More; +for ( @tests ) { + my ( $test, $matrix, $r, $c, $expected ) = @$_; + my $reshaped = reshape( $matrix, $r, $c ); + my $answer = $reshaped ? join( " ", map "[ @$_ ]", @$reshaped ) : 0; + is $answer, $expected, $test; +} + +done_testing; + +__DATA__ + +Example 1 +[ 1 2 ] +[ 3 4 ] +r 1 +c 4 +expect [ 1 2 3 4 ] + +Example 2 +[ 1 2 3 ] +[ 4 5 6 ] +r 3 +c 2 +expect [ 1 2 ] [ 3 4 ] [ 5 6 ] + +Example 3 +[ 1 2 ] +r 3 +c 2 +expect 0 |
