Task: Heronian triangles





Java: import java.util.ArrayList;

public class Heron {
    public static void main(String[] args) {
        ArrayList<int[]> list = new ArrayList<>();

        for (int c = 1; c <= 200; c++) {
            for (int b = 1; b <= c; b++) {
                for (int a = 1; a <= b; a++) {

                    if (gcd(gcd(a, b), c) == 1 && isHeron(heronArea(a, b, c))){
                        int area = (int) heronArea(a, b, c);
                        list.add(new int[]{a, b, c, a + b + c, area});
                    }
                }
            }
        }
        sort(list);

        System.out.printf("Number of primitive Heronian triangles with sides up "
                + "to 200: %d\n\nFirst ten when ordered by increasing area, then"
                + " perimeter:\nSides       Perimeter   Area", list.size());

        for (int i = 0; i < 10; i++) {
            System.out.printf("\n%d x %d x %d   %d      %d",
                    list.get(i)[0], list.get(i)[1], list.get(i)[2],
                    list.get(i)[3], list.get(i)[4]);
        }

        System.out.printf("\n\nArea = 210\nSides        Perimeter   Area");
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i)[4] == 210)
                System.out.printf("\n%d x %d x %d   %d      %d",
                        list.get(i)[0], list.get(i)[1], list.get(i)[2],
                        list.get(i)[3], list.get(i)[4]);
        }
    }

    public static double heronArea(int a, int b, int c) {
        double s = (a + b + c) / 2f;
        return Math.sqrt(s * (s - a) * (s - b) * (s - c));
    }

    public static boolean isHeron(double h) {
        return h % 1 == 0 && h > 0;
    }

    public static int gcd(int a, int b) {
        int leftover = 1, dividend = a > b ? a : b, divisor = a > b ? b : a;
        while (leftover != 0) {
            leftover = dividend % divisor;
            if (leftover > 0) {
                dividend = divisor;
                divisor = leftover;
            }
        }
        return divisor;
    }

    public static void sort(ArrayList<int[]> list) {
        boolean swapped = true;
        int[] temp;
        while (swapped) {
            swapped = false;
            for (int i = 1; i < list.size(); i++) {
                if (list.get(i)[4] < list.get(i - 1)[4] ||
                        list.get(i)[4] == list.get(i - 1)[4] &&
                        list.get(i)[3] < list.get(i - 1)[3]) {
                    temp = list.get(i);
                    list.set(i, list.get(i - 1));
                    list.set(i - 1, temp);
                    swapped = true;
                }
            }
        }
    }
}







Ada: with Ada.Containers.Indefinite_Ordered_Sets;
with Ada.Finalization;
with Ada.Text_IO; use Ada.Text_IO;
procedure Heronian is
   package Int_IO is new Ada.Text_IO.Integer_IO(Integer);
   use Int_IO;
   
   
   function GCD (A, B : in Natural) return Natural is (if B = 0 then A else GCD (B, A mod B));
   
   function Int_Sqrt (N : in Natural) return Natural is
      R1 : Natural := N;
      R2 : Natural;
   begin
      if N <= 1 then
         return N;
      end if;
      loop
         R2 := (R1+N/R1)/2;
         if R2 >= R1 then
            return R1;
         end if;
         R1 := R2;
      end loop;
   end Int_Sqrt;   
   
   
   
   type t_Triangle (A, B, C : Positive) is new Ada.Finalization.Controlled with record
      Is_Heronian  : Boolean;
      Perimeter    : Positive;
      Area         : Natural;
   end record;

   overriding procedure Initialize (Self : in out t_Triangle) is
      
      
      
      
      Long_Product  : Long_Long_Integer;
      Short_Product : Natural;
   begin
      Self.Perimeter   := Self.A + Self.B + Self.C;
      Long_Product     :=   Long_Long_Integer(Self.Perimeter)
                          * Long_Long_Integer(- Self.A + Self.B + Self.C)
                          * Long_Long_Integer(  Self.A - Self.B + Self.C)
                          * Long_Long_Integer(  Self.A + Self.B - Self.C);
      Short_Product    := Natural(Long_Product / 16);
      Self.Area        := Int_Sqrt (Short_Product);
      Self.Is_Heronian := (Long_Product mod 16 = 0) and (Self.Area * Self.Area = Short_Product);
   end Initialize;
   
   
   function "<" (Left, Right : in t_Triangle) return Boolean is
     (Left.Area      < Right.Area      or else (Left.Area      = Right.Area      and then
     (Left.Perimeter < Right.Perimeter or else (Left.Perimeter = Right.Perimeter and then
     (Left.A         < Right.A         or else (Left.A         = Right.A         and then
     (Left.B         < Right.B         or else (Left.B         = Right.B         and then
      Left.C         < Right.C))))))));
   package Triangle_Lists is new Ada.Containers.Indefinite_Ordered_Sets (t_Triangle);
   use Triangle_Lists;

   
   Header : constant String := "  A   B   C Per  Area" & ASCII.LF & "
   procedure Put_Triangle (Position : Cursor) is
      Triangle : constant t_Triangle := Element(Position);
   begin
      Put(Triangle.A, 3);
      Put(Triangle.B, 4);
      Put(Triangle.C, 4);
      Put(Triangle.Perimeter, 4);
      Put(Triangle.Area,      6);
      New_Line;
   end Put_Triangle;

   
   Triangles : Set := Empty_Set;
   
   
   First_201 : Cursor := No_Element;
   Last_201  : Cursor := No_Element;

   procedure Memorize_Triangle (A, B, C : in Positive) is
      Candidate : t_Triangle(A, B, C);
      Position  : Cursor;
      Dummy     : Boolean;
   begin
      if Candidate.Is_Heronian then
         Triangles.Insert (Candidate, Position, Dummy);
         if Candidate.Area = 210 then
            First_201 := (if    First_201 = No_Element then Position
                          elsif Position < First_201   then Position
                          else  First_201);
            Last_201 :=  (if    Last_201  = No_Element then Position
                          elsif Last_201  < Position   then Position
                          else  Last_201);
         end if;
      end if;
   end Memorize_Triangle;
      
begin
   
   
   for A in 1..200 loop
      for B in A..200 loop
         for C in B..Integer'Min(A+B-1,200) loop
            
            if GCD(GCD(A,B),C) = 1 then 
               Memorize_Triangle (A, B, C);
            end if;
         end loop;
      end loop;
   end loop;
   
   Put_Line (Triangles.Length'Img & " heronian triangles found :");
   Put_Line (Header);
   Triangles.Iterate (Process => Put_Triangle'Access);
   New_Line;
   
   Put_Line ("Heronian triangles with area = 201");
   Put_Line (Header);
   declare
      Position : Cursor := First_201;
   begin
      loop
         Put_Triangle (Position);
         exit when Position = Last_201;
         Position := Next(Position);
      end loop;
   end;      
end Heronian;