Task: Law of cosines - triples




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.")
}




Python: 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)