Task: Law of cosines - triples


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;
}


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;
}