aboutsummaryrefslogtreecommitdiff
path: root/challenge-050/colin-crain/perl/ch-1.pl
blob: df93bc41b3b441a043823e99bd0989fa8a62e8f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#! /opt/local/bin/perl
#
#       ch-1.pl
#
#       PWC 50 - TASK #1
#             Merge Intervals
#             Write a script to merge the given intervals where ever possible.
#
#                 [2,7], [3,9], [10,12], [15,19], [18,22]
#
#             The script should merge [2, 7] and [3, 9] together to return [2, 9].
#
#             Similarly it should also merge [15, 19] and [18, 22] together to return [15, 22].
#
#             The final result should be something like below:
#
#                 [2, 9], [10, 12], [15, 22]
#
#         method: Intervals can be merged if the start or end of one interval is
#             contined within the span of another. If the other boundry of the
#             second interval is outside the range of the first, a new interval
#             is created encompassing the combined span of the two.*
#
#             *If the outer boundry is also contained within the range of the
#             first, the second interval is swallowed whole into the larger and
#             disappears.
#
#             This process of integration can be chained, with the new interval
#             becoming increasingly larger, as long as there are intervals that
#             overlap the aggregate. Amoeba-like, the intervals expand as we
#             consolidate the intersecting areas, resulting in a remaining field
#             of discontinuous elements.
#
#             We will choose to to interpret the intervals expressed as an
#             absolute value, a scalar without a vector. The interval [6,4] will
#             be considered equivalent to the interval [4,6] as they encompass
#             the same span; the quantity of difference is what is being
#             measured, rather than a specific sequential progression. With this
#             stipulation the intervals can be always be coerced into ascending
#             order; without it, it's difficult to understand how the idea of
#             merging the intervals can meaningfully done without damaging the
#             data. That task would be more akin to summing vectors, or perhaps
#             finding the area under a graph. In any case it's outside the
#             purview of this challenge.
#
#             In preparation for merging, the interval pairs are sorted
#             ascending, first internally and then by their lower bound.
#             Stepwise, the lowest-bounded (leftmost) interval is shifted off
#             the list. If the next interval start is contained within the
#             existing, it is shifted off the list and the upper bound of the
#             current interval is increased or retained acordingly. This process
#             is continued until the next interval lower bound is outside the
#             range of the current. The current, expanded interval is then
#             output, and the process is begun again with the next, until we run
#             out of data.
#
#
#       2020 colin crain
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##


use warnings;
use strict;
use feature ":5.26";

## ## ## ## ## MAIN:

## sort and order the data before commencing
my @intervals   = ([2,7], [3,9], [19,15], [18,22], [10,12]);
my @remapped    = map  { $_->[0] <= $_->[1] ? $_ : [reverse $_->@*] } @intervals;
my @sorted      = sort { $a->[0] <=> $b->[0] } @remapped;
my @output;

while ( my $current = shift @sorted ){

    ## iterate through the intervals until a lower is greater than the current upper bound
    while (scalar @sorted && ($sorted[0]->[0] <= $current->[1])) {
        my $next = shift @sorted;
        $current->[1] = $next->[1] if $next->[1] > $current->[1];
    }

    ## once out of there we add to the output list, loop and and start again
    ## with the next discontinuous interval
    push @output, $current;
}

## output
say join ', ', map { "[" . (join ", ", $_->@*) . "]" } @output;