I'm working on modernizing Rosetta Code's infrastructure. Starting with communications. Please accept this time-limited open invite to RC's Slack.. --Michael Mol (talk) 20:59, 30 May 2020 (UTC)

# Law of cosines - triples

Law of cosines - triples
You are encouraged to solve this task according to the task description, using any language you may know.

The Law of cosines states that for an angle γ, (gamma) of any triangle, if the sides adjacent to the angle are A and B and the side opposite is C; then the lengths of the sides are related by this formula:

```           `A2 + B2 - 2ABcos(γ) = C2`
```
Specific angles

For an angle of of   90º   this becomes the more familiar "Pythagoras equation":

```           `A2 + B2  =  C2`
```

For an angle of   60º   this becomes the less familiar equation:

```           `A2 + B2 - AB  =  C2`
```

And finally for an angle of   120º   this becomes the equation:

```           `A2 + B2 + AB  =  C2`
```

•   Find all integer solutions (in order) to the three specific cases, distinguishing between each angle being considered.
•   Restrain all sides to the integers   1..13   inclusive.
•   Show how many results there are for each of the three angles mentioned above.

Note: Triangles with the same length sides but different order are to be treated as the same.

Optional Extra credit
• How many 60° integer triples are there for sides in the range 1..10_000 where the sides are not all of the same length.

## 11l

Translation of: Python
`-V n = 13 F method1(n)   V squares = (0..n).map(x -> x ^ 2)   V sqrset = Set(squares)   Set[(Int, Int, Int)] tri90, tri60, tri120    L(a) 1..n      V a2 = squares[a]      L(b) 1..a         V b2 = squares[b]         V c2 = a2 + b2         I c2 C sqrset            tri90.add(tuple_sorted((a, b, Int(sqrt(c2)))))         V ab = a * b         c2 -= ab         I c2 C sqrset            tri60.add(tuple_sorted((a, b, Int(sqrt(c2)))))         c2 += 2 * ab         I c2 C sqrset            tri120.add(tuple_sorted((a, b, Int(sqrt(c2)))))   R [sorted(Array(tri90)),      sorted(Array(tri60)),      sorted(Array(tri120))] print(‘Integer triangular triples for sides 1..#.:’.format(n))L(angle, triples) zip([90, 60, 120], method1(n))   print("  #3° has #. solutions:\n    #.".format(angle, triples.len, triples))V t60 = method1(10'000)V notsame = sum(t60.filter((a, b, c) -> a != b | b != c).map((a, b, c) -> 1))print(‘Extra credit: ’notsame)`
Output:
```Integer triangular triples for sides 1..13:
90° has 3 solutions:
[(3, 4, 5), (5, 12, 13), (6, 8, 10)]
60° has 15 solutions:
[(1, 1, 1), (2, 2, 2), (3, 3, 3), (3, 7, 8), (4, 4, 4), (5, 5, 5), (5, 7, 8), (6, 6, 6), (7, 7, 7), (8, 8, 8), (9, 9, 9), (10, 10, 10), (11, 11, 11), (12, 12, 12), (13, 13, 13)]
120° has 2 solutions:
[(3, 5, 7), (7, 8, 13)]
Extra credit: 18394
```

## Action!

`PROC Test(INT max,angle,coeff)  BYTE count,a,b,c   PrintF("gamma=%B degrees:%E",angle)  count=0  FOR a=1 TO max  DO    FOR b=1 TO a    DO      FOR c=1 TO max      DO        IF a*a+b*b-coeff*a*b=c*c THEN          PrintF("(%B,%B,%B) ",a,b,c)          count==+1        FI      OD    OD  OD  PrintF("%Enumber of triangles is %B%E%E",count)RETURN PROC Main()  Test(13,90,0)  Test(13,60,1)  Test(13,120,-1)RETURN`
Output:
```gamma=90 degrees:
(4,3,5) (8,6,10) (12,5,13)
number of triangles is 3

gamma=60 degrees:
(1,1,1) (2,2,2) (3,3,3) (4,4,4) (5,5,5) (6,6,6) (7,7,7) (8,3,7) (8,5,7) (8,8,8) (9,9,9) (10,10,10) (11,11,11) (12,12,12) (13,13,13)
number of triangles is 15

gamma=120 degrees:
(5,3,7) (8,7,13)
number of triangles is 2
```

`with Ada.Text_IO;with Ada.Containers.Ordered_Maps; procedure Law_Of_Cosines is    type Angle_Kind is (Angle_60, Angle_90, Angle_120);    function Is_Triangle (A, B, C : in Positive;                         Angle   : in Angle_Kind) return Boolean   is      A2 : constant Positive := A**2;      B2 : constant Positive := B**2;      C2 : constant Positive := C**2;      AB : constant Positive := A * B;   begin      case Angle is         when Angle_60  =>  return A2 + B2 - AB = C2;         when Angle_90  =>  return A2 + B2 = C2;         when Angle_120 =>  return A2 + B2 + AB = C2;      end case;   end Is_Triangle;    procedure Count_Triangles is      use Ada.Text_IO;      Count : Natural;   begin      for Angle in Angle_Kind loop         Count := 0;         Put_Line (Angle'Image & " triangles");         for A in 1 ..13 loop            for B in 1 .. A loop               for C in 1 .. 13 loop                  if Is_Triangle (A, B, C, Angle) then                     Put_Line (A'Image & B'Image & C'Image);                     Count := Count + 1;                  end if;               end loop;            end loop;         end loop;         Put_Line ("There are " & Count'Image & " " & Angle'Image &" triangles");      end loop;   end Count_Triangles;    procedure Extra_Credit (Limit : in Natural) is      use Ada.Text_IO;       package Square_Maps is new Ada.Containers.Ordered_Maps (Natural, Boolean);      Squares : Square_Maps.Map;       Count : Natural :=  0;   begin      for C in 1 .. Limit loop         Squares.Insert (C**2, True);      end loop;       for A in 1 .. Limit loop         for B in 1 .. A loop            if Squares.Contains (A**2 + B**2 - A * B) then               Count := Count + 1;            end if;         end loop;      end loop;      Put_Line ("There are " & Natural'(Count - Limit)'Image &                  " " & Angle_60'Image &" triangles between 1 and " & Limit'Image & ".");   end Extra_Credit; begin   Count_Triangles;   Extra_Credit (Limit => 10_000);end Law_Of_Cosines;`
Output:
```ANGLE_60 triangles
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 3 7
8 5 7
8 8 8
9 9 9
10 10 10
11 11 11
12 12 12
13 13 13
There are  15 ANGLE_60 triangles
ANGLE_90 triangles
4 3 5
8 6 10
12 5 13
There are  3 ANGLE_90 triangles
ANGLE_120 triangles
5 3 7
8 7 13
There are  2 ANGLE_120 triangles
There are  18394 ANGLE_60 triangles between 1 and  10000.```

## ALGOL 68

`BEGIN    # find all integer sided 90, 60 and 120 degree triangles by finding integer solutions for #    #    a^2 + b^2 = c^2, a^2 + b^2 - ab = c^2, a^2 + b^2 + ab = c^2 where a, b, c in 1 .. 13 #    INT max side   = 13;                  # max triangle side to consider                     #    INT max square = max side * max side; # max triangle side squared to consider             #    [ 1 : max square ]INT root;           # table of square roots                             #    FOR s TO UPB root DO root[ s     ] := 0 OD;    FOR s TO max side DO root[ s * s ] := s OD;    INT tcount := 0;    [ 1 : max square ]INT ta, tb, tc, tangle;    # prints solutions for the specified angle                                                #    PROC print triangles = ( INT angle )VOID:    BEGIN        INT scount := 0;        FOR t TO tcount DO IF tangle[ t ] = angle THEN scount +:= 1 FI OD;        print( ( whole( scount, -4 ), " ", whole( angle, -3 ), " degree triangles:", newline ) );        FOR t TO tcount DO            IF tangle[ t ] = angle THEN                print( ( "    ", whole( ta[ t ], -3 ), whole( tb[ t ], -3 ), whole( tc[ t ], -3 ), newline ) )            FI        OD    END # print triangles # ;    # stores the triangle with sides a, b, root[ c2 ] and the specified angle,                #    # if it is a solution                                                                     #    PROC try triangle = ( INT a, b, c2, angle )VOID:        IF  c2 <= max square THEN            # the third side is small enough                                                  #            INT c = root[ c2 ];            IF  c /= 0 THEN                # the third side is the square of an integer                                  #                tcount +:= 1;                ta[     tcount ] := a; tb[ tcount ] := b; tc[ tcount ] := root[ c2 ];                tangle[ tcount ] := angle            FI        FI # try triangle # ;    # find all triangles                                                                      #    FOR a TO max side DO        FOR b FROM a TO max side DO            try triangle( a, b, ( a * a ) + ( b * b ) - ( a * b ),  60 );            try triangle( a, b, ( a * a ) + ( b * b ),              90 );            try triangle( a, b, ( a * a ) + ( b * b ) + ( a * b ), 120 )        OD    OD;    # print the solutions                                                                     #        print triangles(  60 );    print triangles(  90 );    print triangles( 120 )END`
Output:
```  15  60 degree triangles:
1  1  1
2  2  2
3  3  3
3  8  7
4  4  4
5  5  5
5  8  7
6  6  6
7  7  7
8  8  8
9  9  9
10 10 10
11 11 11
12 12 12
13 13 13
3  90 degree triangles:
3  4  5
5 12 13
6  8 10
2 120 degree triangles:
3  5  7
7  8 13
```

## AWK

` # syntax: GAWK -f LAW_OF_COSINES_-_TRIPLES.AWK# converted from CBEGIN {    description = "90 degrees, a*a + b*b = c*c"    description = "60 degrees, a*a + b*b - a*b = c*c"    description = "120 degrees, a*a + b*b + a*b = c*c"    split("0,1,-1",coeff,",")    main(13,1,0)    main(1000,0,1) # 10,000 takes too long    exit(0)}function main(max_side_length,show_sides,no_dups,  a,b,c,count,k) {    printf("\nmaximum side length: %d\n",max_side_length)    for (k=1; k<=3; k++) {      count = 0      for (a=1; a<=max_side_length; a++) {        for (b=1; b<=a; b++) {          for (c=1; c<=max_side_length; c++) {            if (a*a + b*b - coeff[k] * a*b == c*c) {              if (no_dups && (a == b || b == c)) {                continue              }              count++              if (show_sides) {                printf("  %d %d %d\n",a,b,c)              }            }          }        }      }      printf("%d triangles, %s\n",count,description[k])    }} `
Output:
```maximum side length: 13
4 3 5
8 6 10
12 5 13
3 triangles, 90 degrees, a*a + b*b = c*c
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 3 7
8 5 7
8 8 8
9 9 9
10 10 10
11 11 11
12 12 12
13 13 13
15 triangles, 60 degrees, a*a + b*b - a*b = c*c
5 3 7
8 7 13
2 triangles, 120 degrees, a*a + b*b + a*b = c*c

maximum side length: 1000
881 triangles, 90 degrees, a*a + b*b = c*c
1260 triangles, 60 degrees, a*a + b*b - a*b = c*c
719 triangles, 120 degrees, a*a + b*b + a*b = c*c
```

