summaryrefslogtreecommitdiff
path: root/factors
diff options
context:
space:
mode:
Diffstat (limited to 'factors')
-rw-r--r--factors/factorize.go26
-rw-r--r--factors/prime_factorization.go18
-rw-r--r--factors/score.go34
-rw-r--r--factors/type.go27
-rw-r--r--factors/uintpow.go6
5 files changed, 57 insertions, 54 deletions
diff --git a/factors/factorize.go b/factors/factorize.go
index 8e82b16..9aa43a7 100644
--- a/factors/factorize.go
+++ b/factors/factorize.go
@@ -10,18 +10,20 @@ func Factors(n uint) []uint {
primeFactorization := PrimeFactorize(n)
factors := []uint{1}
- for p, e := range primeFactorization.exponents {
- next_factors := make([]uint, 0, len(factors)*int(e))
- for _, factor := range factors {
- for i := uint(0); i <= e; i++ {
- multiplier := uint(1)
- for j := uint(0); j < i; j++ {
- multiplier *= p
- }
- next_factors = append(next_factors, factor*multiplier)
- }
- }
- factors = next_factors
+ for prime, exponent := range primeFactorization.exponents {
+ factors = expandFactors(factors, prime, exponent)
}
return factors
}
+
+// expandFactors takes a slice and returns a new slice where every factor
+// f in the original slice is replaced with f, f*p, f*p^2, ..., f*p^e.
+func expandFactors(factors []uint, prime, exponent uint) []uint {
+ nextFactors := make([]uint, 0, len(factors)*int(exponent))
+ for _, factor := range factors {
+ for i := uint(0); i <= exponent; i++ {
+ nextFactors = append(nextFactors, factor*uintpow(prime, i))
+ }
+ }
+ return nextFactors
+}
diff --git a/factors/prime_factorization.go b/factors/prime_factorization.go
index f91a2cf..d9f11e5 100644
--- a/factors/prime_factorization.go
+++ b/factors/prime_factorization.go
@@ -19,17 +19,13 @@ func PrimeFactorize(n uint) PrimeFactorization {
return PrimeFactorization{map[uint]uint{0: 1}}
}
- unfactored := n // number with all found factors removed (divided)
+ unfactored := n
exponents := make(map[uint]uint)
- // try each factor starting at 2
- // if unfactored is divisible divide out until it isn't
- for f := uint(2); f*f <= unfactored; {
- if unfactored%f == 0 {
- unfactored /= f
- exponents[f] += 1
- } else {
- f += 1
+ for possibleFactor := uint(2); possibleFactor*possibleFactor <= unfactored; possibleFactor++ {
+ for unfactored%possibleFactor == 0 {
+ unfactored /= possibleFactor
+ exponents[possibleFactor] += 1
}
}
@@ -90,3 +86,7 @@ func (factors PrimeFactorization) String() string {
}
return strings.Join(parts, " × ")
}
+
+func isPrime(p uint) bool {
+ return p > 1 && PrimeFactorize(p).Exponent(p) == 1
+}
diff --git a/factors/score.go b/factors/score.go
index 9288e8f..0759a74 100644
--- a/factors/score.go
+++ b/factors/score.go
@@ -36,26 +36,20 @@ func Score(n uint) float64 {
// Also known as 2345 Rank.
func BasicRank(n uint) string {
var firstRank, secondRank string
- if n%2 == 0 {
- if n%3 == 0 {
- if n%4 == 0 {
- firstRank = "A"
- } else {
- firstRank = "B"
- }
- } else {
- if n%4 == 0 {
- firstRank = "C"
- } else {
- firstRank = "D"
- }
- }
- } else {
- if n%3 == 0 {
- firstRank = "E"
- } else {
- firstRank = "F"
- }
+
+ switch uint(0) {
+ case n % 12:
+ firstRank = "A"
+ case n % 6:
+ firstRank = "B"
+ case n % 4:
+ firstRank = "C"
+ case n % 2:
+ firstRank = "D"
+ case n % 3:
+ firstRank = "E"
+ default:
+ firstRank = "F"
}
switch n % 5 {
diff --git a/factors/type.go b/factors/type.go
index 7a0f877..b58d01c 100644
--- a/factors/type.go
+++ b/factors/type.go
@@ -76,6 +76,15 @@ func Type(n uint) NumberType {
}
}
+// invariant: p must be odd and >= 3
+func nextPrime(p uint) uint {
+ possiblePrime := p + 2
+ for !isPrime(possiblePrime) {
+ possiblePrime += 2
+ }
+ return possiblePrime
+}
+
func exponentsOrdered(n uint) bool {
if n <= 2 {
return true
@@ -83,19 +92,17 @@ func exponentsOrdered(n uint) bool {
return false
}
- pf := PrimeFactorize(uint(n))
+ pf := PrimeFactorize(n)
maxPrime := slices.Max(pf.Primes())
- lastPrime := uint(2)
- for p := uint(3); p <= maxPrime; p += 2 {
- if PrimeFactorize(p).Exponent(p) == 1 {
- if pf.Exponent(p) > pf.Exponent(lastPrime) {
- return false
- } else if pf.Exponent(p) == 0 && p < maxPrime {
- return false
- }
- lastPrime = p
+ for prime, prevPrime := uint(3), uint(2); prime <= maxPrime; {
+ if pf.Exponent(prime) > pf.Exponent(prevPrime) {
+ return false
+ } else if pf.Exponent(prime) == 0 && prime < maxPrime {
+ return false
}
+
+ prime, prevPrime = nextPrime(prime), prime
}
return true
diff --git a/factors/uintpow.go b/factors/uintpow.go
index 85db67f..50bfe9d 100644
--- a/factors/uintpow.go
+++ b/factors/uintpow.go
@@ -1,9 +1,9 @@
package factors
-func uintpow(a, b uint) uint {
+func uintpow(base, exponent uint) uint {
result := uint(1)
- for i := uint(0); i < b; i++ {
- result *= a
+ for i := uint(0); i < exponent; i++ {
+ result *= base
}
return result
}