Task: Range consolidation


C++: #include <algorithm>
#include <iostream>
#include <utility>
#include <vector>



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);
}



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;
}










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      
            First := Last;
            Last  := Next (Last);
         elsif Element (First).Right >= Element (Last).Left then  
            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;