I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

Range consolidation

Range consolidation
You are encouraged to solve this task according to the task description, using any language you may know.

Define a range of numbers `R`, with bounds `b0` and `b1` covering all numbers between and including both bounds. That range can be shown as:

`[b0, b1]`

or equally as:

`[b1, b0]`.

Given two ranges, the act of consolidation between them compares the two ranges:

• If one range covers all of the other then the result is that encompassing range.
• If the ranges touch or intersect then the result is one new single range covering the overlapping ranges.
• Otherwise the act of consolidation is to return the two non-touching ranges.

Given N ranges where N>2 then the result is the same as repeatedly replacing all combinations of two ranges by their consolidation until no further consolidation between range pairs is possible. If N<2 then range consolidation has no strict meaning and the input can be returned.

Example 1:
Given the two ranges [1, 2.5] and [3, 4.2] then there is no
common region between the ranges and the result is the same as the input.
Example 2:
Given the two ranges [1, 2.5] and [1.8, 4.7] then there is
an overlap [2.5, 1.8] between the ranges and the result is the single
range [1, 4.7]. Note that order of bounds in a range is not, (yet), stated.
Example 3:
Given the two ranges [6.1, 7.2] and [7.2, 8.3] then they
touch at 7.2 and the result is the single range [6.1, 8.3].
Example 4:
Given the three ranges [1, 2] and [4, 8] and [2, 5]
then there is no intersection of the ranges [1, 2] and [4, 8]
but the ranges [1, 2] and [2, 5] overlap and consolidate to
produce the range [1, 5]. This range, in turn, overlaps the other range
[4, 8], and so consolidates to the final output of the single range
[1, 8]
Task:

Let a normalized range display show the smaller bound to the left; and show the range with the smaller lower bound to the left of other ranges when showing multiple ranges.

Output the normalised result of applying consolidation to these five sets of ranges:

```        [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3]
[4, 3], [2, 1]
[4, 3], [2, 1], [-1, -2], [3.9, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]
```

Show output here.

See also

Ada

`with Ada.Text_IO;with Ada.Containers.Vectors; procedure Range_Consolidation is    type Set_Type is record      Left, Right : Float;   end record;    package Set_Vectors is      new Ada.Containers.Vectors (Positive, Set_Type);    procedure Normalize (Set : in out Set_Vectors.Vector) is       function Less_Than (Left, Right : Set_Type) return Boolean is         begin Return Left.Left < Right.Left; end;       package Set_Sorting is         new Set_Vectors.Generic_Sorting (Less_Than);   begin      for Elem of Set loop         Elem := (Left  => Float'Min (Elem.Left,  Elem.Right),                  Right => Float'Max (Elem.Left,  Elem.Right));      end loop;      Set_Sorting.Sort (Set);   end Normalize;    procedure Consolidate (Set : in out Set_Vectors.Vector) is      use Set_Vectors;      First : Cursor := Set.First;      Last  : Cursor := Next (First);   begin      while Last /= No_Element loop         if Element (First).Right < Element (Last).Left then      -- non-overlap            First := Last;            Last  := Next (Last);         elsif Element (First).Right >= Element (Last).Left then  -- overlap            Replace_Element (Set, First, (Left  => Element (First).Left,                                          Right => Float'Max (Element (First).Right,                                                              Element (Last) .Right)));            Delete (Set, Last);            Last := Next (First);         end if;      end loop;   end Consolidate;    procedure Put (Set : in Set_Vectors.Vector) is      package Float_IO is         new Ada.Text_IO.Float_IO (Float);   begin      Float_IO.Default_Exp  := 0;      Float_IO.Default_Aft  := 1;      Float_IO.Default_Fore := 3;      for Elem of Set loop         Ada.Text_IO.Put ("(");         Float_IO.Put (Elem.Left);         Float_IO.Put (Elem.Right);         Ada.Text_IO.Put (") ");      end loop;   end Put;    procedure Show (Set : in out Set_Vectors.Vector) is      use Ada.Text_IO;   begin      Put (Set);      Normalize (Set);      Consolidate (Set);      Set_Col (70);      Put (Set);      New_Line;   end Show;    use Set_Vectors;   Set_0 : Set_Vectors.Vector := Empty_Vector;   Set_1 : Set_Vectors.Vector := Empty_Vector & (1.1, 2.2);   Set_2 : Set_Vectors.Vector := (6.1, 7.2) & (7.2, 8.3);   Set_3 : Set_Vectors.Vector := (4.0, 3.0) & (2.0, 1.0);   Set_4 : Set_Vectors.Vector := (4.0, 3.0) & (2.0, 1.0) & (-1.0, -2.0) & (3.9, 10.0);   Set_5 : Set_Vectors.Vector := (1.0, 3.0) & (-6.0, -1.0) & (-4.0, -5.0) & (8.0, 2.0) & (-6.0, -6.0);begin   Show (Set_0);   Show (Set_1);   Show (Set_2);   Show (Set_3);   Show (Set_4);   Show (Set_5);end Range_Consolidation;`
Output:
```(  1.1  2.2)                                                         (  1.1  2.2)
(  6.1  7.2) (  7.2  8.3)                                            (  6.1  8.3)
(  4.0  3.0) (  2.0  1.0)                                            (  1.0  2.0) (  3.0  4.0)
(  4.0  3.0) (  2.0  1.0) ( -1.0 -2.0) (  3.9 10.0)                  ( -2.0 -1.0) (  1.0  2.0) (  3.0 10.0)
(  1.0  3.0) ( -6.0 -1.0) ( -4.0 -5.0) (  8.0  2.0) ( -6.0 -6.0)     ( -6.0 -1.0) (  1.0  8.0)
```

C

`#include <stdio.h>#include <stdlib.h> typedef struct range_tag {    double low;    double high;} range_t; void normalize_range(range_t* range) {    if (range->high < range->low) {        double tmp = range->low;        range->low = range->high;        range->high = tmp;    }} int range_compare(const void* p1, const void* p2) {    const range_t* r1 = p1;    const range_t* r2 = p2;    if (r1->low < r2->low)        return -1;    if (r1->low > r2->low)        return 1;    if (r1->high < r2->high)        return -1;    if (r1->high > r2->high)        return 1;    return 0;} void normalize_ranges(range_t* ranges, size_t count) {    for (size_t i = 0; i < count; ++i)        normalize_range(&ranges[i]);    qsort(ranges, count, sizeof(range_t), range_compare);} // Consolidates an array of ranges in-place. Returns the// number of ranges after consolidation.size_t consolidate_ranges(range_t* ranges, size_t count) {    normalize_ranges(ranges, count);    size_t out_index = 0;    for (size_t i = 0; i < count; ) {        size_t j = i;        while (++j < count && ranges[j].low <= ranges[i].high) {            if (ranges[i].high < ranges[j].high)                ranges[i].high = ranges[j].high;        }        ranges[out_index++] = ranges[i];        i = j;    }    return out_index;} void print_range(const range_t* range) {    printf("[%g, %g]", range->low, range->high);} void print_ranges(const range_t* ranges, size_t count) {    if (count == 0)        return;    print_range(&ranges[0]);    for (size_t i = 1; i < count; ++i) {        printf(", ");        print_range(&ranges[i]);    }} void test_consolidate_ranges(range_t* ranges, size_t count) {    print_ranges(ranges, count);    printf(" -> ");    count = consolidate_ranges(ranges, count);    print_ranges(ranges, count);    printf("\n");} #define LENGTHOF(a) sizeof(a)/sizeof(a[0]) int main() {    range_t test1[] = { {1.1, 2.2} };    range_t test2[] = { {6.1, 7.2}, {7.2, 8.3} };    range_t test3[] = { {4, 3}, {2, 1} };    range_t test4[] = { {4, 3}, {2, 1}, {-1, -2}, {3.9, 10} };    range_t test5[] = { {1, 3}, {-6, -1}, {-4, -5}, {8, 2}, {-6, -6} };    test_consolidate_ranges(test1, LENGTHOF(test1));    test_consolidate_ranges(test2, LENGTHOF(test2));    test_consolidate_ranges(test3, LENGTHOF(test3));    test_consolidate_ranges(test4, LENGTHOF(test4));    test_consolidate_ranges(test5, LENGTHOF(test5));    return 0;}`
Output:
```[1.1, 2.2] -> [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3] -> [6.1, 8.3]
[4, 3], [2, 1] -> [1, 2], [3, 4]
[4, 3], [2, 1], [-1, -2], [3.9, 10] -> [-2, -1], [1, 2], [3, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] -> [-6, -1], [1, 8]
```

