summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--factor_info.go6
-rw-r--r--factors/prime_factorization.go4
-rw-r--r--factors/slices.go27
-rw-r--r--factors/table_test.go66
-rw-r--r--factors/type.go11
-rw-r--r--go.mod2
6 files changed, 85 insertions, 31 deletions
diff --git a/factor_info.go b/factor_info.go
index a6710e7..f3193b5 100644
--- a/factor_info.go
+++ b/factor_info.go
@@ -5,7 +5,7 @@ import (
"fmt"
"io"
"math"
- "slices"
+ "sort"
)
// FactorInfo contains all of the information this program
@@ -64,7 +64,9 @@ func getFactorInfo(a args) *factorInfo {
radix := a.Radix
r_factors := factors.Factors(radix)
- slices.Sort(r_factors)
+ sort.Slice(r_factors, func(i, j int) bool {
+ return r_factors[i] < r_factors[j]
+ })
var totativeDigits []uint32 = nil
if a.TotativeDigits && radix < maxExtended {
diff --git a/factors/prime_factorization.go b/factors/prime_factorization.go
index 52df2c1..f758448 100644
--- a/factors/prime_factorization.go
+++ b/factors/prime_factorization.go
@@ -2,7 +2,6 @@ package factors
import (
"fmt"
- "slices"
"strings"
)
@@ -69,8 +68,7 @@ func (factors PrimeFactorization) Size() int {
// String returns a string representation of the prime factorization,
// which looks like "2^2 × 3".
func (factors PrimeFactorization) String() string {
- primesSorted := factors.Primes()
- slices.Sort(primesSorted)
+ primesSorted := sortUints(factors.Primes())
parts := make([]string, 0, factors.Size())
for _, p := range primesSorted {
diff --git a/factors/slices.go b/factors/slices.go
new file mode 100644
index 0000000..f2462cf
--- /dev/null
+++ b/factors/slices.go
@@ -0,0 +1,27 @@
+package factors
+
+import "sort"
+
+func sortUints(s []uint) []uint {
+ sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
+ return s
+}
+
+func maxUints(s []uint) uint {
+ max := uint(0)
+ for _, n := range s {
+ if n > max {
+ max = n
+ }
+ }
+ return max
+}
+
+func contains[S ~[]E, E comparable](s S, e E) bool {
+ for _, element := range s {
+ if e == element {
+ return true
+ }
+ }
+ return false
+}
diff --git a/factors/table_test.go b/factors/table_test.go
index e288c3b..828d80b 100644
--- a/factors/table_test.go
+++ b/factors/table_test.go
@@ -2,8 +2,6 @@ package factors
import (
"fmt"
- "maps"
- "slices"
"testing"
)
@@ -41,7 +39,7 @@ var primeFactorCases = map[uint]PrimeFactorization{
func TestPrimeFactorize(t *testing.T) {
equal := func(a, b PrimeFactorization) bool {
- return maps.Equal(a.exponents, b.exponents)
+ return mapEquals(a.exponents, b.exponents)
}
tableTest(t, PrimeFactorize, primeFactorCases, equal, "PrimeFactorize")
}
@@ -66,7 +64,7 @@ var factorCases = map[uint][]uint{
}
func TestFactors(t *testing.T) {
- tableTest(t, Factors, factorCases, setEquals, "Factors")
+ tableTest(t, Factors, factorCases, setEquals[uint], "Factors")
}
var totativeRatioCases = map[uint]float64{
@@ -81,7 +79,8 @@ func totativeRatio(n uint) float64 {
}
func TestTotativeRatio(t *testing.T) {
- tableTest(t, totativeRatio, totativeRatioCases, stdEquals, "TotativeRatio")
+ tableTest(t, totativeRatio, totativeRatioCases, stdEquals[float64],
+ "TotativeRatio")
}
var totientCases = map[uint]uint{
@@ -90,7 +89,7 @@ var totientCases = map[uint]uint{
}
func TestTotativeCount(t *testing.T) {
- tableTest(t, Totient, totientCases, stdEquals, "Totient")
+ tableTest(t, Totient, totientCases, stdEquals[uint], "Totient")
}
var totativeDigitCases = map[uint32][]uint32{
@@ -121,7 +120,7 @@ var totativeDigitCases = map[uint32][]uint32{
}
func TestTotativeDigits(t *testing.T) {
- tableTest(t, TotativeDigits, totativeDigitCases, slices.Equal,
+ tableTest(t, TotativeDigits, totativeDigitCases, sliceEquals[uint32],
"TotativeDigits")
}
@@ -142,7 +141,7 @@ var factorScoreCases = map[uint]float64{
func TestFactorScore(t *testing.T) {
// factors.Score is accurate enough that we can test for exact floats!
- tableTest(t, Score, factorScoreCases, stdEquals, "Score")
+ tableTest(t, Score, factorScoreCases, stdEquals[float64], "Score")
}
var basicRankCases = map[uint]string{
@@ -160,7 +159,7 @@ var basicRankCases = map[uint]string{
}
func TestBasicRank(t *testing.T) {
- tableTest(t, BasicRank, basicRankCases, stdEquals, "BasicRank")
+ tableTest(t, BasicRank, basicRankCases, stdEquals[string], "BasicRank")
}
var gcdCases = map[struct{ a, b uint32 }]uint32{
@@ -181,7 +180,7 @@ func gcdTest(c struct{ a, b uint32 }) uint32 {
}
func TestGCD(t *testing.T) {
- tableTest(t, gcdTest, gcdCases, stdEquals, "gcd")
+ tableTest(t, gcdTest, gcdCases, stdEquals[uint32], "gcd")
}
var mtcCases = map[uint32]uint64{
@@ -194,7 +193,7 @@ var mtcCases = map[uint32]uint64{
}
func TestMTC(t *testing.T) {
- tableTest(t, MTC, mtcCases, stdEquals, "MTC")
+ tableTest(t, MTC, mtcCases, stdEquals[uint64], "MTC")
}
var sanCases = map[uint]bool{
@@ -212,7 +211,7 @@ func isSAN(n uint) bool {
}
func TestSAN(t *testing.T) {
- tableTest(t, isSAN, sanCases, stdEquals, "isSAN")
+ tableTest(t, isSAN, sanCases, stdEquals[bool], "isSAN")
}
var expOrdCases = map[uint]bool{
@@ -223,7 +222,8 @@ var expOrdCases = map[uint]bool{
}
func TestExponentsOrdered(t *testing.T) {
- tableTest(t, exponentsOrdered, expOrdCases, stdEquals, "exponentsOrdered")
+ tableTest(t, exponentsOrdered, expOrdCases, stdEquals[bool],
+ "exponentsOrdered")
}
var practicalCases = map[uint]bool{
@@ -237,7 +237,7 @@ var practicalCases = map[uint]bool{
}
func TestPractical(t *testing.T) {
- tableTest(t, practical, practicalCases, stdEquals, "practical")
+ tableTest(t, practical, practicalCases, stdEquals[bool], "practical")
}
var typeCases = map[uint]CompositenessType{
@@ -255,7 +255,7 @@ var typeCases = map[uint]CompositenessType{
}
func TestType(t *testing.T) {
- tableTest(t, Type, typeCases, stdEquals, "Type")
+ tableTest(t, Type, typeCases, stdEquals[CompositenessType], "Type")
}
// ====== DIGIT MAP TESTS ======
@@ -302,7 +302,7 @@ var digitMapCases = map[uint][]DigitType{
}
func TestDigitMap(t *testing.T) {
- tableTest(t, DigitMap, digitMapCases, slices.Equal, "DigitMap")
+ tableTest(t, DigitMap, digitMapCases, sliceEquals[DigitType], "DigitMap")
}
// ensures GetDigitType(d, r) == DigitMap(r)[d];
@@ -383,12 +383,28 @@ func splitTest(a uintPair) uintPair {
}
func TestSplit(t *testing.T) {
- tableTest(t, splitTest, splitCases, stdEquals, "Split")
+ tableTest(t, splitTest, splitCases, stdEquals[uintPair], "Split")
}
// to be used as the equal paramater for tableTest
func stdEquals[T comparable](a, b T) bool { return a == b }
+func mapEquals[K, V comparable](a, b map[K]V) bool {
+ for k, av := range a {
+ bv, ok := b[k]
+ if !ok || bv != av {
+ return false
+ }
+ }
+ for k, bv := range b {
+ av, ok := a[k]
+ if !ok || bv != av {
+ return false
+ }
+ }
+ return true
+}
+
func setEquals[E comparable](a, b []E) bool {
// use maps to simulate sets
// aSet[a] == true means set contains a, false means not
@@ -400,5 +416,19 @@ func setEquals[E comparable](a, b []E) bool {
for _, j := range b {
bSet[j] = true
}
- return maps.Equal(aSet, bSet)
+ return mapEquals(aSet, bSet)
+}
+
+func sliceEquals[E comparable](a, b []E) bool {
+ if len(a) != len(b) {
+ return false
+ }
+
+ for i := 0; i < len(a); i++ {
+ if a[i] != b[i] {
+ return false
+ }
+ }
+
+ return true
}
diff --git a/factors/type.go b/factors/type.go
index 919baef..3e116af 100644
--- a/factors/type.go
+++ b/factors/type.go
@@ -1,7 +1,5 @@
package factors
-import "slices"
-
// The set of all colossaly abundant numbers that are small enough
// to be stored in a uint64.
// The first 15 are also the first 15 superior highly composites.
@@ -69,9 +67,9 @@ const (
// Type determines the [CompositenessType] of a number.
func Type(n uint) CompositenessType {
- if slices.Contains(colossallyAbundantNums[:], uint64(n)) {
+ if contains(colossallyAbundantNums[:], uint64(n)) {
return ColossallyAbundant
- } else if slices.Contains(superabundantNums[:], uint64(n)) {
+ } else if contains(superabundantNums[:], uint64(n)) {
return Superabundant
} else if exponentsOrdered(n) {
return OrderedExponent
@@ -99,7 +97,7 @@ func exponentsOrdered(n uint) bool {
}
pf := PrimeFactorize(n)
- maxPrime := slices.Max(pf.Primes())
+ maxPrime := maxUints(pf.Primes())
for prime, prevPrime := uint(3), uint(2); prime <= maxPrime; {
if pf.Exponent(prime) > pf.Exponent(prevPrime) {
@@ -122,8 +120,7 @@ func practical(n uint) bool {
}
pf := PrimeFactorize(uint(n))
- primes := pf.Primes()
- slices.Sort(primes)
+ primes := sortUints(pf.Primes())
// algorithm from Wikipedia
for i := 0; i < pf.Size()-1; i++ {
diff --git a/go.mod b/go.mod
index 3e9c6d8..d3ad6f5 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
module aphopkins/radix_info
-go 1.21
+go 1.18