aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-127/jbourlakos/perl/ch-2.pl174
1 files changed, 174 insertions, 0 deletions
diff --git a/challenge-127/jbourlakos/perl/ch-2.pl b/challenge-127/jbourlakos/perl/ch-2.pl
new file mode 100644
index 0000000000..aaf17163a8
--- /dev/null
+++ b/challenge-127/jbourlakos/perl/ch-2.pl
@@ -0,0 +1,174 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use Carp qw(croak);
+use Const::Fast;
+use Data::Dumper;
+use List::MoreUtils qw(first_value);
+use Pod::Usage qw(pod2usage);
+use Try::Tiny;
+use JSON::XS qw();
+
+const my %STATUS => (
+ SUCCESS => 0,
+ FAIL => 1,
+ NO_ARGS => -1,
+ INVALID_ARGS => -2,
+ UNKNOWN => -4,
+);
+
+sub validate_intervals {
+ my ($intervals_arrayref) = @_;
+
+ croak('Invalid argument')
+ if ( ( ref($intervals_arrayref) ne 'ARRAY' )
+ || ( first_value { ref($_) ne 'ARRAY' } @$intervals_arrayref )
+ || ( first_value { scalar(@$_) != 2 } @$intervals_arrayref ) );
+
+ return;
+}
+
+sub conflict_intervals {
+ my ($intervals_arrayref) = @_;
+
+ validate_intervals($intervals_arrayref);
+
+ my @result;
+ my $scene = [];
+ for my $index ( 1 .. scalar(@$intervals_arrayref) ) {
+ $index -= 1;
+ my $intv = $intervals_arrayref->[$index];
+ foreach ( $intv->[0] .. $intv->[1] ) {
+ if ( defined( $scene->[$_] ) ) {
+ push @result, $intv;
+ last;
+ }
+ }
+ $scene->[ $intv->[0] ] = $index;
+ $scene->[ $intv->[1] ] = $index;
+ }
+
+ return \@result;
+}
+
+sub main {
+ my ($intervals_json_string) = @_;
+ my $status;
+
+ if ( scalar(@_) < 1 ) {
+ pod2usage(
+ -msg => 'Not enough arguments',
+ -exitval => $STATUS{NO_ARGS},
+ -verbose => 1,
+ );
+ }
+
+ my $json_coder = JSON::XS->new->ascii;
+
+ my $intervals = try {
+ $json_coder->decode($intervals_json_string);
+ }
+ catch {
+ my $cause = $_ =~ /^(.*)\s*at/ && $1;
+ pod2usage(
+ -msg => "Invalid argument: $intervals_json_string.\nCause: $cause",
+ -exitval => $STATUS{INVALID_ARGS},
+ -verbose => 1,
+ );
+ };
+
+ my $conflicted_intervals = try {
+ conflict_intervals($intervals)
+ }
+ catch {
+ if ( $_ =~ /invalid\s*argument/si ) {
+ pod2usage(
+ -msg => "Invalid argument: $intervals_json_string",
+ -exitval => $STATUS{INVALID_ARGS},
+ -verbose => 1,
+ );
+ }
+ else {
+ pod2usage(
+ -msg => 'Unknown error',
+ -exitval => $STATUS{UNKNOWN},
+ -verbose => 1,
+ );
+ }
+ };
+
+ print $json_coder->encode($conflicted_intervals), "\n";
+
+ $status = ( scalar(@$conflicted_intervals) > 0 ) ? $STATUS{SUCCESS} : $STATUS{FAIL};
+
+ return $status;
+}
+
+exit( main(@ARGV) );
+
+__END__
+
+=head1 NAME
+
+ch-2.pl - Finds if any intervals conflict with any of their previous intervals
+
+=head1 SYNOPSIS
+
+=over 3
+
+=item $ ch-2.pl RANGES
+
+=back
+
+=head1 DESCRIPTION
+
+Parses one string argument as a list of numeric ranges and it reports the ranges
+that conflict with at least one of their previous ones.
+The conflict checking is forward only, so the first range will never appear in
+the result.
+
+The list should be written as an array of arrays of numbers in proper JSON
+format. The output is also in valid JSON format.
+
+=head2 Arguments
+
+=over 3
+
+=item RANGES
+
+JSON formatted array of arrays of two numbers.
+
+Example: '[ [1,4], [3,5], [6,8], [12,13], [3,20] ]'
+
+=back
+
+=head2 Output
+
+It prints a JSON array with the conflicted ranges.
+If none, it just prints an empty JSON array.
+
+=head2 Exit status
+
+=over 6
+
+=item '0'
+
+If conflicted ranges are found.
+
+=item '1'
+
+If no conflicted ranges are found.
+
+=item '< 0'
+
+If errors
+
+=back
+
+=head1 AUTHOR
+
+Ioannis Bourlakos <https://github.com/jbourlakos>
+
+=cut