diff options
| author | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2023-09-19 11:10:48 -0500 |
|---|---|---|
| committer | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2023-09-19 11:10:48 -0500 |
| commit | 165e55184e79553c74b9c9056fd46f1b37a2b5d9 (patch) | |
| tree | 1bd1f92024708da0e381d7db4eecc2500bbb0829 /factors | |
| parent | 23cc07dd1655df05f6967ce848169ab4c658e707 (diff) | |
factors: refactor code to improve readability
Diffstat (limited to 'factors')
| -rw-r--r-- | factors/factorize.go | 26 | ||||
| -rw-r--r-- | factors/prime_factorization.go | 18 | ||||
| -rw-r--r-- | factors/score.go | 34 | ||||
| -rw-r--r-- | factors/type.go | 27 | ||||
| -rw-r--r-- | factors/uintpow.go | 6 |
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 } |
