5M3GSMBZFQ2X7YJF3SYTOMJLDX3JE6I4TRLTRFWCUXYWWUODY5CQC
package dickson_test
import (
"pythagorean"
"pythagorean/dickson"
"reflect"
"testing"
)
var rangeTests = []struct {
min, max int
ts []pythagorean.Triplet
}{
{1, 10, []pythagorean.Triplet{{3, 4, 5}, {6, 8, 10}}},
{11, 20, []pythagorean.Triplet{{12, 16, 20}}},
}
func TestRange(t *testing.T) {
for _, test := range rangeTests {
ts := dickson.Range(test.min, test.max)
if !reflect.DeepEqual(ts, test.ts) {
t.Fatalf("Range(%d, %d) = %v, want %v",
test.min, test.max, ts, test.ts)
}
}
}
var sumTests = []struct {
sum int
ts []pythagorean.Triplet
}{
{180, []pythagorean.Triplet{{18, 80, 82}, {30, 72, 78}, {45, 60, 75}}},
{1000, []pythagorean.Triplet{{200, 375, 425}}},
}
func TestSum(t *testing.T) {
for _, test := range sumTests {
ts := dickson.Sum(test.sum)
if !reflect.DeepEqual(ts, test.ts) {
t.Fatalf("Sum(%d) = %v, want %v",
test.sum, ts, test.ts)
}
}
}
func BenchmarkRange(b *testing.B) {
for i := 0; i < b.N; i++ {
dickson.Range(1, 100)
}
}
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
dickson.Sum(1000)
}
}
// Package dickson calculates pythagorean triplets using Dickson's method.
// https://en.wikipedia.org/wiki/Formulas_for_generating_Pythagorean_triples#Dickson's_method
package dickson
import (
"pythagorean"
)
// Range return a list of all Pythagorean triplets with sides int he range min to max inclusive.
func Range(min, max int) []pythagorean.Triplet {
ret := []pythagorean.Triplet{}
var a, b, c int
for c < max {
for r := 2; r < max/2; r = r + 2 {
fact := factors((r * r) / 2)
for i := 0; i < len(fact)/2; i++ {
s := fact[i]
t := (r * r) / 2 / fact[i]
a = r + s
b = r + t
c = r + s + t
if a >= min && c <= max {
ret = append(ret, pythagorean.Triplet{a, b, c})
}
}
}
}
return ret
}
func factors(input int) []int {
var factor []int
for i := 1; i < input/2+1; i++ {
if input%i == 0 {
factor = append(factor, i)
}
}
factor = append(factor, input)
return factor
}
// Sum returns a list of all Pythagorean triplets where the sum a+b+c is equal to p.
func Sum(p int) []pythagorean.Triplet {
var ret []pythagorean.Triplet
candidates := Range(1, p/2)
for i, tr := range candidates {
if tr[0]+tr[1]+tr[2] == p {
ret = append(ret, candidates[i])
}
}
return ret
}