Task: Convex hull





Java: import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static java.util.Collections.emptyList;

public class ConvexHull {
    private static class Point implements Comparable<Point> {
        private int x, y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public int compareTo(Point o) {
            return Integer.compare(x, o.x);
        }

        @Override
        public String toString() {
            return String.format("(%d, %d)", x, y);
        }
    }

    private static List<Point> convexHull(List<Point> p) {
        if (p.isEmpty()) return emptyList();
        p.sort(Point::compareTo);
        List<Point> h = new ArrayList<>();

        
        for (Point pt : p) {
            while (h.size() >= 2 && !ccw(h.get(h.size() - 2), h.get(h.size() - 1), pt)) {
                h.remove(h.size() - 1);
            }
            h.add(pt);
        }

        
        int t = h.size() + 1;
        for (int i = p.size() - 1; i >= 0; i--) {
            Point pt = p.get(i);
            while (h.size() >= t && !ccw(h.get(h.size() - 2), h.get(h.size() - 1), pt)) {
                h.remove(h.size() - 1);
            }
            h.add(pt);
        }

        h.remove(h.size() - 1);
        return h;
    }

    
    private static boolean ccw(Point a, Point b, Point c) {
        return ((b.x - a.x) * (c.y - a.y)) > ((b.y - a.y) * (c.x - a.x));
    }

    public static void main(String[] args) {
        List<Point> points = Arrays.asList(new Point(16, 3),
                                           new Point(12, 17),
                                           new Point(0, 6),
                                           new Point(-4, -6),
                                           new Point(16, 6),

                                           new Point(16, -7),
                                           new Point(16, -3),
                                           new Point(17, -4),
                                           new Point(5, 19),
                                           new Point(19, -8),

                                           new Point(3, 16),
                                           new Point(12, 13),
                                           new Point(3, -4),
                                           new Point(17, 5),
                                           new Point(-3, 15),

                                           new Point(-3, -9),
                                           new Point(0, 11),
                                           new Point(-9, -3),
                                           new Point(-4, -2),
                                           new Point(12, 10));

        List<Point> hull = convexHull(points);
        System.out.printf("Convex Hull: %s\n", hull);
    }
}







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;