## C

### A brute force algorithm, O(N^3)

`/* * RossetaCode: Law of cosines - triples * * An quick and dirty brute force solutions with O(N^3) cost. * Anyway it is possible set MAX_SIDE_LENGTH equal to 10000  * and use fast computer to obtain the "extra credit" badge. * * Obviously, there are better algorithms. */ #include <stdio.h>#include <math.h> #define MAX_SIDE_LENGTH 13//#define DISPLAY_TRIANGLES 1 int main(void){    static char description = {        "gamma =  90 degrees,  a*a + b*b       == c*c",        "gamma =  60 degrees,  a*a + b*b - a*b == c*c",        "gamma = 120 degrees,  a*a + b*b + a*b == c*c"    };    static int coeff = { 0, 1, -1 };     for (int k = 0; k < 3; k++)    {        int counter = 0;        for (int a = 1; a <= MAX_SIDE_LENGTH; a++)            for (int b = 1; b <= a; b++)                for (int c = 1; c <= MAX_SIDE_LENGTH; c++)                    if (a * a + b * b - coeff[k] * a * b == c * c)                    {                        counter++;#ifdef DISPLAY_TRIANGLES                        printf("  %d  %d  %d\n", a, b, c);#endif                    }        printf("%s,  number of triangles = %d\n", description[k], counter);    }     return 0;} `
Output:
```gamma =  90 degrees,  a*a + b*b       == c*c,  number of triangles = 3
gamma =  60 degrees,  a*a + b*b - a*b == c*c,  number of triangles = 15
gamma = 120 degrees,  a*a + b*b + a*b == c*c,  number of triangles = 2
```

### An algorithm with O(N^2) cost

`/* * RossetaCode: Law of cosines - triples * * A solutions with O(N^2) cost. */ #include <stdio.h>#include <math.h> #define MAX_SIDE_LENGTH 10000//#define DISPLAY_TRIANGLES  int main(void){    static char description = {        "gamma =  90 degrees,  a*a + b*b       == c*c",        "gamma =  60 degrees,  a*a + b*b - a*b == c*c",        "gamma = 120 degrees,  a*a + b*b + a*b == c*c"    };    static int coeff = { 0, 1, -1 };     printf("MAX SIDE LENGTH = %d\n\n", MAX_SIDE_LENGTH);     for (int k = 0; k < 3; k++)    {        int counter = 0;        for (int a = 1; a <= MAX_SIDE_LENGTH; a++)            for (int b = 1; b <= a; b++)            {                int cc = a * a + b * b - coeff[k] * a * b;                int c = (int)(sqrt(cc) + 0.5);                if (c <= MAX_SIDE_LENGTH && c * c == cc)                {#ifdef DISPLAY_TRIANGLES                    printf("%d %d %d\n", a, b, c);#endif                    counter++;                }            }        printf("%s,  number of triangles = %d\n", description[k], counter);    }     return 0;} `
Output:
```MAX SIDE LENGTH = 10000

gamma =  90 degrees,  a*a + b*b       == c*c,  number of triangles = 12471
gamma =  60 degrees,  a*a + b*b - a*b == c*c,  number of triangles = 28394
gamma = 120 degrees,  a*a + b*b + a*b == c*c,  number of triangles = 10374
```

## C++

`#include <cmath>#include <iostream>#include <tuple>#include <vector> using triple = std::tuple<int, int, int>; void print_triple(std::ostream& out, const triple& t) {    out << '(' << std::get<0>(t) << ',' << std::get<1>(t) << ',' << std::get<2>(t) << ')';} void print_vector(std::ostream& out, const std::vector<triple>& vec) {    if (vec.empty())        return;    auto i = vec.begin();    print_triple(out, *i++);    for (; i != vec.end(); ++i) {        out << ' ';        print_triple(out, *i);    }    out << "\n\n";} int isqrt(int n) {    return static_cast<int>(std::sqrt(n));} int main() {    const int min = 1, max = 13;    std::vector<triple> solutions90, solutions60, solutions120;     for (int a = min; a <= max; ++a) {        int a2 = a * a;        for (int b = a; b <= max; ++b) {            int b2 = b * b, ab = a * b;            int c2 = a2 + b2;            int c = isqrt(c2);            if (c <= max && c * c == c2)                solutions90.emplace_back(a, b, c);            else {                c2 = a2 + b2 - ab;                c = isqrt(c2);                if (c <= max && c * c == c2)                    solutions60.emplace_back(a, b, c);                else {                    c2 = a2 + b2 + ab;                    c = isqrt(c2);                    if (c <= max && c * c == c2)                        solutions120.emplace_back(a, b, c);                }            }        }    }     std::cout << "There are " << solutions60.size() << " solutions for gamma = 60 degrees:\n";    print_vector(std::cout, solutions60);     std::cout << "There are " << solutions90.size() << " solutions for gamma = 90 degrees:\n";    print_vector(std::cout, solutions90);     std::cout << "There are " << solutions120.size() << " solutions for gamma = 120 degrees:\n";    print_vector(std::cout, solutions120);     const int max2 = 10000;    int count = 0;    for (int a = min; a <= max2; ++a) {        for (int b = a + 1; b <= max2; ++b) {            int c2 = a * a + b * b - a * b;            int c = isqrt(c2);            if (c <= max2 && c * c == c2)                ++count;        }    }    std::cout << "There are " << count << " solutions for gamma = 60 degrees in the range "        << min << " to " << max2 << " where the sides are not all of the same length.\n";    return 0;}`
Output:
```There are 15 solutions for gamma = 60 degrees:
(1,1,1) (2,2,2) (3,3,3) (3,8,7) (4,4,4) (5,5,5) (5,8,7) (6,6,6) (7,7,7) (8,8,8) (9,9,9) (10,10,10) (11,11,11) (12,12,12) (13,13,13)

There are 3 solutions for gamma = 90 degrees:
(3,4,5) (5,12,13) (6,8,10)

There are 2 solutions for gamma = 120 degrees:
(3,5,7) (7,8,13)

There are 18394 solutions for gamma = 60 degrees in the range 1 to 10000 where the sides are not all of the same length.
```

## C#

`using System;using System.Collections.Generic;using static System.Linq.Enumerable; public static class LawOfCosinesTriples{    public static void Main2() {        PrintTriples(60, 13);        PrintTriples(90, 13);        PrintTriples(120, 13);        PrintTriples(60, 10_000, true, false);    }     private static void PrintTriples(int degrees, int maxSideLength, bool notAllTheSameLength = false, bool print = true) {        string s = \$"{degrees} degree triangles in range 1..{maxSideLength}";        if (notAllTheSameLength) s += " where not all sides are the same";        Console.WriteLine(s);        int count = 0;        var triples = FindTriples(degrees, maxSideLength);        if (notAllTheSameLength) triples = triples.Where(NotAllTheSameLength);        foreach (var triple in triples) {            count++;            if (print) Console.WriteLine(triple);        }        Console.WriteLine(\$"{count} solutions");    }     private static IEnumerable<(int a, int b, int c)> FindTriples(int degrees, int maxSideLength) {        double radians = degrees * Math.PI / 180;        int coefficient = (int)Math.Round(Math.Cos(radians) * -2, MidpointRounding.AwayFromZero);        int maxSideLengthSquared = maxSideLength * maxSideLength;        return            from a in Range(1, maxSideLength)            from b in Range(1, a)            let cc = a * a + b * b + a * b * coefficient            where cc <= maxSideLengthSquared            let c = (int)Math.Sqrt(cc)            where c * c == cc            select (a, b, c);    }     private static bool NotAllTheSameLength((int a, int b, int c) triple) => triple.a != triple.b || triple.a != triple.c;}`
Output:
```60 degree triangles in range 1..13
(1, 1, 1)
(2, 2, 2)
(3, 3, 3)
(4, 4, 4)
(5, 5, 5)
(6, 6, 6)
(7, 7, 7)
(8, 3, 7)
(8, 5, 7)
(8, 8, 8)
(9, 9, 9)
(10, 10, 10)
(11, 11, 11)
(12, 12, 12)
(13, 13, 13)
15 solutions
90 degree triangles in range 1..13
(4, 3, 5)
(8, 6, 10)
(12, 5, 13)
3 solutions
120 degree triangles in range 1..13
(5, 3, 7)
(8, 7, 13)
2 solutions
60 degree triangles in range 1..10000 where not all sides are the same
18394 solutions```

## Factor

`USING: backtrack formatting kernel locals math math.rangessequences sets sorting ;IN: rosetta-code.law-of-cosines :: triples ( quot -- seq )    [        V{ } clone :> seen                13 [1,b] dup dup [ amb-lazy ] [email protected] :> ( a b c )        a sq b sq + a b quot call( x x x -- x ) c sq =        { b a c } seen member? not and        must-be-true { a b c } dup seen push    ] bag-of ; : show-solutions ( quot angle -- )    [ triples { } like dup length ] dip rot    "%d solutions for %d degrees:\n%u\n\n" printf ; [ * + ] 120[ 2drop 0 - ] 90[ * - ] 60 [ show-solutions ] [email protected]`
Output:
```2 solutions for 120 degrees:
{ { 3 5 7 } { 7 8 13 } }

3 solutions for 90 degrees:
{ { 3 4 5 } { 5 12 13 } { 6 8 10 } }

15 solutions for 60 degrees:
{
{ 1 1 1 }
{ 2 2 2 }
{ 3 3 3 }
{ 3 8 7 }
{ 4 4 4 }
{ 5 5 5 }
{ 5 8 7 }
{ 6 6 6 }
{ 7 7 7 }
{ 8 8 8 }
{ 9 9 9 }
{ 10 10 10 }
{ 11 11 11 }
{ 12 12 12 }
{ 13 13 13 }
}
```

## Fortran

