Task: Heronian triangles








VB: Function heroArea(a As Integer, b As Integer, c As Integer) As Double
    s = (a + b + c) / 2
    On Error GoTo Err
    heroArea = Sqr(s * (s - a) * (s - b) * (s - c))
    Exit Function
Err:
    heroArea = -1
End Function
 
Function hero(h As Double) As Boolean
    hero = (h - Int(h) = 0) And h > 0
End Function
 
Public Sub main()
    Dim list() As Variant, items As Integer
    Dim a As Integer, b As Integer, c As Integer
    Dim hArea As Double
    Dim tries As Long
    For a = 1 To 200
        For b = 1 To a
            For c = 1 To b
                tries = tries + 1
                If gcd(gcd(a, b), c) = 1 Then
                    hArea = heroArea(a, b, c)
                    If hero(hArea) Then
                        ReDim Preserve list(items)
                        list(items) = Array(CStr(hArea), CStr(a + b + c), CStr(a), CStr(b), CStr(c))
                        items = items + 1
                    End If
                End If
            Next c
        Next b
    Next a
    list = sort(list)
    Debug.Print "Primitive Heronian triangles with sides up to 200:"; UBound(list) + 1; "(of"; tries; "tested)"
    Debug.Print
    Debug.Print "First 10 ordered by area/perimeter/sides:"
    Debug.Print "area       perimeter        sides"
    For i = 0 To 9
        Debug.Print Format(list(i)(0), "@@@"), Format(list(i)(1), "@@@"),
        Debug.Print list(i)(2); "x"; list(i)(3); "x"; list(i)(4)
    Next i
    Debug.Print
    Debug.Print "area = 210:"
    Debug.Print "area       perimeter        sides"
    For i = 0 To UBound(list)
        If Val(list(i)(0)) = 210 Then
            Debug.Print Format(list(i)(0), "@@@"), Format(list(i)(1), "@@@"),
            Debug.Print list(i)(2); "x"; list(i)(3); "x"; list(i)(4)
        End If
    Next i
End Sub



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