Task: Range consolidation

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



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











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;