Task: Convex hull

C: #include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
 
typedef struct tPoint {
    int x, y;
} Point;
 
bool ccw(const Point *a, const Point *b, const Point *c) {
    return (b->x - a->x) * (c->y - a->y)
         > (b->y - a->y) * (c->x - a->x);
}
 
int comparePoints(const void *lhs, const void *rhs) {
    const Point* lp = lhs;
    const Point* rp = rhs;
    if (lp->x < rp->x)
        return -1;
    if (rp->x < lp->x)
        return 1;
    if (lp->y < rp->y)
        return -1;
    if (rp->y < lp->y)
        return 1;
    return 0;
}

void fatal(const char* message) {
    fprintf(stderr, "%s\n", message);
    exit(1);
}

void* xmalloc(size_t n) {
    void* ptr = malloc(n);
    if (ptr == NULL)
        fatal("Out of memory");
    return ptr;
}

void* xrealloc(void* p, size_t n) {
    void* ptr = realloc(p, n);
    if (ptr == NULL)
        fatal("Out of memory");
    return ptr;
}

void printPoints(const Point* points, int len) {
    printf("[");
    if (len > 0) {
        const Point* ptr = points;
        const Point* end = points + len;
        printf("(%d, %d)", ptr->x, ptr->y);
        ++ptr;
        for (; ptr < end; ++ptr)
            printf(", (%d, %d)", ptr->x, ptr->y);
    }
    printf("]");
}
 
Point* convexHull(Point p[], int len, int* hsize) {
    if (len == 0) {
        *hsize = 0;
        return NULL;
    }

    int i, size = 0, capacity = 4;
    Point* hull = xmalloc(capacity * sizeof(Point));

    qsort(p, len, sizeof(Point), comparePoints);
 
    
    for (i = 0; i < len; ++i) {
        while (size >= 2 && !ccw(&hull[size - 2], &hull[size - 1], &p[i]))
            --size;
        if (size == capacity) {
            capacity *= 2;
            hull = xrealloc(hull, capacity * sizeof(Point));
        }
        assert(size >= 0 && size < capacity);
        hull[size++] = p[i];
    }
 
    
    int t = size + 1;
    for (i = len - 1; i >= 0; i--) {
        while (size >= t && !ccw(&hull[size - 2], &hull[size - 1], &p[i]))
            --size;
        if (size == capacity) {
            capacity *= 2;
            hull = xrealloc(hull, capacity * sizeof(Point));
        }
        assert(size >= 0 && size < capacity);
        hull[size++] = p[i];
    }
    --size;
    assert(size >= 0);
    hull = xrealloc(hull, size * sizeof(Point));
    *hsize = size;
    return hull;
}
 
int main() {
    Point points[] = {
        {16,  3}, {12, 17}, { 0,  6}, {-4, -6}, {16,  6},
        {16, -7}, {16, -3}, {17, -4}, { 5, 19}, {19, -8},
        { 3, 16}, {12, 13}, { 3, -4}, {17,  5}, {-3, 15},
        {-3, -9}, { 0, 11}, {-9, -3}, {-4, -2}, {12, 10}
    };
    int hsize;
    Point* hull = convexHull(points, sizeof(points)/sizeof(Point), &hsize);
    printf("Convex Hull: ");
    printPoints(hull, hsize);
    printf("\n");
    free(hull);
 
    return 0;
}











Ada: with Ada.Text_IO;
with Ada.Containers.Vectors;

procedure Convex_Hull is

   type Point is record
      X, Y : Integer;
   end record;

   package Point_Vectors is
      new Ada.Containers.Vectors (Index_Type   => Positive,
                                  Element_Type => Point);
   use Point_Vectors;

   function Find_Convex_Hull (Vec : in Vector) return Vector is

      function Counter_Clock_Wise (A, B, C : in Point) return Boolean is
         ((B.X - A.X) * (C.Y - A.Y) > (B.Y - A.Y) * (C.X - A.X));

      function Less_Than (Left, Right : Point) return Boolean is
         (Left.X < Right.X);

      package Sorter is
         new Point_Vectors.Generic_Sorting (Less_Than);

      Sorted : Vector := Vec;
      Result : Vector := Empty_vector;
      use type Ada.Containers.Count_Type;
   begin
      if Vec = Empty_Vector then
         return Empty_Vector;
      end if;

      Sorter.Sort (Sorted);

      
      for Index in Sorted.First_Index .. Sorted.Last_Index loop
         while
           Result.Length >= 2 and then
           not Counter_Clock_Wise (Result (Result.Last_Index - 1),
                                   Result (Result.Last_Index),
                                   Sorted (Index))
         loop
            Result.Delete_Last;
         end loop;
         Result.Append (Sorted (Index));
      end loop;

      
      declare
         T : constant Ada.Containers.Count_Type := Result.Length + 1;
      begin
         for Index in reverse Sorted.First_Index .. Sorted.Last_Index loop
            while
              Result.Length >= T and then
              not Counter_Clock_Wise (Result (Result.Last_Index - 1),
                                      Result (Result.Last_Index),
                                      Sorted (Index))
            loop
               Result.Delete_Last;
            end loop;
            Result.Append (Sorted (Index));
         end loop;
      end;

      Result.Delete_Last;
      return Result;
   end Find_Convex_Hull;

   procedure Show (Vec : in Vector) is
      use Ada.Text_IO;
   begin
      Put ("[ ");
      for Point of Vec loop
         Put ("(" & Point.X'Image & "," & Point.Y'Image & ")");
      end loop;
      Put (" ]");
   end Show;

   Vec : constant Vector :=
     (16, 3) & (12,17) & ( 0, 6) & (-4,-6) & (16, 6) &
     (16,-7) & (16,-3) & (17,-4) & ( 5,19) & (19,-8) &
     ( 3,16) & (12,13) & ( 3,-4) & (17, 5) & (-3,15) &
     (-3,-9) & ( 0,11) & (-9,-3) & (-4,-2) & (12,10);
begin
   Show (Find_Convex_Hull (Vec));
   Ada.Text_IO.New_Line;
end Convex_Hull;