C#

Works with: C sharp version 7
`using static System.Math;using System.Linq;using System; public static class RangeConsolidation{    public static void Main() {        foreach (var list in new [] {            new[] { (1.1, 2.2) }.ToList(),            new[] { (6.1, 7.2), (7.2, 8.3) }.ToList(),            new[] { (4d, 3d), (2, 1) }.ToList(),            new[] { (4d, 3d), (2, 1), (-1, 2), (3.9, 10) }.ToList(),            new[] { (1d, 3d), (-6, -1), (-4, -5), (8, 2), (-6, -6) }.ToList()        })        {            for (int z = list.Count-1; z >= 1; z--) {                for (int y = z - 1; y >= 0; y--) {                    if (Overlap(list[z], list[y])) {                        list[y] = Consolidate(list[z], list[y]);                        list.RemoveAt(z);                        break;                    }                }            }            Console.WriteLine(string.Join(", ", list.Select(Normalize).OrderBy(range => range.s)));        }    }     private static bool Overlap((double s, double e) left, (double s, double e) right) =>        Max(left.s, left.e) > Max(right.s, right.e)        ? Max(right.s, right.e) >= Min(left.s, left.e)        : Max(left.s, left.e) >= Min(right.s, right.e);     private static (double s, double e) Consolidate((double s, double e) left, (double s, double e) right) =>        (Min(Min(left.s, left.e), Min(right.s, right.e)), Max(Max(left.s, left.e), Max(right.s, right.e)));     private static (double s, double e) Normalize((double s, double e) range) =>        (Min(range.s, range.e), Max(range.s, range.e));}`
Output:
```(1.1, 2.2)
(6.1, 8.3)
(1, 2), (3, 4)
(-1, 2), (3, 10)
(-6, -1), (1, 8)```

C++

`#include <algorithm>#include <iostream>#include <utility>#include <vector> // A range is represented as std::pair<from, to> template <typename iterator>void normalize_ranges(iterator begin, iterator end) {    for (iterator i = begin; i != end; ++i) {        if (i->second < i->first)            std::swap(i->first, i->second);    }    std::sort(begin, end);} // Merges a range of ranges in-place. Returns an iterator to the// end of the resulting range, similarly to std::remove.template <typename iterator>iterator merge_ranges(iterator begin, iterator end) {    iterator out = begin;    for (iterator i = begin; i != end; ) {        iterator j = i;        while (++j != end && j->first <= i->second)            i->second = std::max(i->second, j->second);        *out++ = *i;        i = j;    }    return out;} template <typename iterator>iterator consolidate_ranges(iterator begin, iterator end) {    normalize_ranges(begin, end);    return merge_ranges(begin, end);} template <typename pair>void print_range(std::ostream& out, const pair& range) {    out << '[' << range.first << ", " << range.second << ']';} template <typename iterator>void print_ranges(std::ostream& out, iterator begin, iterator end) {    if (begin != end) {        print_range(out, *begin++);        for (; begin != end; ++begin) {            out << ", ";            print_range(out, *begin);        }    }} int main() {    std::vector<std::pair<double, double>> test_cases[] = {        { {1.1, 2.2} },        { {6.1, 7.2}, {7.2, 8.3} },        { {4, 3}, {2, 1} },        { {4, 3}, {2, 1}, {-1, -2}, {3.9, 10} },        { {1, 3}, {-6, -1}, {-4, -5}, {8, 2}, {-6, -6} }    };    for (auto&& ranges : test_cases) {        print_ranges(std::cout, std::begin(ranges), std::end(ranges));        std::cout << " -> ";        auto i = consolidate_ranges(std::begin(ranges), std::end(ranges));        print_ranges(std::cout, std::begin(ranges), i);        std::cout << '\n';    }    return 0;}`
Output:
```[1.1, 2.2] -> [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3] -> [6.1, 8.3]
[4, 3], [2, 1] -> [1, 2], [3, 4]
[4, 3], [2, 1], [-1, -2], [3.9, 10] -> [-2, -1], [1, 2], [3, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] -> [-6, -1], [1, 8]
```

Clojure

`(defn normalize [r]  (let [[n1 n2] r]    [(min n1 n2) (max n1 n2)])) (defn touch? [r1 r2]  (let [[lo1 hi1] (normalize r1)        [lo2 hi2] (normalize r2)]    (or (<= lo2 lo1 hi2)        (<= lo2 hi1 hi2)))) (defn consolidate-touching-ranges [rs]  (let [lows  (map #(apply min %) rs)        highs (map #(apply max %) rs)]    [ (apply min lows) (apply max highs) ])) (defn consolidate-ranges [rs]  (loop [res []         rs  rs]    (if (empty? rs)      res      (let [r0 (first rs)            touching (filter #(touch? r0 %) rs)            remove-used (fn [rs used]                          (remove #(contains? (set used) %) rs))]        (recur (conj res (consolidate-touching-ranges touching))               (remove-used (rest rs) touching))))))`
Output:
```  (def test-data [ [[1.1 2.2]]
[[6.1 7.2] [7.2 8.3]]
[[4 3] [2 1]]
[[4 3] [2 1] [-1 -2] [3.9 10]]
[[1 3] [-6 -1] [-4 -5] [8 2] [-6 -6]] ])

(map consolidate-ranges test-data)
;; ==>   ([[1.1 2.2]]
[[6.1 8.3]]
[[3 4] [1 2]]
[[3 10] [1 2] [-2 -1]]
[[1 8] [-6 -1] [-5 -4]]))
```

Dyalect

Translation of: C#
`func max(x, y) {    if x > y {        x    } else {        y    }} func min(x, y) {    if x < y {        x    } else {        y    }} func overlap(left, right) {    if max(left:s, left:e) > max(right:s, right:e) {        max(right:s, right:e) >= min(left:s, left:e)     } else {        max(left:s, left:e) >= min(right:s, right:e)    }} func consolidate(left, right) {    (s = min(min(left:s, left:e), min(right:s, right:e)), e = max(max(left:s, left:e), max(right:s, right:e)))} func normalize(range) {    (s = min(range:s, range:e), e = max(range:s, range:e))} for list in [    [ (s = 1.1, e = 2.2) ],    [ (s = 6.1, e = 7.2), (s = 7.2, e = 8.3) ],    [ (s = 4.0, e = 3.0), (s = 2, e = 1) ],    [ (s = 4.0, e = 3.0), (s = 2, e = 1), (s = -1, e = 2), (s = 3.9, e = 10) ],    [ (s = 1.0, e = 3.0), (s = -6, e = -1), (s = -4, e = -5), (s = 8, e = 2), (s = -6, e = -6) ]] {    var z = list.len()-1    while z >= 1 {        for y in (z - 1)..0 {            if overlap(list[z], list[y]) {                list[y] = consolidate(list[z], list[y])                list.removeAt(z)                break            }        }        z -= 1    }    for i in list.indices() {        list[i] = normalize(list[i])    }    list.sort((x,y) => x:s - y:s)    print(list)}`
Output:
```[(s: 1.1, e: 2.2)]
[(s: 6.1, e: 8.3)]
[(s: 1, e: 2), (s: 3, e: 4)]
[(s: -1, e: 2), (s: 3, e: 10)]
[(s: -6, e: -1), (s: 1, e: 8)]```