`MODULE LAW_OF_COSINES    IMPLICIT NONE     CONTAINS     ! Calculate the third side of a triangle using the cosine rule    REAL FUNCTION COSINE_SIDE(SIDE_A, SIDE_B, ANGLE)        INTEGER, INTENT(IN) :: SIDE_A, SIDE_B        REAL(8), INTENT(IN) :: ANGLE         COSINE_SIDE = SIDE_A**2 + SIDE_B**2 - 2*SIDE_A*SIDE_B*COS(ANGLE)        COSINE_SIDE = COSINE_SIDE**0.5    END FUNCTION COSINE_SIDE     ! Convert an angle in degrees to radians    REAL(8) FUNCTION DEG2RAD(ANGLE)        REAL(8), INTENT(IN) :: ANGLE        REAL(8), PARAMETER :: PI = 4.0D0*DATAN(1.D0)         DEG2RAD = ANGLE*(PI/180)    END FUNCTION DEG2RAD     ! Sort an array of integers    FUNCTION INT_SORTED(ARRAY) RESULT(SORTED)        INTEGER, DIMENSION(:), INTENT(IN) :: ARRAY        INTEGER, DIMENSION(SIZE(ARRAY)) :: SORTED, TEMP        INTEGER :: MAX_VAL, DIVIDE         SORTED = ARRAY        TEMP = ARRAY        DIVIDE = SIZE(ARRAY)         DO WHILE (DIVIDE .NE. 1)            MAX_VAL = MAXVAL(SORTED(1:DIVIDE))            TEMP(DIVIDE) = MAX_VAL            TEMP(MAXLOC(SORTED(1:DIVIDE))) = SORTED(DIVIDE)            SORTED = TEMP            DIVIDE = DIVIDE - 1        END DO    END FUNCTION INT_SORTED     ! Append an integer to the end of an array of integers    SUBROUTINE APPEND(ARRAY, ELEMENT)        INTEGER, DIMENSION(:), ALLOCATABLE, INTENT(INOUT) :: ARRAY        INTEGER, DIMENSION(:), ALLOCATABLE :: TEMP        INTEGER :: ELEMENT        INTEGER :: I, ISIZE         IF (ALLOCATED(ARRAY)) THEN            ISIZE = SIZE(ARRAY)            ALLOCATE(TEMP(ISIZE+1))             DO I=1, ISIZE                TEMP(I) = ARRAY(I)            END DO             TEMP(ISIZE+1) = ELEMENT             DEALLOCATE(ARRAY)             CALL MOVE_ALLOC(TEMP, ARRAY)        ELSE            ALLOCATE(ARRAY(1))            ARRAY(1) = ELEMENT        END IF     END SUBROUTINE APPEND     ! Check if an array of integers contains a subset    LOGICAL FUNCTION CONTAINS_ARR(ARRAY, ELEMENT)        INTEGER, DIMENSION(:), INTENT(IN) :: ARRAY        INTEGER, DIMENSION(:) :: ELEMENT        INTEGER, DIMENSION(SIZE(ELEMENT)) :: TEMP, SORTED_ELEMENT        INTEGER :: I, COUNTER, J         COUNTER = 0         ELEMENT = INT_SORTED(ELEMENT)         DO I=1,SIZE(ARRAY),SIZE(ELEMENT)            TEMP = ARRAY(I:I+SIZE(ELEMENT)-1)            DO J=1,SIZE(ELEMENT)                IF (ELEMENT(J) .EQ. TEMP(J)) THEN                    COUNTER = COUNTER + 1                END IF            END DO             IF (COUNTER .EQ. SIZE(ELEMENT)) THEN                CONTAINS_ARR = .TRUE.                RETURN            END IF        END DO         CONTAINS_ARR = .FALSE.    END FUNCTION CONTAINS_ARR     ! Count and print cosine triples for the given angle in degrees    INTEGER FUNCTION COSINE_TRIPLES(MIN_NUM, MAX_NUM, ANGLE, PRINT_RESULTS) RESULT(COUNTER)        INTEGER, INTENT(IN) :: MIN_NUM, MAX_NUM        REAL(8), INTENT(IN) :: ANGLE        LOGICAL, INTENT(IN) :: PRINT_RESULTS        INTEGER, DIMENSION(:), ALLOCATABLE :: CANDIDATES        INTEGER, DIMENSION(3) :: CANDIDATE        INTEGER :: A, B        REAL :: C         COUNTER = 0         DO A = MIN_NUM, MAX_NUM            DO B = MIN_NUM, MAX_NUM                C = COSINE_SIDE(A, B, DEG2RAD(ANGLE))                IF (C .GT. MAX_NUM .OR. MOD(C, 1.) .NE. 0) THEN                    CYCLE                END IF                 CANDIDATE(1) = A                CANDIDATE(2) = B                CANDIDATE(3) = C                IF (.NOT. CONTAINS_ARR(CANDIDATES, CANDIDATE)) THEN                    COUNTER = COUNTER + 1                    CALL APPEND(CANDIDATES, CANDIDATE(1))                    CALL APPEND(CANDIDATES, CANDIDATE(2))                    CALL APPEND(CANDIDATES, CANDIDATE(3))                     IF (PRINT_RESULTS) THEN                        WRITE(*,'(A,I0,A,I0,A,I0,A)') " (", CANDIDATE(1), ", ", CANDIDATE(2), ", ", CANDIDATE(3), ")"                    END IF                END IF            END DO        END DO    END FUNCTION COSINE_TRIPLES END MODULE LAW_OF_COSINES ! Program prints the cosine triples for the angles 90, 60 and 120 degrees! by using the cosine rule to find the third side of each candidate and! checking that this is an integer. Candidates are appended to an array! after the sides have been sorted into ascending order! the array is repeatedly checked to ensure there are no duplicates.PROGRAM LOC    USE LAW_OF_COSINES     REAL(8), DIMENSION(3) :: TEST_ANGLES = (/90., 60., 120./)    INTEGER :: I, COUNTER     DO I = 1,SIZE(TEST_ANGLES)        WRITE(*, '(F0.0, A)') TEST_ANGLES(I), " degree triangles: "         COUNTER = COSINE_TRIPLES(1, 13, TEST_ANGLES(I), .TRUE.)        WRITE(*,'(A, I0)') "TOTAL: ", COUNTER        WRITE(*,*) NEW_LINE('A')    END DO END PROGRAM LOC`
```90. degree triangles:
(3, 4, 5)
(5, 12, 13)
(6, 8, 10)
TOTAL: 3

60. degree triangles:
(1, 1, 1)
(2, 2, 2)
(3, 3, 3)
(3, 7, 8)
(4, 4, 4)
(5, 5, 5)
(6, 6, 6)
(7, 7, 7)
(3, 7, 8)
(8, 8, 8)
(9, 9, 9)
(10, 10, 10)
(11, 11, 11)
(12, 12, 12)
(13, 13, 13)
TOTAL: 15

120. degree triangles:
(3, 5, 7)
(7, 8, 13)
TOTAL: 2
```

## FreeBASIC

`' version 03-03-2019' compile with: fbc -s console #Define max 13 #Define Format(_x)  Right("    " + Str(_x), 4) Dim As UInteger a, b, c, a2, b2, c2, c60 , c90, c120Dim As String s60, s90, s120 For a = 1 To max    a2 = a * a    For b = a To max        b2 = b * b        ' 60 degrees        c2 = a2 + b * b - a * b        c = Sqr(c2)        If c * c = c2 AndAlso c <= max Then            s60 += Format(a) + Format(b) + Format(c) + Chr(10, 13)            c60 += 1        End If        ' 90 degrees        c2 = a2 + b * b        c = Sqr(c2)        If c * c = c2 AndAlso c <= max Then            s90 += Format(a) + Format(b) + Format(c) + Chr(10, 13)            c90 += 1        End If        ' 120 degrees        c2 = a2 + b * b + a * b        c = Sqr(c2)        If c * c = c2 AndAlso c <= max Then            s120 += Format(a) + Format(b) + Format(c) + Chr(10, 13)            c120 += 1        End If    NextNext  Print Using "###: 60 degree triangles"; c60Print s60Print Print Using "###: 90 degree triangles"; c90Print s90Print Print Using "###: 120 degree triangles"; c120Print s120Print #Undef max#Define max 10000 c60 = 0For a = 1 To max    a2 = a * a    For b = a +1 To max        c2 = a2 + b * (b - a)        c = Sqr(c2)        If c * c = c2 AndAlso c <= max Then            c60 += 1        End If    NextNext Print "For 60 degree triangles in the range [1, 10000]"Print "There are "; c60; " triangles that have different length for a, b and c" ' empty keyboard bufferWhile InKey <> "" : WendPrint : Print "hit any key to end program"SleepEnd`
Output:
``` 15: 60 degree triangles
1   1   1
2   2   2
3   3   3
3   8   7
4   4   4
5   5   5
5   8   7
6   6   6
7   7   7
8   8   8
9   9   9
10  10  10
11  11  11
12  12  12
13  13  13

3: 90 degree triangles
3   4   5
5  12  13
6   8  10

2: 120 degree triangles
3   5   7
7   8  13

For 60 degree triangles in the range [1, 10000]
There are 18394 triangles that have different length for a, b and c```

## Go

`package main import "fmt" type triple struct{ a, b, c int } var squares13 = make(map[int]int, 13)var squares10000 = make(map[int]int, 10000) func init() {    for i := 1; i <= 13; i++ {        squares13[i*i] = i    }    for i := 1; i <= 10000; i++ {        squares10000[i*i] = i    }} func solve(angle, maxLen int, allowSame bool) []triple {    var solutions []triple    for a := 1; a <= maxLen; a++ {        for b := a; b <= maxLen; b++ {            lhs := a*a + b*b            if angle != 90 {                switch angle {                case 60:                    lhs -= a * b                case 120:                    lhs += a * b                default:                    panic("Angle must be 60, 90 or 120 degrees")                }            }            switch maxLen {            case 13:                if c, ok := squares13[lhs]; ok {                    if !allowSame && a == b && b == c {                        continue                    }                    solutions = append(solutions, triple{a, b, c})                }            case 10000:                if c, ok := squares10000[lhs]; ok {                    if !allowSame && a == b && b == c {                        continue                    }                    solutions = append(solutions, triple{a, b, c})                }            default:                panic("Maximum length must be either 13 or 10000")            }        }    }    return solutions} func main() {    fmt.Print("For sides in the range [1, 13] ")    fmt.Println("where they can all be of the same length:-\n")    angles := []int{90, 60, 120}    var solutions []triple    for _, angle := range angles {        solutions = solve(angle, 13, true)        fmt.Printf("  For an angle of %d degrees", angle)        fmt.Println(" there are", len(solutions), "solutions, namely:")        fmt.Printf("  %v\n", solutions)        fmt.Println()    }    fmt.Print("For sides in the range [1, 10000] ")    fmt.Println("where they cannot ALL be of the same length:-\n")    solutions = solve(60, 10000, false)    fmt.Print("  For an angle of 60 degrees")    fmt.Println(" there are", len(solutions), "solutions.")}`
Output:
```For sides in the range [1, 13] where they can all be of the same length:-

For an angle of 90 degrees there are 3 solutions, namely:
[{3 4 5} {5 12 13} {6 8 10}]

For an angle of 60 degrees there are 15 solutions, namely:
[{1 1 1} {2 2 2} {3 3 3} {3 8 7} {4 4 4} {5 5 5} {5 8 7} {6 6 6} {7 7 7} {8 8 8} {9 9 9} {10 10 10} {11 11 11} {12 12 12} {13 13 13}]

For an angle of 120 degrees there are 2 solutions, namely:
[{3 5 7} {7 8 13}]

For sides in the range [1, 10000] where they cannot ALL be of the same length:-

For an angle of 60 degrees there are 18394 solutions.
```

