Task: Heronian triangles







Python: from __future__ import division, print_function
from math import gcd, sqrt


def hero(a, b, c):
    s = (a + b + c) / 2
    a2 = s * (s - a) * (s - b) * (s - c)
    return sqrt(a2) if a2 > 0 else 0


def is_heronian(a, b, c):
    a = hero(a, b, c)
    return a > 0 and a.is_integer()


def gcd3(x, y, z):
    return gcd(gcd(x, y), z)


if __name__ == '__main__':
    MAXSIDE = 200

    N = 1 + MAXSIDE
    h = [(x, y, z)
         for x in range(1, N)
         for y in range(x, N)
         for z in range(y, N) if (x + y > z) and
         1 == gcd3(x, y, z) and
         is_heronian(x, y, z)]

    
    h.sort(key=lambda x: (hero(*x), sum(x), x[::-1]))

    print(
        'Primitive Heronian triangles with sides up to %i:' % MAXSIDE, len(h)
    )
    print('\nFirst ten when ordered by increasing area, then perimeter,',
          'then maximum sides:')
    print('\n'.join('  %14r perim: %3i area: %i'
                    % (sides, sum(sides), hero(*sides)) for sides in h[:10]))
    print('\nAll with area 210 subject to the previous ordering:')
    print('\n'.join('  %14r perim: %3i area: %i'
                    % (sides, sum(sides), hero(*sides)) for sides in h
                    if hero(*sides) == 210))




Fortran:  
      MODULE GREEK MATHEMATICIANS	
       CONTAINS
        INTEGER FUNCTION GCD(I,J)	
         INTEGER I,J	
         INTEGER N,M,R	
          N = MAX(I,J)	
          M = MIN(I,J)	
    1     R = MOD(N,M)		
c          write (6,*) "M,N,R",M,N,R
          IF (R.GT.0) THEN	
            N = M			
            M = R			
            IF (R .GT. 1) GO TO 1	
          END IF			
          GCD = M			
        END FUNCTION GCD	
        FUNCTION GCD3(I,J,K)	
         INTEGER I,J,K	
         INTEGER R	
          R = GCD(I,J)		
          IF (R .GT. 1) R = GCD(R,K)	
          GCD3 = R		
        END FUNCTION GCD3

        REAL*8 FUNCTION HERO(SIDE)	
Calculations could proceed with non-integer sides.
         INTEGER SIDE(3)	
         REAL*8 S		
          S = SUM(SIDE)		
          S = S/2		
          S = S*PRODUCT(S - SIDE)	
          HERO = SIGN(SQRT(ABS(S)),S)	
        END FUNCTION HERO		
      END MODULE GREEK MATHEMATICIANS	

      PROGRAM TEST		
      USE GREEK MATHEMATICIANS	
      INTEGER LIMIT,LOTS	
      PARAMETER (LIMIT = 200, LOTS = 666)	
      INTEGER I,J,K,SIDE(3)	
      EQUIVALENCE (SIDE(1),I),(SIDE(2),J),(SIDE(3),K)	
      REAL*8 A			
      TYPE ABLOB		
       INTEGER SIDE(3)		
       INTEGER PERIMETER	
       INTEGER AREA		
      END TYPE ABLOB		
      TYPE(ABLOB) STASH(LOTS)	
      INTEGER N,XNDX(LOTS)	
      INTEGER H,T		
      LOGICAL CURSE		
      INTEGER TASTE,CHOICE	
      PARAMETER (TASTE = 10, CHOICE = 210)	

Collect some triangles.
      N = 0	
      DO K = 1,LIMIT	
        DO J = 1,K		
          DO I = 1,J			
            IF (GCD3(I,J,K).GT.1) CYCLE	
            A = HERO(SIDE)		
            IF (A.LE.0) CYCLE		
            IF (A .NE. INT(A)) CYCLE	
            N = N + 1			
            IF (N.GT.LOTS) STOP "Too many
            XNDX(N) = N			
            STASH(N).SIDE = SIDE		
            STASH(N).PERIMETER = SUM(SIDE)	
            STASH(N).AREA = A			
c            WRITE (6,10) N,STASH(N)
   10       FORMAT (I4,":",3I4,I7,I8)	
          END DO
        END DO
      END DO
      WRITE (6,11) N,LIMIT	
   11 FORMAT (I0," triangles of integral area. Sides up to ",I0)

Comb sort involves coding only one test, and the comparison is to be compound...
      H = N - 1	
   20 H = MAX(1,H*10/13)	
      IF (H.EQ.9 .OR. H.EQ.10) H = 11	
      CURSE = .FALSE.		
      DO 24 I = N - H,1,-1	
        IF (STASH(XNDX(I)).AREA - STASH(XNDX(I + H)).AREA) 24,21,23 	
   21   IF (STASH(XNDX(I)).PERIMETER-STASH(XNDX(I+H)).PERIMETER)24,22,23 	
   22   IF (MAXVAL(STASH(XNDX(I)).SIDE)			
     1    - MAXVAL(STASH(XNDX(I+H)).SIDE)) 24,24,23	
   23     T=XNDX(I); XNDX(I)=XNDX(I+H); XNDX(I+H)=T	
          CURSE = .TRUE.			
   24 CONTINUE				
      IF (CURSE .OR. H.GT.1) GO TO 20	

Cast forth the results, as per the specification.
      WRITE (6,30) TASTE
   30 FORMAT ("First ",I0,", ordered by area, perimeter, longest side.",
     1 /,"Index ---Sides--- Perimeter Area")
      DO I = 1,TASTE
        WRITE (6,10) XNDX(I),STASH(XNDX(I))
      END DO

      WRITE (6,31) CHOICE
   31 FORMAT ("Those triangles with area",I7)
      DO I = 1,N	
        IF (STASH(XNDX(I)).AREA.NE.CHOICE) CYCLE
        WRITE (6,10) XNDX(I),STASH(XNDX(I))	
      END DO		
      END