diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2023-04-07 01:30:59 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-04-07 01:30:59 +0100 |
| commit | c76c373fdf70d1b34420d0108f616eac18fc1c8e (patch) | |
| tree | cf7745bed7c7e1a53fc19a0b8633af97e3e75b6f | |
| parent | fd7adafd4b3283d736f61b680480a8ba6bf8c60f (diff) | |
| parent | 9610421ef59f3668b4f10ac4b953ddf7717ee676 (diff) | |
| download | perlweeklychallenge-club-c76c373fdf70d1b34420d0108f616eac18fc1c8e.tar.gz perlweeklychallenge-club-c76c373fdf70d1b34420d0108f616eac18fc1c8e.tar.bz2 perlweeklychallenge-club-c76c373fdf70d1b34420d0108f616eac18fc1c8e.zip | |
Merge pull request #7851 from jo-37/contrib
Solutions to challenge 211
| -rwxr-xr-x | challenge-211/jo-37/perl/ch-1.pl | 85 | ||||
| -rwxr-xr-x | challenge-211/jo-37/perl/ch-2.pl | 73 |
2 files changed, 158 insertions, 0 deletions
diff --git a/challenge-211/jo-37/perl/ch-1.pl b/challenge-211/jo-37/perl/ch-1.pl new file mode 100755 index 0000000000..586b91905e --- /dev/null +++ b/challenge-211/jo-37/perl/ch-1.pl @@ -0,0 +1,85 @@ +#!/usr/bin/perl -s + +use v5.16; +use Test2::V0 '!float'; +use PDL; + +our ($tests, $examples); + +run_tests() if $tests || $examples; # does not return + +die <<EOS unless @ARGV; +usage: $0 [-examples] [-tests] [Matrix] + +-examples + run the examples from the challenge + +-tests + run some tests + +Matrix + a string representation of a matrix as accepted by the PDL constructor, + e.g. "[3 2 1] [4 3 2]" + +EOS + + +### Input and Output + +say is_toeplitz("@ARGV") ? 'true' : 'false'; + + +### Implementation + +# A NxM matrix (N,M > 1) has N + M - 3 diagonals having more than one +# element. Creating a set of NxN matrices where each of them have one +# of the orignal matrix' diagonals as its main diagonal. Then take the +# diagonal of these matrices and re-arrange them into a new matrix +# having the main diagonals of the matrix series as rows. Taking minimum +# and maximum over the rows. If min and max equals for every row, the +# matrix is Toeplitz. +# Note: Utilizing BAD values in incomplete diagonals that do not account +# for minimum or maximum. +sub is_toeplitz { + (my $m = pdl @_)->badflag(1); + my ($min, $max) = ( + cat map $_->diagonal(0, 1), + $m->range($m->dim(0) - 2 - sequence(indx, 1, $m->shape->sum - 3), + $m->dim(1), 't') + ->reorder(1,2,0)->dog + )->minmaximum; + + all $min == $max; +} + + +### Examples and tests + +sub run_tests { + SKIP: { + skip "examples" unless $examples; + + ok is_toeplitz( + [4, 3, 2, 1], + [5, 4, 3, 2], + [6, 5, 4, 3]), 'example 1'; + + ok !is_toeplitz( + [1, 2, 3], + [3, 2, 1]), 'example 2'; + } + + SKIP: { + skip "tests" unless $tests; + + ok is_toeplitz(sequence(4) + 5 - sequence(5)->dummy(0)), '4 x 5'; + ok is_toeplitz(sequence(5) + 4 - sequence(4)->dummy(0)), '5 x 4'; + + my $nt = sequence(4) + 5 - sequence(5)->dummy(0); + $nt->set(1, 4, 0); + ok !is_toeplitz($nt), 'one element failing'; + } + + done_testing; + exit; +} diff --git a/challenge-211/jo-37/perl/ch-2.pl b/challenge-211/jo-37/perl/ch-2.pl new file mode 100755 index 0000000000..dd2c6b03fb --- /dev/null +++ b/challenge-211/jo-37/perl/ch-2.pl @@ -0,0 +1,73 @@ +#!/usr/bin/perl -s + +use v5.16; +use Test2::V0; +use Math::Prime::Util qw(forcomb lastfor); +use List::Util qw(sum); +use experimental qw(signatures); + +our ($tests, $examples); + +run_tests() if $tests || $examples; # does not return + +die <<EOS unless @ARGV; +usage: $0 [-examples] [-tests] [--] [N...] + +-examples + run the examples from the challenge + +-tests + run some tests + +N... + list of numbers + +EOS + + +### Input and Output + +say same_average(@ARGV) ? 'true' : 'false'; + + +### Implementation + +# It can easily be shown that if two partitions of the list have the +# same average, this common average equals the average of the whole +# list. Thus all we need to do is find a nonempty true subset of the +# list having the same average as the list. The complement will have +# the same average. + +sub same_average (@list) { + state $delta = 1e-6; + my $avg = sum(@list) / @list; + my $res; + # Loop over all subsets. + forcomb { + # Skip non true subsets. + return unless @_ && @_ != @list; + $res = 1, lastfor if abs($avg - sum(@list[@_]) / @_) < $delta; + } @list; + + $res; +} + + +### Examples and tests + +sub run_tests { + SKIP: { + skip "examples" unless $examples; + + ok same_average(1, 2, 3, 4, 5, 6, 7, 8), 'example 1'; + ok !same_average(1, 3), 'example 2'; + } + + SKIP: { + skip "tests" unless $tests; + ok same_average(1, 1, 1, 1, 5, 9,), '(1 5), (1 1 1 9)'; + } + + done_testing; + exit; +} |