`import qualified Data.Map.Strict as Mapimport qualified Data.Set as Setimport Data.Monoid ((<>)) triangles  :: (Map.Map Int Int -> Int -> Int -> Int -> Int -> Maybe Int)  -> Int  -> [(Int, Int, Int)]triangles f n =  let mapRoots = Map.fromList \$ ((,) =<< (^ 2)) <\$> [1 .. n]  in Set.elems \$     foldr       (\(suma2b2, a, b) triSet ->           (case f mapRoots suma2b2 (a * b) a b of              Just c -> Set.insert (a, b, c) triSet              _ -> triSet))       (Set.fromList [])       ([1 .. n] >>=        (\a -> (flip (,,) a =<< (a * a +) . (>>= id) (*)) <\$> [1 .. a]))  -- TESTS ------------------------------------------------------------------------ f90, f60, f60ne, f120 :: Map.Map Int Int -> Int -> Int -> Int -> Int -> Maybe Intf90 dct x2 ab a b = Map.lookup x2 dct f60 dct x2 ab a b = Map.lookup (x2 - ab) dct f120 dct x2 ab a b = Map.lookup (x2 + ab) dct f60ne dct x2 ab a b  | a == b = Nothing  | otherwise = Map.lookup (x2 - ab) dct main :: IO ()main = do  putStrLn    (unlines \$     "Triangles of maximum side 13\n" :     zipWith       (\f n ->           let solns = triangles f 13           in show (length solns) <> " solutions for " <> show n <>              " degrees:\n" <>              unlines (show <\$> solns))       [f120, f90, f60]       [120, 90, 60])  putStrLn "60 degrees - uneven triangles of maximum side 10000. Total:"  print \$ length \$ triangles f60ne 10000`
Output:
```Triangles of maximum side 13

2 solutions for 120 degrees:
(5,3,7)
(8,7,13)

3 solutions for 90 degrees:
(4,3,5)
(8,6,10)
(12,5,13)

15 solutions for 60 degrees:
(1,1,1)
(2,2,2)
(3,3,3)
(4,4,4)
(5,5,5)
(6,6,6)
(7,7,7)
(8,3,7)
(8,5,7)
(8,8,8)
(9,9,9)
(10,10,10)
(11,11,11)
(12,12,12)
(13,13,13)

60 degrees - uneven triangles of maximum side 10000. Total:
18394```

## J

Solution:

`load 'trig stats'RHS=: *:                               NB. right-hand-side of Cosine LawLHS=: +/@:*:@] - [email protected]@[ * 2 * */@]  NB. Left-hand-side of Cosine Law solve=: 4 :0  adjsides=. >: 2 combrep y  oppside=. >: i. y  idx=. (RHS oppside) i. x LHS"1 adjsides  adjsides ((#~ idx ~: #) ,. ({~ idx -. #)@]) oppside)`

Example:

`   60 90 120 solve&.> 13+--------+-------+------+| 1  1  1|3  4  5|3 5  7|| 2  2  2|5 12 13|7 8 13|| 3  3  3|6  8 10|      || 3  8  7|       |      || 4  4  4|       |      || 5  5  5|       |      || 5  8  7|       |      || 6  6  6|       |      || 7  7  7|       |      || 8  8  8|       |      || 9  9  9|       |      ||10 10 10|       |      ||11 11 11|       |      ||12 12 12|       |      ||13 13 13|       |      |+--------+-------+------+   60 #@(solve -. _3 ]\ 3 # >:@[email protected]]) 10000  NB. optional extra credit18394`

## Java

` public class LawOfCosines {     public static void main(String[] args) {        generateTriples(13);        generateTriples60(10000);    }     private static void generateTriples(int max) {        for ( int coeff : new int[] {0, -1, 1} ) {            int count = 0;            System.out.printf("Max side length %d, formula:  a*a + b*b %s= c*c%n", max, coeff == 0 ? "" : (coeff<0 ? "-"  : "+") + " a*b ");            for ( int a = 1 ; a <= max ; a++ ) {                for ( int b = 1 ; b <= a ; b++ ) {                    int val = a*a + b*b + coeff*a*b;                    int c = (int) (Math.sqrt(val) + .5d);                    if ( c > max ) {                        break;                    }                    if ( c*c == val ) {                        System.out.printf("  (%d, %d, %d)%n", a, b ,c);                        count++;                    }                }            }            System.out.printf("%d triangles%n", count);        }            }     private static void generateTriples60(int max) {        int count = 0;        System.out.printf("%nExtra Credit.%nMax side length %d, sides different length, formula:  a*a + b*b - a*b = c*c%n", max);        for ( int a = 1 ; a <= max ; a++ ) {            for ( int b = 1 ; b < a ; b++ ) {                int val = a*a + b*b - a*b;                int c = (int) (Math.sqrt(val) + .5d);                if ( c*c == val ) {                    count++;                }            }        }        System.out.printf("%d triangles%n", count);    } } `
Output:
```Max side length 13, formula:  a*a + b*b = c*c
(4, 3, 5)
(8, 6, 10)
(12, 5, 13)
3 triangles
Max side length 13, formula:  a*a + b*b - a*b = c*c
(1, 1, 1)
(2, 2, 2)
(3, 3, 3)
(4, 4, 4)
(5, 5, 5)
(6, 6, 6)
(7, 7, 7)
(8, 3, 7)
(8, 5, 7)
(8, 8, 8)
(9, 9, 9)
(10, 10, 10)
(11, 11, 11)
(12, 12, 12)
(13, 13, 13)
15 triangles
Max side length 13, formula:  a*a + b*b + a*b = c*c
(5, 3, 7)
(8, 7, 13)
2 triangles

Extra Credit.
Max side length 10000, sides different length, formula:  a*a + b*b - a*b = c*c
18394 triangles
```

## JavaScript

`(() => {    'use strict';     // main :: IO ()    const main = () => {         const            f90 = dct => x2 => dct[x2],            f60 = dct => (x2, ab) => dct[x2 - ab],            f120 = dct => (x2, ab) => dct[x2 + ab],            f60unequal = dct => (x2, ab, a, b) =>            (a !== b) ? (                dct[x2 - ab]            ) : undefined;          // triangles :: Dict -> (Int -> Int -> Int -> Int -> Maybe Int)        //                   -> [String]        const triangles = (f, n) => {            const                xs = enumFromTo(1, n),                fr = f(xs.reduce((a, x) => (a[x * x] = x, a), {})),                gc = xs.reduce((a, _) => a, {}),                setSoln = new Set();            return (                xs.forEach(                    a => {                        const a2 = a * a;                        enumFromTo(1, 1 + a).forEach(                            b => {                                const                                    suma2b2 = a2 + b * b,                                    c = fr(suma2b2, a * b, a, b);                                if (undefined !== c) {                                    setSoln.add([a, b, c].sort())                                };                            }                        );                    }                ),                Array.from(setSoln.keys())            );        };         const            result = 'Triangles of maximum side 13:\n\n' +            unlines(                zipWith(                    (s, f) => {                        const ks = triangles(f, 13);                        return ks.length.toString() + ' solutions for ' + s +                            ' degrees:\n' + unlines(ks) + '\n';                    },                    ['120', '90', '60'],                    [f120, f90, f60]                )            ) + '\nUneven triangles of maximum side 10000. Total:\n' +            triangles(f60unequal, 10000).length         return (            //console.log(result),            result        );    };      // GENERIC FUNCTIONS ----------------------------     // concatMap :: (a -> [b]) -> [a] -> [b]    const concatMap = (f, xs) =>        xs.reduce((a, x) => a.concat(f(x)), []);     // enumFromTo :: Int -> Int -> [Int]    const enumFromTo = (m, n) =>        m <= n ? iterateUntil(            x => n <= x,            x => 1 + x,            m        ) : [];     // iterateUntil :: (a -> Bool) -> (a -> a) -> a -> [a]    const iterateUntil = (p, f, x) => {        const vs = [x];        let h = x;        while (!p(h))(h = f(h), vs.push(h));        return vs;    };     // Returns Infinity over objects without finite length    // this enables zip and zipWith to choose the shorter    // argument when one non-finite like cycle, repeat etc     // length :: [a] -> Int    const length = xs => xs.length || Infinity;     // take :: Int -> [a] -> [a]    // take :: Int -> String -> String    const take = (n, xs) =>        xs.constructor.constructor.name !== 'GeneratorFunction' ? (            xs.slice(0, n)        ) : [].concat.apply([], Array.from({            length: n        }, () => {            const x = xs.next();            return x.done ? [] : [x.value];        }));     // unlines :: [String] -> String    const unlines = xs => xs.join('\n');     // Use of `take` and `length` here allows zipping with non-finite lists    // i.e. generators like cycle, repeat, iterate.     // Use of `take` and `length` here allows zipping with non-finite lists    // i.e. generators like cycle, repeat, iterate.     // zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]    const zipWith = (f, xs, ys) => {        const            lng = Math.min(length(xs), length(ys)),            as = take(lng, xs),            bs = take(lng, ys);        return Array.from({            length: lng        }, (_, i) => f(as[i], bs[i], i));    };     // MAIN ---    return main();})();`
Output:
```Triangles of maximum side 13:

2 solutions for 120 degrees:
3,5,7
13,7,8

3 solutions for 90 degrees:
3,4,5
10,6,8
12,13,5

15 solutions for 60 degrees:
1,1,1
2,2,2
3,3,3
4,4,4
5,5,5
6,6,6
7,7,7
3,7,8
5,7,8
8,8,8
9,9,9
10,10,10
11,11,11
12,12,12
13,13,13

Uneven triangles of maximum side 10000. Total:
18394
[Finished in 3.444s]```