Go

`package main import (    "fmt"    "math"    "sort") type Range struct{ Lower, Upper float64 } func (r Range) Norm() Range {    if r.Lower > r.Upper {        return Range{r.Upper, r.Lower}    }    return r} func (r Range) String() string {    return fmt.Sprintf("[%g, %g]", r.Lower, r.Upper)} func (r1 Range) Union(r2 Range) []Range {    if r1.Upper < r2.Lower {        return []Range{r1, r2}    }    r := Range{r1.Lower, math.Max(r1.Upper, r2.Upper)}    return []Range{r}} func consolidate(rs []Range) []Range {    for i := range rs {        rs[i] = rs[i].Norm()    }    le := len(rs)    if le < 2 {        return rs    }    sort.Slice(rs, func(i, j int) bool {        return rs[i].Lower < rs[j].Lower    })    if le == 2 {        return rs[0].Union(rs[1])    }    for i := 0; i < le-1; i++ {        for j := i + 1; j < le; j++ {            ru := rs[i].Union(rs[j])            if len(ru) == 1 {                rs[i] = ru[0]                copy(rs[j:], rs[j+1:])                rs = rs[:le-1]                le--                i--                break            }        }    }    return rs} func main() {    rss := [][]Range{        {{1.1, 2.2}},        {{6.1, 7.2}, {7.2, 8.3}},        {{4, 3}, {2, 1}},        {{4, 3}, {2, 1}, {-1, -2}, {3.9, 10}},        {{1, 3}, {-6, -1}, {-4, -5}, {8, 2}, {-6, -6}},    }    for _, rs := range rss {        s := fmt.Sprintf("%v", rs)        fmt.Printf("%40s => ", s[1:len(s)-1])        rs2 := consolidate(rs)        s = fmt.Sprintf("%v", rs2)        fmt.Println(s[1 : len(s)-1])    }}`
Output:
```                              [1.1, 2.2] => [1.1, 2.2]
[6.1, 7.2] [7.2, 8.3] => [6.1, 8.3]
[4, 3] [2, 1] => [1, 2] [3, 4]
[4, 3] [2, 1] [-1, -2] [3.9, 10] => [-2, -1] [1, 2] [3, 10]
[1, 3] [-6, -1] [-4, -5] [8, 2] [-6, -6] => [-6, -1] [1, 8]
```

Haskell

`import Data.List (intercalate, maximumBy, sort)import Data.Ord (comparing) consolidated :: [(Float, Float)] -> [(Float, Float)]consolidated xs =  let go xy [] = [xy]      go xy@(x, y) abetc@((a, b):etc)        | y >= b = xy : etc        | y >= a = (x, b) : etc        | otherwise = xy : abetc      ab (a, b)        | a <= b = (a, b)        | otherwise = (b, a)  in foldr go [] (sort . fmap ab \$ xs)  -- TEST ---------------------------------------------------tests :: [[(Float, Float)]]tests =  [ []  , [(1.1, 2.2)]  , [(6.1, 7.2), (7.2, 8.3)]  , [(4, 3), (2, 1)]  , [(4, 3), (2, 1), (-1, -2), (3.9, 10)]  , [(1, 3), (-6, -1), (-4, -5), (8, 2), (-6, -6)]  ] main :: IO ()main =  putStrLn \$  tabulated "Range consolidations:" showPairs showPairs consolidated tests  -- DISPLAY FORMATTING ------------------------------------- tabulated :: String -> (a -> String) -> (b -> String) -> (a -> b) -> [a] -> Stringtabulated s xShow fxShow f xs =  let w = length \$ maximumBy (comparing length) (xShow <\$> xs)      rjust n c s = drop (length s) (replicate n c ++ s)  in unlines \$     s : fmap (((++) . rjust w ' ' . xShow) <*> ((" -> " ++) . fxShow . f)) xs showPairs :: [(Float, Float)] -> StringshowPairs xs  | null xs = "[]"  | otherwise = '[' : intercalate ", " (showPair <\$> xs) ++ "]" showPair :: (Float, Float) -> StringshowPair (a, b) = '(' : showNum a ++ ", " ++ showNum b ++ ")" showNum :: Float -> StringshowNum n  | 0 == (n - fromIntegral (round n)) = show (round n)  | otherwise = show n`
Output:
```Range consolidations:
[] -> []
[(1.1, 2.2)] -> [(1.1, 2.2)]
[(6.1, 7.2), (7.2, 8.3)] -> [(6.1, 8.3)]
[(4, 3), (2, 1)] -> [(1, 2), (3, 4)]
[(4, 3), (2, 1), (-1, -2), (3.9, 10)] -> [(-2, -1), (1, 2), (3, 10)]
[(1, 3), (-6, -1), (-4, -5), (8, 2), (-6, -6)] -> [(-6, -1), (1, 8)]```

J

Solution:

