aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Sommrey <28217714+jo-37@users.noreply.github.com>2023-05-26 14:47:45 +0200
committerJörg Sommrey <28217714+jo-37@users.noreply.github.com>2023-05-26 14:47:45 +0200
commit554f196beb2a83d90d0111e41058c306bdd2ce8f (patch)
tree64669482f1aef3309925bd3cf28a88e0f8fd7ee8
parent430f300fd7abb93023633e53f7d3d0768d0a8723 (diff)
parent784f3a7dbf8ce42f6f4f147fbcb821365772cd83 (diff)
downloadperlweeklychallenge-club-554f196beb2a83d90d0111e41058c306bdd2ce8f.tar.gz
perlweeklychallenge-club-554f196beb2a83d90d0111e41058c306bdd2ce8f.tar.bz2
perlweeklychallenge-club-554f196beb2a83d90d0111e41058c306bdd2ce8f.zip
Solutions to challenge 218
-rwxr-xr-xchallenge-218/jo-37/perl/ch-1.pl69
-rwxr-xr-xchallenge-218/jo-37/perl/ch-2.pl89
2 files changed, 158 insertions, 0 deletions
diff --git a/challenge-218/jo-37/perl/ch-1.pl b/challenge-218/jo-37/perl/ch-1.pl
new file mode 100755
index 0000000000..acde924b6e
--- /dev/null
+++ b/challenge-218/jo-37/perl/ch-1.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/perl -s
+
+use v5.24;
+use Test2::V0;
+
+our ($tests, $examples);
+
+run_tests() if $tests || $examples; # does not return
+
+die <<EOS unless @ARGV >= 3;
+usage: $0 [-examples] [-tests] [--] [N...]
+
+-examples
+ run the examples from the challenge
+
+-tests
+ run some tests
+
+N...
+ list of at least three numbers
+
+EOS
+
+
+### Input and Output
+
+say max_prod(@ARGV);
+
+
+### Implementation
+
+# There are only two candidates for the maximum product of three
+# elements:
+# - the product of the three largest elements
+# - the product of the two smallest elements with the largest
+sub max_prod {
+ # For the sake of convenience, sort the elements.
+ my @s = sort {$a <=> $b} @_;
+ my $left = $s[0] * $s[1] * $s[-1];
+ my $right = $s[-3] * $s[-2] * $s[-1];
+
+ $left > $right ? $left : $right;
+}
+
+
+### Examples and tests
+
+sub run_tests {
+ SKIP: {
+ skip "examples" unless $examples;
+
+ is max_prod(3, 1, 2), 6, 'example 1';
+ is max_prod(4, 1, 3, 2), 24, 'example 2';
+ is max_prod(-1, 0, 1, 3, 1), 3, 'example 3';
+ is max_prod(-8, 2, -9, 0, -4, 3), 216, 'example 4';
+ }
+
+ SKIP: {
+ skip "tests" unless $tests;
+
+ is max_prod(-1, -2, -3, -4, -5), -6, 'all negative';
+ is max_prod(1, 2, 3, 4, -5), 24, 'one negative';
+ is max_prod(1, 2, -3, -4, 4, 5), 60, 'left wins';
+ is max_prod(1, -2, 3, -4, 4, 5), 60, 'right wins';
+ }
+
+ done_testing;
+ exit;
+}
diff --git a/challenge-218/jo-37/perl/ch-2.pl b/challenge-218/jo-37/perl/ch-2.pl
new file mode 100755
index 0000000000..6c67fa4ac0
--- /dev/null
+++ b/challenge-218/jo-37/perl/ch-2.pl
@@ -0,0 +1,89 @@
+#!/usr/bin/perl -s
+
+use v5.24;
+use Test2::V0 '!float';
+use PDL;
+use PDL::NiceSlice;
+use Math::Prime::Util 'fromdigits';
+use experimental 'signatures';
+
+our ($tests, $examples, $verbose);
+
+run_tests() if $tests || $examples; # does not return
+
+die <<EOS unless @ARGV;
+usage: $0 [-examples] [-tests] [-verbose] [--] [...]
+
+-examples
+ run the examples from the challenge
+
+-tests
+ run some tests
+
+-verbose
+ enable trace output
+
+M
+ matrix from zeroes and ones in any form accepted by the PDL string
+ constructor, e.g.
+ "[ [0,0,1,1], [1,0,1,0], [1,1,0,0], ]"
+
+EOS
+
+
+### Input and Output
+
+say matrix_score(byte "@ARGV");
+
+
+### Implementation
+
+# The matrix is maximal w.r.t. row toggles if the first column is
+# all-ones. Any toggled row would decrease the overall sum.
+# The matrix is maximal w.r.t. column toggles, if all columns have at
+# least as many ones as zeroes. Toggling a column having an equal
+# number of zeroes and ones would not change the overall sum whereas the
+# overall sum would decrease otherwise.
+
+sub matrix_score ($b) {
+ say "inititial:", $b if $verbose;
+
+ # Toggle all rows having a zero in the first column.
+ $b ^= !$b(0);
+ say "intermediate:", $b if $verbose;
+
+ # Toggle all columns having less ones than zeroes.
+ $b ^= $b->xchg(0, 1)->sumover < $b->dim(1) / 2;
+ say "final:", $b if $verbose;
+
+ # Fromdigits accepts digits of any size, thus there is no need to
+ # calculate the individual numbers.
+ fromdigits $b->xchg(0, 1)->sumover->unpdl, 2;
+}
+
+
+### Examples and tests
+
+sub run_tests {
+ local $verbose;
+
+ SKIP: {
+ skip "examples" unless $examples;
+
+ is matrix_score(byte [0,0,1,1], [1,0,1,0], [1,1,0,0]), 39, 'example 1';
+ is matrix_score(byte [[0]]), 1, 'example 2';
+ }
+
+ SKIP: {
+ skip "tests" unless $tests;
+
+ is matrix_score(byte [1, 1, 0, 0, 0, 1], [0, 0, 0, 1, 1, 1],
+ [1, 0, 1, 1, 0, 0], [0, 1, 1, 0, 0, 1], [1, 0, 0, 0, 1, 1]),
+ 253, 'toggle all but first columns';
+ # 32 * 5 + (16 + 8 + 4 + 2 + 1) * 3
+
+ }
+
+ done_testing;
+ exit;
+}