## jq

Works with: jq

Works with gojq, the Go implementation of jq

To save space, we define `squares` as a hash rather than as a JSON array.

`def squares(n):  reduce range(1; 1+n) as \$i ({}; .[\$i*\$i|tostring] = \$i); # if count, then just countdef solve(angle; maxLen; allowSame; count):  squares(maxLen) as \$squares   | def qsqrt(\$n):    \$squares[\$n|tostring] as \$sqrt    | if \$sqrt then \$sqrt else null end;   reduce range(1; maxLen+1) as \$a ({};      reduce range(\$a; maxLen+1) as \$b (.;        .lhs = \$a*\$a + \$b*\$b        | if angle != 90          then if angle == 60               then .lhs += ( - \$a*\$b)               elif angle == 120               then .lhs +=  \$a*\$b               else "Angle must be 60, 90 or 120 degrees" | error               end          else .          end        | qsqrt(.lhs) as \$c        | if \$c != null          then if allowSame or \$a != \$b or \$b != \$c               then .solutions += if count then 1 else [[\$a, \$b, \$c]] end               else .               end           else .           end        )    )  | .solutions ; def task1(\$angles):  "For sides in the range [1, 13] where they can all be of the same length:\n",  (\$angles[]   | . as \$angle   | solve(\$angle; 13; true; false)   | "  For an angle of \(\$angle) degrees, there are \(length) solutions, namely:", .); def task2(degrees; n):  "For sides in the range [1, \(n)] where they cannot ALL be of the same length:",  (solve(degrees; n; false; true)   | "  For an angle of \(degrees) degrees, there are \(.) solutions.") ; task1([90, 60, 120]), "", task2(60; 10000)`
Output:
```For sides in the range [1, 13] where they can all be of the same length:

For an angle of 90 degrees, there are 3 solutions, namely:
[[3,4,5],[5,12,13],[6,8,10]]
For an angle of 60 degrees, there are 15 solutions, namely:
[[1,1,1],[2,2,2],[3,3,3],[3,8,7],[4,4,4],[5,5,5],[5,8,7],[6,6,6],[7,7,7],[8,8,8],[9,9,9],[10,10,10],[11,11,11],[12,12,12],[13,13,13]]
For an angle of 120 degrees, there are 2 solutions, namely:
[[3,5,7],[7,8,13]]

For sides in the range [1, 10000] where they cannot ALL be of the same length:
For an angle of 60 degrees, there are 18394 solutions.
```

## Julia

Translation of: zkl
`sqdict(n) = Dict([(x*x, x) for x in 1:n])numnotsame(arrarr) = sum(map(x -> !all(y -> y == x, x), arrarr)) function filtertriangles(N)    sqd = sqdict(N)    t60 = Vector{Vector{Int}}()    t90 = Vector{Vector{Int}}()    t120 = Vector{Vector{Int}}()    for x in 1:N, y in 1:x        xsq, ysq, xy = (x*x, y*y, x*y)        if haskey(sqd, xsq + ysq - xy)            push!(t60, sort([x, y, sqd[xsq + ysq - xy]]))        elseif haskey(sqd, xsq + ysq)            push!(t90, sort([x, y, sqd[xsq + ysq]]))        elseif haskey(sqd, xsq + ysq + xy)            push!(t120, sort([x, y, sqd[xsq + ysq + xy]]))        end    end    t60, t90, t120end tri60, tri90, tri120 = filtertriangles(13)println("Integer triples for 1 <= side length <= 13:\n")println("Angle 60:"); for t in tri60 println(t) endprintln("Angle 90:"); for t in tri90 println(t) endprintln("Angle 120:"); for t in tri120 println(t) endprintln("\nFor sizes N through 10000, there are \$(numnotsame(filtertriangles(10000))) 60 degree triples with nonequal sides.") `
Output:
```
Integer triples for 1 <= side length <= 13:
Angle 60:
[1, 1, 1]
[2, 2, 2]
[3, 3, 3]
[4, 4, 4]
[5, 5, 5]
[6, 6, 6]
[7, 7, 7]
[3, 7, 8]
[5, 7, 8]
[8, 8, 8]
[9, 9, 9]
[10, 10, 10]
[11, 11, 11]
[12, 12, 12]
[13, 13, 13]
Angle 90:
[3, 4, 5]
[6, 8, 10]
[5, 12, 13]
Angle 120:
[3, 5, 7]
[7, 8, 13]
For sizes N through 10000, there are 18394 60 degree triples with nonequal sides.

```

## Kotlin

Translation of: Go
`// Version 1.2.70 val squares13 = mutableMapOf<Int, Int>()val squares10000 = mutableMapOf<Int, Int>() class Trio(val a: Int, val b: Int, val c: Int) {    override fun toString() = "(\$a \$b \$c)"} fun init() {    for (i in 1..13) squares13.put(i * i, i)    for (i in 1..10000) squares10000.put(i * i, i)} fun solve(angle :Int, maxLen: Int, allowSame: Boolean): List<Trio> {    val solutions = mutableListOf<Trio>()    for (a in 1..maxLen) {        inner@ for (b in a..maxLen) {            var lhs = a * a + b * b            if (angle != 90) {                when (angle) {                    60   -> lhs -= a * b                    120  -> lhs += a * b                    else -> throw RuntimeException("Angle must be 60, 90 or 120 degrees")                }            }            when (maxLen) {                13 -> {                    val c = squares13[lhs]                    if (c != null) {                        if (!allowSame && a == b && b == c) continue@inner                        solutions.add(Trio(a, b, c))                    }                }                 10000 -> {                    val c = squares10000[lhs]                    if (c != null) {                        if (!allowSame && a == b && b == c) continue@inner                        solutions.add(Trio(a, b, c))                    }                }                 else -> throw RuntimeException("Maximum length must be either 13 or 10000")            }        }    }    return solutions} fun main(args: Array<String>) {    init()    print("For sides in the range [1, 13] ")    println("where they can all be of the same length:-\n")    val angles = intArrayOf(90, 60, 120)    lateinit var solutions: List<Trio>    for (angle in angles) {        solutions = solve(angle, 13, true)        print("  For an angle of \${angle} degrees")        println(" there are \${solutions.size} solutions, namely:")        println("  \${solutions.joinToString(" ", "[", "]")}\n")    }    print("For sides in the range [1, 10000] ")    println("where they cannot ALL be of the same length:-\n")    solutions = solve(60, 10000, false)    print("  For an angle of 60 degrees")    println(" there are \${solutions.size} solutions.")}`
Output:
```For sides in the range [1, 13] where they can all be of the same length:-

For an angle of 90 degrees there are 3 solutions, namely:
[(3 4 5) (5 12 13) (6 8 10)]

For an angle of 60 degrees there are 15 solutions, namely:
[(1 1 1) (2 2 2) (3 3 3) (3 8 7) (4 4 4) (5 5 5) (5 8 7) (6 6 6) (7 7 7) (8 8 8) (9 9 9) (10 10 10) (11 11 11) (12 12 12) (13 13 13)]

For an angle of 120 degrees there are 2 solutions, namely:
[(3 5 7) (7 8 13)]

For sides in the range [1, 10000] where they cannot ALL be of the same length:-

For an angle of 60 degrees there are 18394 solutions.
```

## Lua

`function solve(angle, maxlen, filter)  local squares, roots, solutions = {}, {}, {}  local cos2 = ({=-1,=0,=1})[angle]  for i = 1, maxlen do squares[i], roots[i^2] = i^2, i end  for a = 1, maxlen do    for b = a, maxlen do      local lhs = squares[a] + squares[b] + cos2*a*b      local c = roots[lhs]      if c and (not filter or filter(a,b,c)) then        solutions[#solutions+1] = {a=a,b=b,c=c}      end    end  end  print(angle.."° on 1.."..maxlen.." has "..#solutions.." solutions")  if not filter then    for i,v in ipairs(solutions) do print("",v.a,v.b,v.c) end  endendsolve(90, 13)solve(60, 13)solve(120, 13)function fexcr(a,b,c) return a~=b or b~=c endsolve(60, 10000, fexcr)  -- extra creditsolve(90, 10000, fexcr)  -- more extra creditsolve(120, 10000, fexcr) -- even more extra credit`
Output:
```90° on 1..13 has 3 solutions
3       4       5
5       12      13
6       8       10
60° on 1..13 has 15 solutions
1       1       1
2       2       2
3       3       3
3       8       7
4       4       4
5       5       5
5       8       7
6       6       6
7       7       7
8       8       8
9       9       9
10      10      10
11      11      11
12      12      12
13      13      13
120° on 1..13 has 2 solutions
3       5       7
7       8       13
60° on 1..10000 has 18394 solutions
90° on 1..10000 has 12471 solutions
120° on 1..10000 has 10374 solutions```

## Mathematica/Wolfram Language

`Solve[{a^2+b^2==c^2,1<=a<=13,1<=b<=13,1<=c<=13,a<=b},{a,b,c},Integers]Length[%]Solve[{a^2+b^2-a b==c^2,1<=a<=13,1<=b<=13,1<=c<=13,a<=b},{a,b,c},Integers]Length[%]Solve[{a^2+b^2+a b==c^2,1<=a<=13,1<=b<=13,1<=c<=13,a<=b},{a,b,c},Integers]Length[%]Solve[{a^2+b^2-a b==c^2,1<=a<=10000,1<=b<=10000,1<=c<=10000,a<=b,a!=b,b!=c,a!=c},{a,b,c},Integers]//Length`
Output:
```{{a->3,b->4,c->5},{a->5,b->12,c->13},{a->6,b->8,c->10}}
3
{{a->1,b->1,c->1},{a->2,b->2,c->2},{a->3,b->3,c->3},{a->3,b->8,c->7},{a->4,b->4,c->4},{a->5,b->5,c->5},{a->5,b->8,c->7},{a->6,b->6,c->6},{a->7,b->7,c->7},{a->8,b->8,c->8},{a->9,b->9,c->9},{a->10,b->10,c->10},{a->11,b->11,c->11},{a->12,b->12,c->12},{a->13,b->13,c->13}}
15
{{a->3,b->5,c->7},{a->7,b->8,c->13}}
2
18394```

## Nim

