aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Sommrey <28217714+jo-37@users.noreply.github.com>2020-11-16 11:54:44 +0100
committerJörg Sommrey <28217714+jo-37@users.noreply.github.com>2020-11-20 18:11:31 +0100
commitb834dc76110f72a8d5b8908d79e2a64adc52bd1d (patch)
treee84a9ecf6fae277361254584321750a7bc6a69c0
parentda1ffc2a1a2d010be8ac804e34295c70f7dbd69e (diff)
downloadperlweeklychallenge-club-b834dc76110f72a8d5b8908d79e2a64adc52bd1d.tar.gz
perlweeklychallenge-club-b834dc76110f72a8d5b8908d79e2a64adc52bd1d.tar.bz2
perlweeklychallenge-club-b834dc76110f72a8d5b8908d79e2a64adc52bd1d.zip
Solution to task 1
-rwxr-xr-xchallenge-087/jo-37/perl/ch-1.pl48
1 files changed, 48 insertions, 0 deletions
diff --git a/challenge-087/jo-37/perl/ch-1.pl b/challenge-087/jo-37/perl/ch-1.pl
new file mode 100755
index 0000000000..6eaeea9087
--- /dev/null
+++ b/challenge-087/jo-37/perl/ch-1.pl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+
+use 5.012;
+use Test2::V0;
+use List::Util qw(reduce uniqnum);
+use Data::Dump;
+
+# Find longest consecutive sequence in a list of integers. An empty
+# result in boolean context gives zero as requested.
+sub lcs {
+ # Sort unique values.
+ my @sorted = uniqnum sort {$a <=> $b} @_;
+
+ # Abusing "reduce" as a sliding window implementation for two
+ # elements at a time.
+ # Transform the sorted list into sawtooth shape, where every number
+ # is shifted to zero if is not the successor of the previous.
+ my @sawtooth;
+ my $level;
+ reduce {
+ $level = $b if $b != $a + 1;
+ push @sawtooth, $b - $level;
+ $b
+ } '-inf', @sorted;
+
+ # Find the maximum and simultanously its position in the list.
+ my $maxat = reduce {
+ $sawtooth[$b] > $a->[0] ? [$sawtooth[$b], $b] : $a
+ } ['-inf'], 0 .. $#sawtooth;
+
+ # The longest consecutive list ends at the position of the maximum
+ # and has one more element than the maximum in the sawtooth list.
+ # Extract this sublist from the ordered list. Empty the result list
+ # if the maximum is zero, i.e. if the lcs consists of a single
+ # number.
+ (@sorted[$maxat->[1] - $maxat->[0] .. $maxat->[1]]) x !!$maxat->[0];
+}
+
+is [lcs 100, 4, 50, 3, 2], [2, 3, 4], 'Example 1';
+is lcs(20, 30, 10, 40, 50), F(), 'Example 2';
+is [lcs 20, 19, 9, 11, 10], [9, 10, 11], 'Example 3';
+
+is [lcs 1, 2, 3, 11, 12, 13, 14, 21, 22], [11, 12, 13, 14], 'max != index';
+is [lcs 12, 3, 1, 14, 5, 2, 11, 3, 4, 13], [1, 2, 3, 4, 5], 'has duplicate';
+is [lcs 1, 2.1, 3.2, 4.3, 5.3, 6.3, 7.2, 8.1, 9], [4.3, 5.3, 6.3],
+ 'works with broken numbers, too';
+
+done_testing;