`ensure2D=: ,:^:(1 = #@\$)                 NB. if list make 1 row tablenormalise=: ([: /:~ /:~"1)@ensure2D      NB. normalises list of rangesmerge=: ,:`(<.&{. , >.&{:)@.(>:/&{: |.)  NB. merge ranges x and yconsolidate=: (}[email protected]] ,~ (merge {.)) ensure2D`

Required Examples:

`   tests=:  <@".;._2 noun define1.1 2.26.1 7.2 ,: 7.2 8.34 3 ,: 2 14 3 , 2 1 , _1 _2 ,: 3.9 101 3 , _6 _1 , _4 _5 , 8 2 ,: _6 _6)    consolidate/@normalise&.> tests+-------+-------+---+-----+-----+|1.1 2.2|6.1 8.3|1 2|_2 _1|_6 _1||       |       |3 4| 1  2| 1  8||       |       |   | 3 10|     |+-------+-------+---+-----+-----+`

Java

` import java.util.ArrayList;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.List; public class RangeConsolidation {     public static void main(String[] args) {        displayRanges( Arrays.asList(new Range(1.1, 2.2)));        displayRanges( Arrays.asList(new Range(6.1, 7.2), new Range(7.2, 8.3)));        displayRanges( Arrays.asList(new Range(4, 3), new Range(2, 1)));        displayRanges( Arrays.asList(new Range(4, 3), new Range(2, 1), new Range(-1, -2), new Range(3.9, 10)));        displayRanges( Arrays.asList(new Range(1, 3), new Range(-6, -1), new Range(-4, -5), new Range(8, 2), new Range(-6, -6)));        displayRanges( Arrays.asList(new Range(1, 1), new Range(1, 1)));        displayRanges( Arrays.asList(new Range(1, 1), new Range(1, 2)));        displayRanges( Arrays.asList(new Range(1, 2), new Range(3, 4), new Range(1.5, 3.5), new Range(1.2, 2.5)));    }     private static final void displayRanges(List<Range> ranges) {        System.out.printf("ranges = %-70s, colsolidated = %s%n", ranges, Range.consolidate(ranges));    }     private static final class RangeSorter implements Comparator<Range> {        @Override        public int compare(Range o1, Range o2) {            return (int) (o1.left - o2.left);        }            }     private static class Range {        double left;        double right;         public Range(double left, double right) {            if ( left <= right ) {                this.left = left;                this.right = right;            }            else {                this.left = right;                this.right = left;            }        }         public Range consolidate(Range range) {            //  no overlap            if ( this.right < range.left ) {                return null;            }            //  no overlap            if ( range.right < this.left ) {                return null;            }            //  contained            if ( this.left <= range.left && this.right >= range.right ) {                return this;            }            //  contained            if ( range.left <= this.left && range.right >= this.right ) {                return range;            }            //  overlap            if ( this.left <= range.left && this.right <= range.right ) {                return new Range(this.left, range.right);            }            //  overlap            if ( this.left >= range.left && this.right >= range.right ) {                return new Range(range.left, this.right);            }            throw new RuntimeException("ERROR:  Logic invalid.");        }         @Override        public String toString() {            return "[" + left + ", " + right + "]";        }         private static List<Range> consolidate(List<Range> ranges) {            List<Range> consolidated = new ArrayList<>();             Collections.sort(ranges, new RangeSorter());             for ( Range inRange : ranges ) {                Range r = null;                Range conRange = null;                for ( Range conRangeLoop : consolidated ) {                    r = inRange.consolidate(conRangeLoop);                    if (r != null ) {                        conRange = conRangeLoop;                        break;                    }                }                if ( r == null ) {                    consolidated.add(inRange);                }                else {                    consolidated.remove(conRange);                    consolidated.add(r);                                    }            }             Collections.sort(consolidated, new RangeSorter());             return consolidated;        }    } } `
Output:

Required and other examples.

```ranges = [[1.1, 2.2]]                                                          , consolidated = [[1.1, 2.2]]
ranges = [[6.1, 7.2], [7.2, 8.3]]                                              , consolidated = [[6.1, 8.3]]
ranges = [[1.0, 2.0], [3.0, 4.0]]                                              , consolidated = [[1.0, 2.0], [3.0, 4.0]]
ranges = [[-2.0, -1.0], [1.0, 2.0], [3.0, 4.0], [3.9, 10.0]]                   , consolidated = [[-2.0, -1.0], [1.0, 2.0], [3.0, 10.0]]
ranges = [[-6.0, -1.0], [-6.0, -6.0], [-5.0, -4.0], [1.0, 3.0], [2.0, 8.0]]    , consolidated = [[-6.0, -1.0], [1.0, 8.0]]
ranges = [[1.0, 1.0], [1.0, 1.0]]                                              , consolidated = [[1.0, 1.0]]
ranges = [[1.0, 1.0], [1.0, 2.0]]                                              , consolidated = [[1.0, 2.0]]
ranges = [[1.0, 2.0], [1.5, 3.5], [1.2, 2.5], [3.0, 4.0]]                      , consolidated = [[1.0, 4.0]]
```

JavaScript

Translation of: Haskell
Translation of: Python
`(() => {    'use strict';     const main = () => {         // consolidated :: [(Float, Float)] -> [(Float, Float)]        const consolidated = xs =>            foldl((abetc, xy) =>                0 < abetc.length ? (() => {                    const                        etc = abetc.slice(1),                        [a, b] = abetc[0],                        [x, y] = xy;                     return y >= b ? (                        cons(xy, etc)                    ) : y >= a ? (                        cons([x, b], etc)                    ) : cons(xy, abetc);                })() : [xy],                [],                sortBy(flip(comparing(fst)),                    map(([a, b]) => a < b ? (                            [a, b]                        ) : [b, a],                        xs                    )                )            );         // TEST -------------------------------------------        console.log(            tabulated(                'Range consolidations:',                JSON.stringify,                JSON.stringify,                consolidated,                [                    [                        [1.1, 2.2]                    ],                    [                        [6.1, 7.2],                        [7.2, 8.3]                    ],                    [                        [4, 3],                        [2, 1]                    ],                    [                        [4, 3],                        [2, 1],                        [-1, -2],                        [3.9, 10]                    ],                    [                        [1, 3],                        [-6, -1],                        [-4, -5],                        [8, 2],                        [-6, -6]                    ]                ]            )        );    };     // GENERIC FUNCTIONS ----------------------------     // comparing :: (a -> b) -> (a -> a -> Ordering)    const comparing = f =>        (x, y) => {            const                a = f(x),                b = f(y);            return a < b ? -1 : (a > b ? 1 : 0);        };     // compose (<<<) :: (b -> c) -> (a -> b) -> a -> c    const compose = (f, g) => x => f(g(x));     // cons :: a -> [a] -> [a]    const cons = (x, xs) => [x].concat(xs);     // flip :: (a -> b -> c) -> b -> a -> c    const flip = f =>        1 < f.length ? (            (a, b) => f(b, a)        ) : (x => y => f(y)(x));     // foldl :: (a -> b -> a) -> a -> [b] -> a    const foldl = (f, a, xs) => xs.reduce(f, a);     // fst :: (a, b) -> a    const fst = tpl => tpl[0];     // justifyRight :: Int -> Char -> String -> String    const justifyRight = (n, cFiller, s) =>        n > s.length ? (            s.padStart(n, cFiller)        ) : s;     // Returns Infinity over objects without finite length.    // This enables zip and zipWith to choose the shorter    // argument when one is non-finite, like cycle, repeat etc     // length :: [a] -> Int    const length = xs =>        (Array.isArray(xs) || 'string' === typeof xs) ? (            xs.length        ) : Infinity;     // map :: (a -> b) -> [a] -> [b]    const map = (f, xs) =>        (Array.isArray(xs) ? (            xs        ) : xs.split('')).map(f);     // maximumBy :: (a -> a -> Ordering) -> [a] -> a    const maximumBy = (f, xs) =>        0 < xs.length ? (            xs.slice(1)            .reduce((a, x) => 0 < f(x, a) ? x : a, xs[0])        ) : undefined;     // sortBy :: (a -> a -> Ordering) -> [a] -> [a]    const sortBy = (f, xs) =>        xs.slice()        .sort(f);     // tabulated :: String -> (a -> String) ->    //                        (b -> String) ->    //           (a -> b) -> [a] -> String    const tabulated = (s, xShow, fxShow, f, xs) => {        // Heading -> x display function ->        //           fx display function ->        //    f -> values -> tabular string        const            ys = map(xShow, xs),            w = maximumBy(comparing(x => x.length), ys).length,            rows = zipWith(                (a, b) => justifyRight(w, ' ', a) + ' -> ' + b,                ys,                map(compose(fxShow, f), xs)            );        return s + '\n' + unlines(rows);    };     // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = (n, xs) =>        'GeneratorFunction' !== xs.constructor.constructor.name ? (            xs.slice(0, n)        ) : [].concat.apply([], Array.from({            length: n        }, () => {            const x = xs.next();            return x.done ? [] : [x.value];        }));     // unlines :: [String] -> String    const unlines = xs => xs.join('\n');     // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]    const zipWith = (f, xs, ys) => {        const            lng = Math.min(length(xs), length(ys)),            as = take(lng, xs),            bs = take(lng, ys);        return Array.from({            length: lng        }, (_, i) => f(as[i], bs[i], i));    };     // MAIN ---    return main();})();`
Output:
```Range consolidations:
[[1.1,2.2]] -> [[1.1,2.2]]
[[6.1,7.2],[7.2,8.3]] -> [[6.1,8.3]]
[[4,3],[2,1]] -> [[1,2],[3,4]]
[[4,3],[2,1],[-1,-2],[3.9,10]] -> [[-2,-1],[1,2],[3,10]]
[[1,3],[-6,-1],[-4,-5],[8,2],[-6,-6]] -> [[-6,-1],[1,8]]```

Julia

In Julia, a Range is a type of iterator, generally one over a specified interval. The task as specified is orthogonal to the iteration purpose of a Julia Range, since the task is about merging sets of numbers, not iterations. Therefore, a translation of the Python code is done, rather than using a native Julia Range.

Translation of: Python
`normalize(s) = sort([sort(bounds) for bounds in s]) function consolidate(ranges)    norm = normalize(ranges)    for (i, r1) in enumerate(norm)        if !isempty(r1)            for r2 in norm[i+1:end]                if !isempty(r2) && r1[end] >= r2[1]     # intersect?                    r1 .= [r1[1], max(r1[end], r2[end])]                    empty!(r2)                end            end        end    end    [r for r in norm if !isempty(r)]end function testranges()    for s in [[[1.1, 2.2]], [[6.1, 7.2], [7.2, 8.3]], [[4, 3], [2, 1]],              [[4, 3], [2, 1], [-1, -2], [3.9, 10]],              [[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]]]        println("\$s => \$(consolidate(s))")    endend testranges() `
Output:
```Array{Float64,1}[[1.1, 2.2]] => Array{Float64,1}[[1.1, 2.2]]
Array{Float64,1}[[6.1, 7.2], [7.2, 8.3]] => Array{Float64,1}[[6.1, 8.3]]
Array{Float64,1}[[4.0, 3.0], [2.0, 1.0]] => Array{Float64,1}[[1.0, 2.0], [3.0, 4.0]]
Array{Float64,1}[[4.0, 3.0], [2.0, 1.0], [-1.0, -2.0], [3.9, 10.0]] => Array{Float64,1}[[-2.0, -1.0], [1.0, 2.0], [3.0, 10.0]]
Array{Float64,1}[[1.0, 3.0], [-6.0, -1.0], [-4.0, -5.0], [8.0, 2.0], [-6.0, -6.0]] => Array{Float64,1}[[-6.0, -1.0], [1.0, 8.0]]
```

Kotlin

`fun <T> consolidate(ranges: Iterable<ClosedRange<T>>): List<ClosedRange<T>> where T : Comparable<T>{    return ranges        .sortedWith(compareBy({ it.start }, { it.endInclusive }))        .asReversed()        .fold(mutableListOf<ClosedRange<T>>()) {            consolidatedRanges, range ->            if (consolidatedRanges.isEmpty())            {                consolidatedRanges.add(range)            }            // Keep in mind the reverse-sorting applied above:            // If the end of the current-range is higher, than it must start at a lower value,            else if (range.endInclusive >= consolidatedRanges[0].endInclusive)            {                consolidatedRanges[0] = range            }            else if (range.endInclusive >= consolidatedRanges[0].start)            {                consolidatedRanges[0] = range.start .. consolidatedRanges[0].endInclusive            }            else            {                consolidatedRanges.add(0, range)            }             [email protected] consolidatedRanges        }        .toList()} // What a bummer! Kotlin's range syntax (a..b) doesn't meet the task requirements when b < b,// and on the other hand, the syntax for constructing lists, arrays and pairs isn't close enough// to the range notation. Instead then, here's a *very* naive parser. Don't take it seriously.val rangeRegex = Regex("""\[(.+),(.+)\]""")fun parseDoubleRange(rangeStr: String): ClosedFloatingPointRange<Double> {    val parts = rangeRegex        .matchEntire(rangeStr)        ?.groupValues        ?.drop(1)        ?.map { it.toDouble() }        ?.sorted()    if (parts == null) throw IllegalArgumentException("Unable to parse range \$rangeStr")    return parts[0] .. parts[1]} fun serializeRange(range: ClosedRange<*>) = "[\${range.start}, \${range.endInclusive}]" // See above. In practice you'd probably use consolidate directlyfun consolidateDoubleRanges(rangeStrings: Iterable<String>): List<String>{    return consolidate(rangeStrings.asSequence().map(::parseDoubleRange).toList()).map(::serializeRange)}  fun main() {    val inputRanges = listOf(        listOf("[1.1, 2.2]"),        listOf("[6.1, 7.2]", "[7.2, 8.3]"),        listOf("[4, 3]", "[2, 1]"),        listOf("[4, 3]", "[2, 1]", "[-1, -2]", "[3.9, 10]"),        listOf("[1, 3]", "[-6, -1]", "[-4, -5]", "[8, 2]", "[-6, -6]")    )     inputRanges.associateBy(Any::toString, ::consolidateDoubleRanges).forEach({ println("\${it.key} => \${it.value}") })}`
Output:
```[[1.1, 2.2]] => [[1.1, 2.2]]
[[6.1, 7.2], [7.2, 8.3]] => [[6.1, 8.3]]
[[4, 3], [2, 1]] => [[1.0, 2.0], [3.0, 4.0]]
[[4, 3], [2, 1], [-1, -2], [3.9, 10]] => [[-2.0, -1.0], [1.0, 2.0], [3.0, 10.0]]
[[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]] => [[-6.0, -1.0], [1.0, 8.0]]
```

Perl

Note: the output is shown in the standard Perl notation for Ranges.

`use strict;use warnings; use List::Util qw(min max); sub consolidate {    our @arr; local *arr = shift;    my @sorted = sort { @\$a[0] <=> @\$b[0] } map { [sort { \$a <=> \$b } @\$_] } @arr;    my @merge = shift @sorted;    for my \$i (@sorted) {        if (\$merge[-1][1] >= @\$i[0]) {            \$merge[-1][0] = min(\$merge[-1][0], @\$i[0]);            \$merge[-1][1] = max(\$merge[-1][1], @\$i[1]);        } else {            push @merge, \$i;        }    }    return @merge;} for my \$intervals (    [[1.1, 2.2],],    [[6.1, 7.2], [7.2, 8.3]],    [[4, 3], [2, 1]],    [[4, 3], [2, 1], [-1, -2], [3.9, 10]],    [[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]]) {        my(\$in,\$out);        \$in   = join ', ', map { '[' . join(', ', @\$_) . ']' } @\$intervals;        \$out .= join('..', @\$_). ' ' for consolidate(\$intervals);        printf "%44s => %s\n", \$in, \$out;}`
Output:
```                                  [1.1, 2.2] => 1.1..2.2
[6.1, 7.2], [7.2, 8.3] => 6.1..8.3
[4, 3], [2, 1] => 1..2 3..4
[4, 3], [2, 1], [-1, -2], [3.9, 10] => -2..-1 1..2 3..10
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] => -6..-1 1..8```

Phix

`function consolidate(sequence sets)    for i=length(sets) to 1 by -1 do        sets[i] = sort(sets[i])        atom {is,ie} = sets[i]        for j=length(sets) to i+1 by -1 do            atom {js,je} = sets[j]            bool overlap = iff(is<=js?js<=ie:is<=je)            if overlap then                sets[i] = {min(is,js),max(ie,je)}                sets[j..j] = {}            end if        end for    end for    return sort(sets)end function procedure test(sequence set)    printf(1,"%40v => %v\n",{set,consolidate(set)})end procedure test({{1.1,2.2}})test({{6.1,7.2},{7.2,8.3}})test({{4,3},{2,1}})test({{4,3},{2,1},{-1,-2},{3.9,10}})test({{1,3},{-6,-1},{-4,-5},{8,2},{-6,-6}})`
Output:
```                             {{1.1,2.2}} => {{1.1,2.2}}
{{6.1,7.2},{7.2,8.3}} => {{6.1,8.3}}
{{4,3},{2,1}} => {{1,2},{3,4}}
{{4,3},{2,1},{-1,-2},{3.9,10}} => {{-2,-1},{1,2},{3,10}}
{{1,3},{-6,-1},{-4,-5},{8,2},{-6,-6}} => {{-6,-1},{1,8}}
```

Prolog

Works with: SWI Prolog
`consolidate_ranges(Ranges, Consolidated):-    normalize(Ranges, Normalized),    sort(Normalized, Sorted),    merge(Sorted, Consolidated). normalize([], []):-!.normalize([r(X, Y)|Ranges], [r(Min, Max)|Normalized]):-    (X > Y -> Min = Y, Max = X; Min = X, Max = Y),    normalize(Ranges, Normalized). merge([], []):-!.merge([Range], [Range]):-!.merge([r(Min1, Max1), r(Min2, Max2)|Rest], Merged):-    Min2 =< Max1,    !,    Max is max(Max1, Max2),    merge([r(Min1, Max)|Rest], Merged).merge([Range|Ranges], [Range|Merged]):-    merge(Ranges, Merged). write_range(r(Min, Max)):-    writef('[%w, %w]', [Min, Max]). write_ranges([]):-!.write_ranges([Range]):-    !,    write_range(Range).write_ranges([Range|Ranges]):-    write_range(Range),    write(', '),    write_ranges(Ranges). test_case([r(1.1, 2.2)]).test_case([r(6.1, 7.2), r(7.2, 8.3)]).test_case([r(4, 3), r(2, 1)]).test_case([r(4, 3), r(2, 1), r(-1, -2), r(3.9, 10)]).test_case([r(1, 3), r(-6, -1), r(-4, -5), r(8, 2), r(-6, -6)]). main:-    forall(test_case(Ranges),           (consolidate_ranges(Ranges, Consolidated),            write_ranges(Ranges), write(' -> '),            write_ranges(Consolidated), nl)).`
Output:
```[1.1, 2.2] -> [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3] -> [6.1, 8.3]
[4, 3], [2, 1] -> [1, 2], [3, 4]
[4, 3], [2, 1], [-1, -2], [3.9, 10] -> [-2, -1], [1, 2], [3, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] -> [-6, -1], [1, 8]
```

Python

Procedural

`def normalize(s):    return sorted(sorted(bounds) for bounds in s if bounds) def consolidate(ranges):    norm = normalize(ranges)    for i, r1 in enumerate(norm):        if r1:            for r2 in norm[i+1:]:                if r2 and r1[-1] >= r2[0]:     # intersect?                    r1[:] = [r1[0], max(r1[-1], r2[-1])]                    r2.clear()    return [rnge for rnge in norm if rnge] if __name__ == '__main__':    for s in [            [[1.1, 2.2]],            [[6.1, 7.2], [7.2, 8.3]],            [[4, 3], [2, 1]],            [[4, 3], [2, 1], [-1, -2], [3.9, 10]],            [[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]],            ]:        print(f"{str(s)[1:-1]} => {str(consolidate(s))[1:-1]}") `
Output:
```[1.1, 2.2] => [1.1, 2.2]
[6.1, 7.2], [7.2, 8.3] => [6.1, 8.3]
[4, 3], [2, 1] => [1, 2], [3, 4]
[4, 3], [2, 1], [-1, -2], [3.9, 10] => [-2, -1], [1, 2], [3, 10]
[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6] => [-6, -1], [1, 8]```

Functional

Defining consolidation as a fold over a list of tuples:

Translation of: Haskell
Works with: Python version 3.7
`'''Range consolidation''' from functools import reduce  # consolidated :: [(Float, Float)] -> [(Float, Float)]def consolidated(xs):    '''A consolidated list of       [(Float, Float)] ranges.'''     def go(abetc, xy):        '''A copy of the accumulator abetc,           with its head range ab either:           1. replaced by or           2. merged with           the next range xy, or           with xy simply prepended.'''        if abetc:            a, b = abetc[0]            etc = abetc[1:]            x, y = xy            return [xy] + etc if y >= b else (   # ab replaced.                [(x, b)] + etc if y >= a else (  # xy + ab merged.                    [xy] + abetc                 # xy simply prepended.                )            )        else:            return [xy]     def tupleSort(ab):        a, b = ab        return ab if a <= b else (b, a)     return reduce(        go,        sorted(map(tupleSort, xs), reverse=True),        []    )  # TEST ----------------------------------------------------# main :: IO ()def main():    '''Tests'''     print(        tabulated('Consolidation of numeric ranges:')(str)(str)(            consolidated        )([            [(1.1, 2.2)],            [(6.1, 7.2), (7.2, 8.3)],            [(4, 3), (2, 1)],            [(4, 3), (2, 1), (-1, -2), (3.9, 10)],            [(1, 3), (-6, -1), (-4, -5), (8, 2), (-6, -6)]        ])    )  # GENERIC FUNCTIONS FOR DISPLAY ---------------------------  # compose (<<<) :: (b -> c) -> (a -> b) -> a -> cdef compose(g):    '''Right to left function composition.'''    return lambda f: lambda x: g(f(x))  # tabulated :: String -> (a -> String) ->#                        (b -> String) ->#                        (a -> b) -> [a] -> Stringdef tabulated(s):    '''Heading -> x display function -> fx display function ->          f -> value list -> tabular string.'''    def go(xShow, fxShow, f, xs):        w = max(map(compose(len)(xShow), xs))        return s + '\n' + '\n'.join([            xShow(x).rjust(w, ' ') + ' -> ' + fxShow(f(x)) for x in xs        ])    return lambda xShow: lambda fxShow: (        lambda f: lambda xs: go(            xShow, fxShow, f, xs        )    )  # MAIN ---if __name__ == '__main__':    main()`
Output:
```Consolidation of numeric ranges:
[(1.1, 2.2)] -> [(1.1, 2.2)]
[(6.1, 7.2), (7.2, 8.3)] -> [(6.1, 8.3)]
[(4, 3), (2, 1)] -> [(1, 2), (3, 4)]
[(4, 3), (2, 1), (-1, -2), (3.9, 10)] -> [(-2, -1), (1, 2), (3, 10)]
[(1, 3), (-6, -1), (-4, -5), (8, 2), (-6, -6)] -> [(-6, -1), (1, 8)]```

Racket

`#lang racket ;; Racket's max and min allow inexact numbers to contaminate exact numbers;; Use argmax and argmin instead, as they don't have this problem (define (max . xs) (argmax identity xs))(define (min . xs) (argmin identity xs)) ;; a bag is a list of disjoint intervals (define ((irrelevant? x y) item) (or (< (second item) x) (> (first item) y))) (define (insert bag x y)  (define-values (irrelevant relevant) (partition (irrelevant? x y) bag))  (cons (list (apply min x (map first relevant))              (apply max y (map second relevant))) irrelevant)) (define (solve xs)  (sort (for/fold ([bag '()]) ([x (in-list xs)])          (insert bag (apply min x) (apply max x))) < #:key first)) (define inputs '(([1.1 2.2])                 ([6.1 7.2] [7.2 8.3])                 ([4 3] [2 1])                 ([4 3] [2 1] [-1 -2] [3.9 10])                 ([1 3] [-6 -1] [-4 -5] [8 2] [-6 -6]))) (for ([xs (in-list inputs)]) (printf "~a => ~a\n" xs (solve xs)))`
Output:
```((1.1 2.2)) => ((1.1 2.2))
((6.1 7.2) (7.2 8.3)) => ((6.1 8.3))
((4 3) (2 1)) => ((1 2) (3 4))
((4 3) (2 1) (-1 -2) (3.9 10)) => ((-2 -1) (1 2) (3 10))
((1 3) (-6 -1) (-4 -5) (8 2) (-6 -6)) => ((-6 -1) (1 8))
```

Raku

(formerly Perl 6)

Works with: Rakudo version 2020.08.1

In Raku, a Range is a first class object with its own specialized notation. Raku Ranges allow for exclusion of the boundary numbers. This example doesn't since it isn't a requirement in this task. Much of the logic is lifted from the Set_of_real_numbers task with simplified logic for the much simpler requirements.

Note: the output is in standard Raku notation for Ranges.

`# Unionsub infix:<∪> (Range \$a, Range \$b) { Range.new(\$a.min,max(\$a.max,\$b.max)) } # Intersectionsub infix:<∩> (Range \$a, Range \$b) { so \$a.max >= \$b.min } multi consolidate() { () } multi consolidate(\$this is copy, **@those) {    gather {        for consolidate |@those -> \$that {            if \$this ∩ \$that { \$this ∪= \$that }            else             { take \$that }        }        take \$this;    }} for [[1.1, 2.2],],    [[6.1, 7.2], [7.2, 8.3]],    [[4, 3], [2, 1]],    [[4, 3], [2, 1], [-1, -2], [3.9, 10]],    [[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]]-> @intervals {    printf "%46s => ", @intervals.raku;    say reverse consolidate |@intervals.grep(*.elems)».sort.sort({ [.[0], .[*-1]] }).map: { Range.new(.[0], .[*-1]) }}`
Output:
```                                 [[1.1, 2.2],] => (1.1..2.2)
[[6.1, 7.2], [7.2, 8.3]] => (6.1..8.3)
[[4, 3], [2, 1]] => (1..2 3..4)
[[4, 3], [2, 1], [-1, -2], [3.9, 10]] => (-2..-1 1..2 3..10)
[[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]] => (-6..-1 1..8)
```

REXX

Most of the REXX code was testing (and rebuilding) the syntax (insuring blanks after commas), and handling of a null set.

The actual logic for the range consolidation is marked with the comments:     /*■■■■►*/

`/*REXX program performs range consolidation (they can be [equal] ascending/descending). */#.=                                              /*define the default for range sets.   */parse arg #.1                                    /*obtain optional arguments from the CL*/if #.1=''  then do                               /*Not specified?  Then use the defaults*/                #.1= '[1.1, 2.2]'                #.2= '[6.1, 7.2], [7.2, 8.3]'                #.3= '[4, 3], [2, 1]'                #.4= '[4, 3], [2, 1], [-1, -2], [3.9, 10]'                #.5= '[1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]'                #.6= '[]'                end        do j=1  while #.j\=='';   \$= #.j          /*process each of the range sets.      */       say copies('═', 75)                       /*display a fence between range sets.  */       say '         original ranges:'     \$     /*display the original range set.      */       \$= order(\$)                               /*order low and high ranges; normalize.*/       call xSort  words(\$)                      /*sort the ranges using a simple sort. */       \$= merge(\$)                               /*consolidate the ranges.              */       say '     consolidated ranges:'     \$     /*display the consolidated range set.  */       end   /*j*/exit                                             /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/merge: procedure expose @.; parse arg y       if words(y)<2  then signal build          /*Null or only 1 range?  Skip merging. */           do j=1  to @.0-1;         if @.j==''  then iterate      /*skip deleted ranges.*/            do k=j+1  to  @.0;      if @.k==''  then iterate      /*  "     "       "   */            parse var  @.j  a   b;  parse var  @.k  aa  bb        /*extract low and high*//*■■■■►*/   if a<=aa & b>=bb  then  do; @.k=;  iterate;            end  /*within a range*//*■■■■►*/   if a<=aa & b>=aa  then  do; @.j= a bb; @.k=; iterate;  end  /*abutted ranges*/            end   /*k*/          end     /*j*/build: z=             do r=1  for @.0;  z= z translate(@.r, ',', " ");  end   /*r*/   /*add comma*/       f=;   do s=1  for words(z);   f= f '['word(z, s)"], ";  end   /*s*/   /*add [ ], */       if f==''  then return '[]'                                            /*null set.*/       return space( changestr(',',  strip( space(f), 'T', ","), ", ") )     /*add blank*//*──────────────────────────────────────────────────────────────────────────────────────*/order: procedure expose @.; parse arg y,,z;  @.= /*obtain arguments from the invocation.*/       y= space(y, 0)                            /*elide superfluous blanks in the sets.*/          do k=1  while y\==''  &  y\=='[]'      /*process ranges while range not blank.*/          y= strip(y, 'L', ",")                  /*elide commas between sets of ranges. */          parse var  y   '['  L  ","  H  ']'   y /*extract  the "low" and "high" values.*/          if H<L  then parse value  L H with H L /*order     "    "    "     "      "   */          L= L / 1;     H= H / 1                 /*normalize the  L  and the  H  values.*/          @.k= L H;     z= z L','H               /*re─build the set w/o and with commas.*/          end   /*k*/                            /* [↓]  at this point, K is one to big.*/       @.0= k - 1                                /*keep track of the number of ranges.  */       return strip(z)                           /*elide the extra leading blank in set.*//*──────────────────────────────────────────────────────────────────────────────────────*/xSort: procedure expose @.; parse arg n          /*a simple sort for small set of ranges*/          do j=1  to n-1;                        _= @.j            do k=j+1  to n; if word(@.k,1)>=word(_,1)  then iterate; @.[email protected].k; @.k=_; [email protected].j            end   /*k*/          end     /*j*/;        return`
output   when using the default inputs:
```═══════════════════════════════════════════════════════════════════════════
original ranges: [1.1, 2.2]
consolidated ranges: [1.1, 2.2]
═══════════════════════════════════════════════════════════════════════════
original ranges: [6.1, 7.2], [7.2, 8.3]
consolidated ranges: [6.1, 8.3]
═══════════════════════════════════════════════════════════════════════════
original ranges: [4, 3], [2, 1]
consolidated ranges: [1, 2], [3, 4]
═══════════════════════════════════════════════════════════════════════════
original ranges: [4, 3], [2, 1], [-1, -2], [3.9, 10]
consolidated ranges: [-2, -1], [1, 2], [3, 10]
═══════════════════════════════════════════════════════════════════════════
original ranges: [1, 3], [-6, -1], [-4, -5], [8, 2], [-6, -6]
consolidated ranges: [-6, -1], [1, 8]
═══════════════════════════════════════════════════════════════════════════
original ranges: []
consolidated ranges: []
```

Rust

Most of the implementation below belongs to the test and formatting support. If the output might be more arbitrary, the source would be quite small. The algorithm relies on normalizing the ranges and folding a sorted sequence of them.

`use std::fmt::{Display, Formatter}; // We could use std::ops::RangeInclusive, but we would have to extend it to// normalize self (not much trouble) and it would not have to handle pretty// printing for it explicitly. So, let's make rather an own type. #[derive(Clone, Debug, PartialEq, PartialOrd)]pub struct ClosedRange<Idx> {    start: Idx,    end: Idx,} impl<Idx> ClosedRange<Idx> {    pub fn start(&self) -> &Idx {        &self.start    }     pub fn end(&self) -> &Idx {        &self.end    }} impl<Idx: PartialOrd> ClosedRange<Idx> {    pub fn new(start: Idx, end: Idx) -> Self {        if start <= end {            Self { start, end }        } else {            Self {                end: start,                start: end,            }        }    }} // To make test input more compactimpl<Idx: PartialOrd> From<(Idx, Idx)> for ClosedRange<Idx> {    fn from((start, end): (Idx, Idx)) -> Self {        Self::new(start, end)    }} // For the required print formatimpl<Idx: Display> Display for ClosedRange<Idx> {    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {        write!(f, "[{}, {}]", self.start, self.end)    }} fn consolidate<Idx>(a: &ClosedRange<Idx>, b: &ClosedRange<Idx>) -> Option<ClosedRange<Idx>>where    Idx: PartialOrd + Clone,{    if a.start() <= b.start() {        if b.end() <= a.end() {            Some(a.clone())        } else if a.end() < b.start() {            None        } else {            Some(ClosedRange::new(a.start().clone(), b.end().clone()))        }    } else {        consolidate(b, a)    }} fn consolidate_all<Idx>(mut ranges: Vec<ClosedRange<Idx>>) -> Vec<ClosedRange<Idx>>where    Idx: PartialOrd + Clone,{    // Panics for incomparable elements! So no NaN for floats, for instance.    ranges.sort_by(|a, b| a.partial_cmp(b).unwrap());    let mut ranges = ranges.into_iter();    let mut result = Vec::new();     if let Some(current) = ranges.next() {        let leftover = ranges.fold(current, |mut acc, next| {            match consolidate(&acc, &next) {                Some(merger) => {                    acc = merger;                }                 None => {                    result.push(acc);                    acc = next;                }            }             acc        });         result.push(leftover);    }     result} #[cfg(test)]mod tests {    use super::{consolidate_all, ClosedRange};    use std::fmt::{Display, Formatter};     struct IteratorToDisplay<F>(F);     impl<F, I> Display for IteratorToDisplay<F>    where        F: Fn() -> I,        I: Iterator,        I::Item: Display,    {        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {            let mut items = self.0();             if let Some(item) = items.next() {                write!(f, "{}", item)?;                for item in items {                    write!(f, ", {}", item)?;                }            }             Ok(())        }    }     macro_rules! parameterized {        (\$(\$name:ident: \$value:expr,)*) => {            \$(                #[test]                fn \$name() {                    let (input, expected) = \$value;                    let expected: Vec<_> = expected.into_iter().map(ClosedRange::from).collect();                    let output = consolidate_all(input.into_iter().map(ClosedRange::from).collect());                    println!("{}: {}", stringify!(\$name), IteratorToDisplay(|| output.iter()));                    assert_eq!(expected, output);                }            )*        }    }     parameterized! {        single: (vec![(1.1, 2.2)], vec![(1.1, 2.2)]),        touching: (vec![(6.1, 7.2), (7.2, 8.3)], vec![(6.1, 8.3)]),        disjoint: (vec![(4, 3), (2, 1)], vec![(1, 2), (3, 4)]),        overlap: (vec![(4.0, 3.0), (2.0, 1.0), (-1.0, -2.0), (3.9, 10.0)], vec![(-2.0, -1.0), (1.0, 2.0), (3.0, 10.0)]),        integer: (vec![(1, 3), (-6, -1), (-4, -5), (8, 2), (-6, -6)], vec![(-6, -1), (1, 8)]),    }} fn main() {    // To prevent dead code and to check empty input    consolidate_all(Vec::<ClosedRange<usize>>::new());     println!("Run: cargo test -- --nocapture");}`
Output:
```running 5 tests
integer: [-6, -1], [1, 8]
disjoint: [1, 2], [3, 4]
single: [1.1, 2.2]
touching: [6.1, 8.3]
overlap: [-2, -1], [1, 2], [3, 10]
test tests::integer ... ok
test tests::disjoint ... ok
test tests::single ... ok
test tests::touching ... ok
test tests::overlap ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```

Wren

Library: Wren-math

As Wren already has a built-in Range class (which is not quite the same as what's required here), we create a Span class instead.

`import "/math" for Math class Span {    construct new(r) {        if (r.type != Range || !r.isInclusive) Fiber.abort("Argument must be an inclusive range.")        _low = r.from        _high = r.to        if (_low > _high) {            _low = r.to            _high = r.from        }    }     low  { _low }    high { _high }     consolidate(r) {         if (r.type != Span) Fiber.abort("Argument must be a Span.")         if (_high < r.low) return [this, r]         if (r.high < _low) return [r, this]         return [Span.new(Math.min(_low, r.low)..Math.max(_high, r.high))]    }     toString { "[%(_low), %(_high)]" }} var spanLists = [    [Span.new(1.1..2.2)],    [Span.new(6.1..7.2), Span.new(7.2..8.3)],    [Span.new(4..3), Span.new(2..1)],    [Span.new(4..3), Span.new(2..1), Span.new(-1..-2), Span.new(3.9..10)],    [Span.new(1..3), Span.new(-6..-1), Span.new(-4..-5), Span.new(8..2), Span.new(-6..-6)]] for (spanList in spanLists) {    if (spanList.count == 1) {        System.print(spanList.toString[1..-2])    } else if (spanList.count == 2) {        System.print(spanList[0].consolidate(spanList[1]).toString[1..-2])    } else {        var first = 0        while (first < spanList.count-1) {            var next = first + 1            while (next < spanList.count) {                var res = spanList[first].consolidate(spanList[next])                spanList[first] = res[0]                if (res.count == 2) {                    spanList[next] = res[1]                    next = next + 1                } else {                    spanList.removeAt(next)                }            }            first = first + 1        }        System.print(spanList.toString[1..-2])    } }`
Output:
```[1.1, 2.2]
[6.1, 8.3]
[1, 2], [3, 4]
[-2, -1], [1, 2], [3, 10]
[-6, -1], [1, 8]
```

Yabasic

`sub sort(tabla())    local items, i, t1, t2, s     items = arraysize(tabla(), 1)     repeat        s = true        for i = 1 to items-1            if tabla(i, 1) > tabla(i+1, 1) then                t1 = tabla(i, 1) : t2 = tabla(i, 2)                tabla(i, 1) = tabla(i + 1, 1) : tabla(i, 2) = tabla(i + 1, 2)                tabla(i + 1, 1) = t1 : tabla(i + 1, 2) = t2                s = false            end if        next    until(s)end sub sub normalize(tabla())    local items, i, t     items = arraysize(tabla(), 1)     for i = 1 to items        if tabla(i, 1) > tabla(i, 2) then            t = tabla(i, 1)            tabla(i, 1) = tabla(i, 2)            tabla(i, 2) = t        end if    next     sort(tabla())end sub sub consolidate(tabla())    local items, i     normalize(tabla())    items = arraysize(tabla(), 1)     for i = 1 to items - 1        if tabla(i + 1, 1) <= tabla(i, 2) then            tabla(i + 1, 1) = tabla(i, 1)            if tabla(i + 1, 2) <= tabla(i, 2) then                tabla(i + 1, 2) = tabla(i, 2)            end if            tabla(i, 1) = void : tabla(i, 2) = void        end if    nextend sub // data 1, 1.1, 2.2// data 2, 6.1, 7.2, 7.2, 8.3// data 2, 4, 3, 2, 1// data 4, 4, 3, 2, 1, -1, -2, 3.9, 10 data 5, 1,3, -6,-1, -4,-5, 8,2, -6,-6 void = 10^30read items dim tabla(items,  2) for i = 1 to items    read tabla(i, 1), tabla(i, 2)next consolidate(tabla()) for i = 1 to items    if tabla(i, 1) <> void print tabla(i, 1), "..", tabla(i, 2);next`

zkl

`fcn consolidate(rs){   (s:=List()).append(      normalize(rs).reduce('wrap(ab,cd){     if(ab[1]>=cd[0]) L(ab[0],ab[1].max(cd[1])); // consolidate     else{ s.append(ab); cd }            // no overlap      }) )}fcn normalize(s){ s.apply("sort").sort(fcn(a,b){ a[0]<b[0] }) }`
`foreach rs in (L(   L(L(1.1, 2.2)),    L(L(6.1, 7.2), L(7.2, 8.3)),    L(L(4, 3), L(2, 1)),   L(L(4.0, 3.0), L(2.0, 1.0), L(-1.0, -2.0), L(3.9, 10.0)),   L(L(1, 3), L(-6, -1), L(-4, -5), L(8, 2), L(-6, -6)), )){ println(ppp(rs),"--> ",ppp(consolidate(rs))) }fcn ppp(ll){ ll.pump(String,fcn(list){ list.concat(", ",  "[",  "] ") }) }`
Output:
```[1.1, 2.2] --> [1.1, 2.2]
[6.1, 7.2] [7.2, 8.3] --> [6.1, 8.3]
[4, 3] [2, 1] --> [1, 2] [3, 4]
[4, 3] [2, 1] [-1, -2] [3.9, 10] --> [-2, -1] [1, 2] [3, 10]
[1, 3] [-6, -1] [-4, -5] [8, 2] [-6, -6] --> [-6, -1] [1, 8]
```