`import strformatimport tables # Generate tables at compile time. This eliminates the initialization at# the expense of a bigger executable. const square13 = block:  var tmp = newSeq[tuple[a, b: int]]()  for i in 1..13:    tmp.add((i * i, i))  toTable(tmp) const square10000 = block:  var tmp = newSeq[tuple[a, b: int]]()  for i in 1..10000:    tmp.add((i * i, i))  toTable(tmp) proc solve(angle, maxLen: int, allowSame: bool): seq[tuple[a, b, c: int]] =  result = newSeq[tuple[a, b, c: int]]()  for a in 1..maxLen:    for b in a..maxLen:      var lhs = a * a + b * b      if angle != 90:        case angle        of 60:          dec lhs, a * b        of 120:          inc lhs, a * b        else:          raise newException(IOError, "Angle must be 60, 90 or 120 degrees")      case maxLen      of 13:        var c = square13.getOrDefault(lhs)        if (not allowSame and a == b and b == c) or c == 0:          continue        result.add((a, b, c))      of 10000:        var c = square10000.getOrDefault(lhs)        if (not allowSame and a == b and b == c) or c == 0:          continue        result.add((a, b, c))      else:        raise newException(IOError, "Maximum length must be either 13 or 10000") echo "For sides in the range [1, 13] where they can all be the same length:\n"let angles = [90, 60, 120]for angle in angles:  var solutions = solve(angle, 13, true)  echo fmt"    For an angle of {angle} degrees there are {len(solutions)} solutions, to wit:"  write(stdout, "    ")  for i in 0..<len(solutions):    write(stdout, fmt"{solutions[i]:25}")    if i mod 3 == 2:      write(stdout, "\n    ")  write(stdout, "\n")echo "\nFor sides in the range [1, 10000] where they cannot ALL be of the same length:\n"var solutions = solve(60, 10000, false)echo fmt"    For an angle of 60 degrees there are {len(solutions)} solutions."`
Output:
```For sides in the range [1, 13] where they can all be the same length:

For an angle of 90 degrees there are 3 solutions, to wit:
(a: 3, b: 4, c: 5)       (a: 5, b: 12, c: 13)     (a: 6, b: 8, c: 10)

For an angle of 60 degrees there are 15 solutions, to wit:
(a: 1, b: 1, c: 1)       (a: 2, b: 2, c: 2)       (a: 3, b: 3, c: 3)
(a: 3, b: 8, c: 7)       (a: 4, b: 4, c: 4)       (a: 5, b: 5, c: 5)
(a: 5, b: 8, c: 7)       (a: 6, b: 6, c: 6)       (a: 7, b: 7, c: 7)
(a: 8, b: 8, c: 8)       (a: 9, b: 9, c: 9)       (a: 10, b: 10, c: 10)
(a: 11, b: 11, c: 11)    (a: 12, b: 12, c: 12)    (a: 13, b: 13, c: 13)

For an angle of 120 degrees there are 2 solutions, to wit:
(a: 3, b: 5, c: 7)       (a: 7, b: 8, c: 13)

For sides in the range [1, 10000] where they cannot ALL be of the same length:

For an angle of 60 degrees there are 18394 solutions.
```

## Perl

Translation of: Raku
`use utf8;binmode STDOUT, "utf8:";use Sort::Naturally; sub triples {    my(\$n,\$angle) = @_;    my(@triples,%sq);    \$sq{\$_**2}=\$_ for 1..\$n;    for \$a (1..\$n-1) {      for \$b (\$a+1..\$n) {        my \$ab = \$a*\$a + \$b*\$b;        my \$cos = \$angle == 60  ? \$ab - \$a * \$b :                  \$angle == 120 ? \$ab + \$a * \$b :                                  \$ab;        if (\$angle == 60) {            push @triples, "\$a \$sq{\$cos} \$b" if exists \$sq{\$cos};        } else {            push @triples, "\$a \$b \$sq{\$cos}" if exists \$sq{\$cos};        }      }    }    @triples;} \$n = 13;print "Integer triangular triples for sides 1..\$n:\n";for my \$angle (120, 90, 60) {   my @itt = triples(\$n,\$angle);   if (\$angle == 60) { push @itt, "\$_ \$_ \$_" for 1..\$n }   printf "Angle %3d° has %2d solutions: %s\n", \$angle, scalar @itt,         join ', ', nsort @itt;} printf "Non-equilateral n=10000/60°: %d\n", scalar triples(10000,60);`
Output:
```Integer triangular triples for sides 1..13:
Angle 120° has  2 solutions: 3 5 7, 7 8 13
Angle  90° has  3 solutions: 3 4 5, 6 8 10, 5 12 13
Angle  60° has 15 solutions: 1 1 1, 2 2 2, 3 3 3, 3 7 8, 4 4 4, 5 5 5, 5 7 8, 6 6 6, 7 7 7, 8 8 8, 9 9 9, 10 10 10, 11 11 11, 12 12 12, 13 13 13
Non-equilateral n=10000/60°: 18394```

## Phix

Using a simple flat sequence of 100 million elements (well within the desktop language limits, but beyond JavaScript) proved significantly faster than a dictionary (5x or so).

```with javascript_semantics
--constant lim = iff(platform()=JS?13:10000)
constant lim = 10000
--sequence squares = repeat(0,lim*lim)
sequence squares = iff(platform()=JS?{}:repeat(0,lim*lim))
for c=1 to lim do
squares[c*c] = c
end for

function solve(integer angle, maxlen, bool samelen=true)
sequence res = {}
for a=1 to maxlen do
integer a2 = a*a
for b=a to maxlen do
integer c2 = a2+b*b
if angle!=90 then
if    angle=60  then c2 -= a*b
elsif angle=120 then c2 += a*b
else crash("angle must be 60/90/120")
end if
end if
integer c = iff(c2>length(squares)?0:squares[c2])
if c!=0 and c<=maxlen then
if samelen or a!=b or b!=c then
res = append(res,{a,b,c})
end if
end if
end for
end for
return res
end function

procedure show(string fmt,sequence res, bool full=true)
printf(1,fmt,{length(res),iff(full?sprint(res):"")})
end procedure

puts(1,"Integer triangular triples for sides 1..13:\n")
show("Angle  60 has %2d solutions: %s\n",solve( 60,13))
show("Angle  90 has %2d solutions: %s\n",solve( 90,13))
show("Angle 120 has %2d solutions: %s\n",solve(120,13))
--if platform()!=JS then
show("Non-equilateral angle 60 triangles for sides 1..10000: %d%s\n",solve(60,10000,false),false)
--end if
```
Output:
```Integer triangular triples for sides 1..13:
Angle  60 has 15 solutions: {{1,1,1},{2,2,2},{3,3,3},{3,8,7},{4,4,4},{5,5,5},{5,8,7},{6,6,6},{7,7,7},{8,8,8},{9,9,9},{10,10,10},{11,11,11},{12,12,12},{13,13,13}}
Angle  90 has  3 solutions: {{3,4,5},{5,12,13},{6,8,10}}
Angle 120 has  2 solutions: {{3,5,7},{7,8,13}}
Non-equilateral angle 60 triangles for sides 1..10000: 18394
```

As noted I had to resort to a little trickery to get that last line to run in JavaScript, should a future version impose stricter bounds checking that will stop working.

## Prolog

Works with: SWI Prolog
`find_solutions(Limit, Solutions):-    find_solutions(Limit, Solutions, Limit, []). find_solutions(_, S, 0, S):-    !.find_solutions(Limit, Solutions, A, S):-    find_solutions1(Limit, A, A, S1, S),    A_next is A - 1,    find_solutions(Limit, Solutions, A_next, S1). find_solutions1(Limit, _, B, Triples, Triples):-    B > Limit,    !.find_solutions1(Limit, A, B, [Triple|Triples], T):-    is_solution(Limit, A, B, Triple),    !,    B_next is B + 1,    find_solutions1(Limit, A, B_next, Triples, T).find_solutions1(Limit, A, B, Triples, T):-    B_next is B + 1,    find_solutions1(Limit, A, B_next, Triples, T). is_solution(Limit, A, B, t(Angle, A, B, C)):-    X is A * A + B * B,    Y is A * B,    (        Angle = 90, C is round(sqrt(X)), X is C * C        ;        Angle = 120, C2 is X + Y, C is round(sqrt(C2)), C2 is C * C        ;        Angle = 60, C2 is X - Y, C is round(sqrt(C2)), C2 is C * C    ),    C =< Limit,    !. write_triples(Angle, Solutions):-    find_triples(Angle, Solutions, List, 0, Count),    writef('There are %w solutions for gamma = %w:\n', [Count, Angle]),    write_triples1(List),    nl. find_triples(_, [], [], Count, Count):-    !.find_triples(Angle, [Triple|Triples], [Triple|Result], C, Count):-    Triple = t(Angle, _, _, _),    !,    C1 is C + 1,    find_triples(Angle, Triples, Result, C1, Count).find_triples(Angle, [_|Triples], Result, C, Count):-    find_triples(Angle, Triples, Result, C, Count). write_triples1([]):-!.write_triples1([t(_, A, B, C)]):-    writef('(%w,%w,%w)\n', [A, B, C]),    !.write_triples1([t(_, A, B, C)|Triples]):-    writef('(%w,%w,%w) ', [A, B, C]),    write_triples1(Triples). main:-    find_solutions(13, Solutions),    write_triples(60, Solutions),    write_triples(90, Solutions),    write_triples(120, Solutions).`
Output:
```There are 15 solutions for gamma = 60:
(1,1,1) (2,2,2) (3,3,3) (3,8,7) (4,4,4) (5,5,5) (5,8,7) (6,6,6) (7,7,7) (8,8,8) (9,9,9) (10,10,10) (11,11,11) (12,12,12) (13,13,13)

There are 3 solutions for gamma = 90:
(3,4,5) (5,12,13) (6,8,10)

There are 2 solutions for gamma = 120:
(3,5,7) (7,8,13)
```

## Python

### Sets

`N = 13 def method1(N=N):    squares = [x**2 for x in range(0, N+1)]    sqrset = set(squares)    tri90, tri60, tri120 = (set() for _ in range(3))    for a in range(1, N+1):        a2 = squares[a]        for b in range(1, a + 1):            b2 = squares[b]            c2 = a2 + b2            if c2 in sqrset:                tri90.add(tuple(sorted((a, b, int(c2**0.5)))))            ab = a * b            c2 -= ab            if c2 in sqrset:                tri60.add(tuple(sorted((a, b, int(c2**0.5)))))            c2 += 2 * ab            if c2 in sqrset:                tri120.add(tuple(sorted((a, b, int(c2**0.5)))))    return  sorted(tri90), sorted(tri60), sorted(tri120)#%%if __name__ == '__main__':    print(f'Integer triangular triples for sides 1..{N}:')    for angle, triples in zip([90, 60, 120], method1(N)):        print(f'  {angle:3}° has {len(triples)} solutions:\n    {triples}')    _, t60, _ = method1(10_000)    notsame = sum(1 for a, b, c in t60 if a != b or b != c)    print('Extra credit:', notsame)`
Output:
```Integer triangular triples for sides 1..13:
90° has 3 solutions:
[(3, 4, 5), (5, 12, 13), (6, 8, 10)]
60° has 15 solutions:
[(1, 1, 1), (2, 2, 2), (3, 3, 3), (3, 7, 8), (4, 4, 4), (5, 5, 5), (5, 7, 8), (6, 6, 6), (7, 7, 7), (8, 8, 8), (9, 9, 9), (10, 10, 10), (11, 11, 11), (12, 12, 12), (13, 13, 13)]
120° has 2 solutions:
[(3, 5, 7), (7, 8, 13)]
Extra credit: 18394```

### Dictionaries

A variant Python draft based on dictionaries. (Test functions are passed as parameters to the main function.)

`from itertools import (starmap)  def f90(dct):    return lambda x2, ab, a, b: dct.get(x2, None)  def f60(dct):    return lambda x2, ab, a, b: dct.get(x2 - ab, None)  def f120(dct):    return lambda x2, ab, a, b: dct.get(x2 + ab, None)  def f60unequal(dct):    return lambda x2, ab, a, b: (        dct.get(x2 - ab, None) if a != b else None    )  # triangles :: Dict -> (Int -> Int -> Int -> Int -> Maybe Int)#                   -> [String]def triangles(f, n):    upto = enumFromTo(1)    xs = upto(n)    dctSquares = dict(zip(xs, [x**2 for x in xs]))    dctRoots = {v: k for k, v in dctSquares.items()}    fr = f(dctRoots)    dct = {}    for a in xs:        a2 = dctSquares[a]        for b in upto(a):            suma2b2 = a2 + dctSquares[b]            c = fr(suma2b2, a * b, a, b)            if (c is not None):                dct[str(sorted([a, b, c]))] = 1    return list(dct.keys())  def main():    print(        'Triangles of maximum side 13\n\n' +        unlines(            zipWith(                lambda f, n: (                    lambda ks=triangles(f, 13): (                        str(len(ks)) + ' solutions for ' +                        str(n) + ' degrees:\n' +                        unlines(ks) + '\n'                    )                )()            )([f120, f90, f60])             ([120, 90, 60])        ) + '\n\n' +        '60 degrees - uneven triangles of maximum side 10000. Total:\n' +        str(len(triangles(f60unequal, 10000)))    )  # GENERIC -------------------------------------------------------------- # enumFromTo :: Int -> Int -> [Int]def enumFromTo(m):    return lambda n: list(range(m, 1 + n))  # unlines :: [String] -> Stringdef unlines(xs):    return '\n'.join(xs)  # zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]def zipWith(f):    return lambda xs: lambda ys: (        list(starmap(f, zip(xs, ys)))    )  if __name__ == '__main__':    main()`
Output:
```Triangles of maximum side 13

2 solutions for 120 degrees:
[3, 5, 7]
[7, 8, 13]

3 solutions for 90 degrees:
[3, 4, 5]
[6, 8, 10]
[5, 12, 13]

15 solutions for 60 degrees:
[1, 1, 1]
[2, 2, 2]
[3, 3, 3]
[4, 4, 4]
[5, 5, 5]
[6, 6, 6]
[7, 7, 7]
[3, 7, 8]
[5, 7, 8]
[8, 8, 8]
[9, 9, 9]
[10, 10, 10]
[11, 11, 11]
[12, 12, 12]
[13, 13, 13]

60 degrees - uneven triangles of maximum side 10000. Total:
18394```

## R

This looks a bit messy, but it really pays off when you see how nicely the output prints.

`inputs <- cbind(combn(1:13, 2), rbind(seq_len(13), seq_len(13)))inputs <- cbind(A = inputs[1, ], B = inputs[2, ])[sort.list(inputs[1, ]),]Pythagoras <- inputs[, "A"]^2 + inputs[, "B"]^2AtimesB <- inputs[, "A"] * inputs[, "B"]CValues <- sqrt(cbind("C (90º)" = Pythagoras,                      "C (60º)" = Pythagoras - AtimesB,                      "C (120º)" = Pythagoras + AtimesB))CValues[!t(apply(CValues, MARGIN = 1, function(x) x %in% 1:13))] <- NAoutput <- cbind(inputs, CValues)[!apply(CValues, MARGIN = 1, function(x) all(is.na(x))),]rownames(output) <- paste0("Solution ", seq_len(nrow(output)), ":")print(output, na.print = "")cat("There are",    sum(!is.na(output[, 3])), "solutions in the 90º case,",    sum(!is.na(output[, 4])), "solutions in the 60º case, and",    sum(!is.na(output[, 5])), "solutions in the 120º case.")`
Output:
```              A  B C (90º) C (60º) C (120º)
Solution 1:   1  1               1
Solution 2:   2  2               2
Solution 3:   3  4       5
Solution 4:   3  5                        7
Solution 5:   3  8               7
Solution 6:   3  3               3
Solution 7:   4  4               4
Solution 8:   5  8               7
Solution 9:   5 12      13
Solution 10:  5  5               5
Solution 11:  6  8      10
Solution 12:  6  6               6
Solution 13:  7  8                       13
Solution 14:  7  7               7
Solution 15:  8  8               8
Solution 16:  9  9               9
Solution 17: 10 10              10
Solution 18: 11 11              11
Solution 19: 12 12              12
Solution 20: 13 13              13
There are 3 solutions in the 90º case, 15 solutions in the 60º case, and 2 solutions in the 120º case.```

## Raku

(formerly Perl 6) In each routine, race is used to allow concurrent operations, requiring the use of the atomic increment operator, ⚛++, to safely update @triples, which must be declared fixed-sized, as an auto-resizing array is not thread-safe. At exit, default values in @triples are filtered out with the test `!eqv Any`.

`multi triples (60, \$n) {    my %sq = (1..\$n).map: { .² => \$_ };    my atomicint \$i = 0;    my @triples[2*\$n];    (1..^\$n).race(:8degree).map: -> \$a {        for \$a^..\$n -> \$b {            my \$cos = \$a * \$a + \$b * \$b - \$a * \$b;            @triples[\$i⚛++] = \$a, %sq{\$cos}, \$b if %sq{\$cos}:exists;        }    }    @triples.grep: so *;} multi triples (90, \$n) {    my %sq = (1..\$n).map: { .² => \$_ };    my atomicint \$i = 0;    my @triples[2*\$n];    (1..^\$n).race(:8degree).map: -> \$a {        for \$a^..\$n -> \$b {            my \$cos = \$a * \$a + \$b * \$b;            @triples[\$i⚛++] = \$a, \$b, %sq{\$cos} and last if %sq{\$cos}:exists;        }    }    @triples.grep: so *;} multi triples (120, \$n) {    my %sq = (1..\$n).map: { .² => \$_ };    my atomicint \$i = 0;    my @triples[2*\$n];    (1..^\$n).race(:8degree).map: -> \$a {        for \$a^..\$n -> \$b {            my \$cos = \$a * \$a + \$b * \$b + \$a * \$b;            @triples[\$i⚛++] = \$a, \$b, %sq{\$cos} and last if %sq{\$cos}:exists;        }    }    @triples.grep: so *;} use Sort::Naturally; my \$n = 13;say "Integer triangular triples for sides 1..\$n:";for 120, 90, 60 -> \$angle {    my @itt = triples(\$angle, \$n);    if \$angle == 60 { push @itt, "\$_ \$_ \$_" for 1..\$n }    printf "Angle %3d° has %2d solutions: %s\n", \$angle, +@itt, @itt.sort(&naturally).join(', ');} my (\$angle, \$count) = 60, 10_000;say "\nExtra credit:";say "\$angle° integer triples in the range 1..\$count where the sides are not all the same length: ", +triples(\$angle, \$count);`
Output:
```Integer triangular triples for sides 1..13:
Angle 120° has  2 solutions: 3 5 7, 7 8 13
Angle  90° has  3 solutions: 3 4 5, 5 12 13, 6 8 10
Angle  60° has 15 solutions: 1 1 1, 2 2 2, 3 3 3, 3 7 8, 4 4 4, 5 5 5, 5 7 8, 6 6 6, 7 7 7, 8 8 8, 9 9 9, 10 10 10, 11 11 11, 12 12 12, 13 13 13

Extra credit:
60° integer triples in the range 1..10000 where the sides are not all the same length: 18394```

## REXX

(Using some optimization and memoization.)

Instead of coding a general purpose subroutine (or function) to solve all of the task's requirements,   it was decided to
write three very similar   do   loops (triple nested) to provide the answers for the three requirements.

Three arguments   (from the command line)   can be specified which indicates the maximum length of the triangle sides
(the default is   13,   as per the task's requirement)   for each of the three types of angles   (60º, 90º, and 120º)   for
the triangles.   If the maximum length of the triangle's number of sides is positive,   it indicates that the triangle sides are
displayed,   as well as a total number of triangles found.

If the maximum length of the triangle sides is negative,   only the   number   of triangles are displayed   (using the
absolute value of the negative number).

`/*REXX pgm finds integer sided triangles that satisfy Law of cosines for 60º, 90º, 120º.*/parse arg os1 os2 os3 os4 .                      /*obtain optional arguments from the CL*/if os1=='' | os1==","  then os1= 13; s1=abs(os1) /*Not specified?  Then use the default.*/if os2=='' | os2==","  then os2= 13; s2=abs(os2) /* "      "         "   "   "     "    */if os3=='' | os3==","  then os3= 13; s3=abs(os3) /* "      "         "   "   "     "    */if os4=='' | os4==","  then os4= -0; s4=abs(os4) /* "      "         "   "   "     "    */@.=                                              /*@:  array holds squares, max of sides*/                      do j=1  for max(s1, s2, s3, s4);  @.j= j * j    /*use memoization.*/                      end   /*j*/if s1>0  then call s1                            /*handle the triangle case for   120º. */if s2>0  then call s2                            /*handle the triangle case for    90º. */if s3>0  then call s3                            /*handle the triangle case for    60º. */if s4>0  then call s4                            /*handle the case for unique sides.    */exit 0                                           /*stick a fork in it,  we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/commas: parse arg ?;  do jc=length(?)-3  to 1  by -3; ?=insert(',', ?, jc); end;  return ?dAng: w= length(s); ang= ' 'd"º " uq' ';  ss= s * s;  @sol= " solutions found for"; return          foot: say right(commas(#) @sol ang  "(sides up to" commas(arg(1) +0)')', 65);  say; returnhead: #= 0;  parse arg d,uq,s;  @= ',';   call dAng;      say center(ang, 65, '═'); returnshow: #=#+1; arg p; if p>0  then say '     ('right(a,w)@ right(b,w)@ right(c,w)")"; return/*──────────────────────────────────────────────────────────────────────────────────────*/s1:   call head 120,,s1                          /*────────── 120º:  a² + b² + ab  ≡ c² */             do     a=1    for s1;         ap1= a + 1               do   b=ap1  for s1-ap1+1;   x= @.a + @.b + a*b;     if x>ss  then iterate a                 do c=b+1  for s1-b+1  until @.c>x                 if [email protected].c  then do;  call show os1;  iterate b;  end                 end   /*c*/               end     /*b*/             end       /*a*/      call foot s1;                        return/*──────────────────────────────────────────────────────────────────────────────────────*/s2:   call head  90,,s2                          /*────────── 90º:   a² + b²       ≡ c² */             do     a=1    for s2;         ap1= a + 1               do   b=ap1  for s2-ap1+1;   x= @.a + @.b;           if x>ss  then iterate a                 do c=b+1  for s2-b+2  until @.c>x                 if [email protected].c  then do;  call show os2;  iterate b;  end                 end   /*c*/               end     /*b*/             end       /*a*/      call foot s2;                        return/*──────────────────────────────────────────────────────────────────────────────────────*/s3:   call head  60,,s3                          /*────────── 60º:   a² + b² ─ ab  ≡ c² */             do     a=1   for s3;          s3ma= s3 - a + 1               do   b=a   for s3ma;        x= @.a + @.b - a*b;     if x>ss  then iterate a                 do c=a   for s3ma  until @.c>x                 if [email protected].c  then do;  call show os3;  iterate b;  end                 end   /*c*/               end     /*b*/             end       /*a*/      call foot s2;                        return/*──────────────────────────────────────────────────────────────────────────────────────*/s4:   call head  60, 'unique', os4               /*────────── 60º:  a² + b² ─ ab   ≡ c² */             do     a=1    for s4;         ap1= a + 1;    s4map1= s4 - ap1 + 1               do   b=ap1  for s4map1;     x= @.a + @.b - a*b;     if x>ss  then iterate a                 do c=ap1  for s4map1  until @.c>x                 if [email protected].c  then do;  call show os4;  iterate b;  end                 end   /*c*/               end     /*b*/             end       /*a*/      call foot s4;                        return`
output   when using the default number of sides for the input:     13
```═════════════════════════════ 120º ══════════════════════════════
( 3,  5,  7)
( 7,  8, 13)
2  solutions found for  120º  (sides up to 13)

══════════════════════════════ 90º ══════════════════════════════
( 3,  4,  5)
( 5, 12, 13)
( 6,  8, 10)
3  solutions found for  90º  (sides up to 13)

══════════════════════════════ 60º ══════════════════════════════
( 1,  1,  1)
( 2,  2,  2)
( 3,  3,  3)
( 3,  8,  7)
( 4,  4,  4)
( 5,  5,  5)
( 5,  8,  7)
( 6,  6,  6)
( 7,  7,  7)
( 8,  8,  8)
( 9,  9,  9)
(10, 10, 10)
(11, 11, 11)
(12, 12, 12)
(13, 13, 13)
15  solutions found for  60º  (sides up to 13)
```
output   when using the inputs of:     0   0   0   -10000

Note that the first three computations are bypassed because of the three zero (0) numbers,   the negative ten thousand indicates to find all the triangles with sides up to 10,000,   but not list the triangles, it just reports the   number   of solutions found.

```══════════════════════════ 60º  unique ══════════════════════════
18,394  solutions found for  60º  unique (sides up to 10,000)
```

## Ruby

`grouped =  (1..13).to_a.repeated_permutation(3).group_by do |a,b,c|  sumaabb, ab = a*a + b*b, a*b  case c*c    when sumaabb      then 90    when sumaabb - ab then 60    when sumaabb + ab then 120  endend grouped.delete(nil)res = grouped.transform_values{|v| v.map(&:sort).uniq } res.each do |k,v|  puts "For an angle of #{k} there are #{v.size} solutions:"  puts v.inspect, "\n"end `
Output:
```For an angle of 60 there are 15 solutions:
[[1, 1, 1], [2, 2, 2], [3, 3, 3], [3, 7, 8], [4, 4, 4], [5, 5, 5], [5, 7, 8], [6, 6, 6], [7, 7, 7], [8, 8, 8], [9, 9, 9], [10, 10, 10], [11, 11, 11], [12, 12, 12], [13, 13, 13]]

For an angle of 90 there are 3 solutions:
[[3, 4, 5], [5, 12, 13], [6, 8, 10]]

For an angle of 120 there are 2 solutions:
[[3, 5, 7], [7, 8, 13]]
```

Extra credit:

`n  = 10_000ar = (1..n).to_asquares = {}ar.each{|i| squares[i*i] = true }count = ar.combination(2).count{|a,b| squares.key?(a*a + b*b - a*b)} puts "There are #{count} 60° triangles with unequal sides of max size #{n}." `
Output:
```There are 18394 60° triangles with unequal sides of max size 10000.

```

## Wren

Translation of: Go
`var squares13 = {}var squares10000 = {} var initMaps = Fn.new {    for (i in 1..13) squares13[i*i] = i    for (i in 1..10000) squares10000[i*i] = i} var solve = Fn.new { |angle, maxLen, allowSame|    var solutions = []    for (a in 1..maxLen) {        for (b in a..maxLen) {            var lhs = a*a + b*b            if (angle != 90) {                if (angle == 60) {                    lhs = lhs - a*b                } else if (angle == 120) {                    lhs = lhs + a*b                } else {                    Fiber.abort("Angle must be 60, 90 or 120 degrees")                }            }            if (maxLen == 13) {                var c = squares13[lhs]                if (c != null) {                    if (allowSame || a != b || b != c) {                        solutions.add([a, b, c])                    }                }            } else if (maxLen == 10000) {                                 var c = squares10000[lhs]                if (c != null) {                    if (allowSame || a != b || b != c) {                        solutions.add([a, b, c])                    }                }            } else {                Fiber.abort("Maximum length must be either 13 or 10000")            }        }    }    return solutions} initMaps.call()System.write("For sides in the range [1, 13] ")System.print("where they can all be of the same length:-\n")var angles = [90, 60, 120]var solutions = []for (angle in angles) {    solutions = solve.call(angle, 13, true)    System.write("  For an angle of %(angle) degrees")    System.print(" there are %(solutions.count) solutions, namely:")    System.print("  %(solutions)")    System.print()}System.write("For sides in the range [1, 10000] ")System.print("where they cannot ALL be of the same length:-\n")solutions = solve.call(60, 10000, false)System.write("  For an angle of 60 degrees")System.print(" there are %(solutions.count) solutions.")`
Output:
```For sides in the range [1, 13] where they can all be of the same length:-

For an angle of 90 degrees there are 3 solutions, namely:
[[3, 4, 5], [5, 12, 13], [6, 8, 10]]

For an angle of 60 degrees there are 15 solutions, namely:
[[1, 1, 1], [2, 2, 2], [3, 3, 3], [3, 8, 7], [4, 4, 4], [5, 5, 5], [5, 8, 7], [6, 6, 6], [7, 7, 7], [8, 8, 8], [9, 9, 9], [10, 10, 10], [11, 11, 11], [12, 12, 12], [13, 13, 13]]

For an angle of 120 degrees there are 2 solutions, namely:
[[3, 5, 7], [7, 8, 13]]

For sides in the range [1, 10000] where they cannot ALL be of the same length:-

For an angle of 60 degrees there are 18394 solutions.
```

## zkl

`fcn tritri(N=13){   sqrset:=[0..N].pump(Dictionary().add.fp1(True),fcn(n){ n*n });   tri90, tri60, tri120 := List(),List(),List();   foreach a,b in ([1..N],[1..a]){      aa,bb := a*a,b*b;      ab,c  := a*b, aa + bb - ab;	// 60*      if(sqrset.holds(c)){ tri60.append(abc(a,b,c)); continue; }       c=aa + bb;			// 90*      if(sqrset.holds(c)){ tri90.append(abc(a,b,c)); continue; }       c=aa + bb + ab;			// 120*      if(sqrset.holds(c))  tri120.append(abc(a,b,c));   }   List(tri60,tri90,tri120)}fcn abc(a,b,c){ List(a,b).sort().append(c.toFloat().sqrt().toInt()) }fcn triToStr(tri){	// ((c,d,e),(a,b,c))-->"(a,b,c),(c,d,e)"   tri.sort(fcn(t1,t2){ t1<t2 })      .apply("concat",",").apply("(%s)".fmt).concat(",")}`
`N:=13;println("Integer triangular triples for sides 1..%d:".fmt(N));foreach angle, triples in (T(60,90,120).zip(tritri(N))){   println(" %3d\U00B0; has %d solutions:\n    %s"           .fmt(angle,triples.len(),triToStr(triples)));}`
Output:
```Integer triangular triples for sides 1..13:
60° has 15 solutions:
(1,1,1),(2,2,2),(3,8,7),(3,3,3),(4,4,4),(5,8,7),(5,5,5),(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10),(11,11,11),(12,12,12),(13,13,13)
90° has 3 solutions:
(3,4,5),(5,12,13),(6,8,10)
120° has 2 solutions:
(3,5,7),(7,8,13)
```

Extra credit:

`fcn tri60(N){	// special case 60*   sqrset:=[1..N].pump(Dictionary().add.fp1(True),fcn(n){ n*n });   n60:=0;   foreach a,b in ([1..N],[1..a]){      c:=a*a + b*b - a*b;      if(sqrset.holds(c) and a!=b!=c) n60+=1;   }   n60}`
`N:=10_000;println(("60\U00b0; triangle where side lengths are unique,\n"   "   side lengths 1..%,d, there are %,d solutions.").fmt(N,tri60(N)));`
Output:
```60° triangle where side lengths are unique,
side lengths 1..10,000, there are 18,394 solutions.
```