diff options
| author | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2023-09-07 11:38:32 -0500 |
|---|---|---|
| committer | Adrien Hopkins <adrien.p.hopkins@gmail.com> | 2023-09-07 11:42:21 -0500 |
| commit | 7fa8cf9666cd3427dd078bb4a5fdb9fa30c94b09 (patch) | |
| tree | 0ff7b1349bdf132702b05753af2f0d8044d19a5e /factors | |
| parent | 73a5964d665920eee6dd68ae78bb3aeec18b1bde (diff) | |
Calculate type of all radices without -l
factors.Type now supports all numbers; I have used lookup arrays instead
of determining whether a number is SAN or not. There are only 117
elements to store, and this makes the algorithm Θ(1), so it's an
improvement.
Also, I have changed the size of some integer values to correspond to
this change - they now indicate the size of numbers they can accept.
The only outputs that are hidden for large radices are:
- The digit map, which goes up to 36 because I don't have any more
digits beyond that point
- The multiplication table complexity, which is estimated above 2^16
(for performance), and can optionally be extended to 2^32 (above this,
the output could overflow a uint64).
Diffstat (limited to 'factors')
| -rw-r--r-- | factors/factors_test.go | 18 | ||||
| -rw-r--r-- | factors/mtc.go | 8 | ||||
| -rw-r--r-- | factors/type.go | 76 |
3 files changed, 54 insertions, 48 deletions
diff --git a/factors/factors_test.go b/factors/factors_test.go index 745fd2c..dec651c 100644 --- a/factors/factors_test.go +++ b/factors/factors_test.go @@ -115,7 +115,7 @@ func TestBasicRank(t *testing.T) { tableTest(t, BasicRank, basicRankCases, stdEquals, "BasicRank") } -var gcdCases = map[struct{ a, b uint64 }]uint64{ +var gcdCases = map[struct{ a, b uint32 }]uint32{ {0, 0}: 0, {1, 1}: 1, {6, 10}: 2, {10, 6}: 2, {12, 20}: 4, {20, 12}: 4, @@ -124,7 +124,7 @@ var gcdCases = map[struct{ a, b uint64 }]uint64{ } // a version of gcd() for testing purposes -func gcdTest(c struct{ a, b uint64 }) uint64 { +func gcdTest(c struct{ a, b uint32 }) uint32 { return gcd(c.a, c.b) } @@ -132,7 +132,7 @@ func TestGCD(t *testing.T) { tableTest(t, gcdTest, gcdCases, stdEquals, "gcd") } -var mtcCases = map[uint64]uint64{ +var mtcCases = map[uint32]uint64{ 2: 0, 3: 0, 4: 2, 5: 10, 6: 8, 7: 28, 8: 26, 9: 42, 10: 42, 11: 88, 12: 52, 13: 130, 14: 100, 15: 116, 16: 138, 18: 146, @@ -145,7 +145,7 @@ func TestMTC(t *testing.T) { tableTest(t, MTC, mtcCases, stdEquals, "MTC") } -var sanCases = map[uint32]bool{ +var sanCases = map[uint]bool{ 1: true, 2: true, 4: true, 6: true, 12: true, 24: true, 36: true, 48: true, 60: true, 120: true, 180: true, 240: true, 360: true, 720: true, 840: true, 1260: true, 1680: true, 2520: true, 5040: true, @@ -155,11 +155,15 @@ var sanCases = map[uint32]bool{ 1728: false, 4000: false, 6912: false, 7560: false, } +func isSAN(n uint) bool { + return Type(n) >= Superabundant +} + func TestSAN(t *testing.T) { tableTest(t, isSAN, sanCases, stdEquals, "isSAN") } -var expOrdCases = map[uint32]bool{ +var expOrdCases = map[uint]bool{ 1: true, 2: true, 4: true, 5: false, 6: true, 12: true, 18: false, 20: false, 30: true, 44: false, 60: true, 70: false, 96: true, 101: false, 120: true, 144: true, 770: false, 6912: true, 10010: false, @@ -169,7 +173,7 @@ func TestExponentsOrdered(t *testing.T) { tableTest(t, exponentsOrdered, expOrdCases, stdEquals, "exponentsOrdered") } -var practicalCases = map[uint32]bool{ +var practicalCases = map[uint]bool{ 1: true, 2: true, 4: true, 6: true, 8: true, 12: true, 16: true, 18: true, 20: true, 24: true, 28: true, 30: true, 32: true, 36: true, 48: true, 60: true, 120: true, 180: true, 240: true, 360: true, @@ -183,7 +187,7 @@ func TestPractical(t *testing.T) { tableTest(t, practical, practicalCases, stdEquals, "practical") } -var typeCases = map[uint32]NumberType{ +var typeCases = map[uint]NumberType{ 2: ColossallyAbundant, 3: NotPractical, 4: Superabundant, 6: ColossallyAbundant, 8: OrderedExponent, 10: NotPractical, 12: ColossallyAbundant, 18: Practical, 20: Practical, 24: Superabundant, diff --git a/factors/mtc.go b/factors/mtc.go index 655124c..024391e 100644 --- a/factors/mtc.go +++ b/factors/mtc.go @@ -3,15 +3,15 @@ package factors // MTC returns the multiplication table complexity of a radix n. // This is an estimate of how difficult it is to learn a radix's // multiplication table. -func MTC(n uint64) uint64 { +func MTC(n uint32) uint64 { mtc := uint64(0) - for i := uint64(2); i <= n-2; i++ { - mtc += n / gcd(i, n) + for i := uint32(2); i <= n-2; i++ { + mtc += uint64(n / gcd(i, n)) } return mtc } -func gcd(a, b uint64) uint64 { +func gcd(a, b uint32) uint32 { for b > 0 { a, b = b, a%b } diff --git a/factors/type.go b/factors/type.go index 4b58a1d..7a0f877 100644 --- a/factors/type.go +++ b/factors/type.go @@ -3,14 +3,41 @@ package factors import "slices" // The set of all colossaly abundant numbers that are small enough -// to be stored in a uint32. -// These numbers are also the first 14 superior highly composites. -var colossallyAbundantNums = [...]uint32{ +// to be stored in a uint64. +// The first 15 are also the first 15 superior highly composites. +// source: https://oeis.org/A004490 +var colossallyAbundantNums = [...]uint64{ 2, 6, 12, 60, 120, 360, 2520, 5040, 55440, - 720720, 1441440, 4324320, 21621600, 367567200} - -// A cache containing all superabundant numbers up to a certain value -var sanCache = []uint32{1} + 720720, 1441440, 4324320, 21621600, 367567200, 6983776800, + 160626866400, 321253732800, 9316358251200, 288807105787200, + 2021649740510400, 6064949221531200, 224403121196654400, + 9200527969062830400} + +// source: https://oeis.org/A004394 +var superabundantNums = [...]uint64{ + 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680, + 2520, 5040, 10080, 15120, 25200, 27720, 55440, 110880, 166320, 277200, + 332640, 554400, 665280, 720720, 1441440, 2162160, 3603600, 4324320, + 7207200, 8648640, 10810800, 21621600, 36756720, 61261200, 73513440, + 122522400, 147026880, 183783600, 367567200, 698377680, 735134400, + 1102701600, 1163962800, 1396755360, 2327925600, 2793510720, 3491888400, + 6983776800, 13967553600, 20951330400, 27935107200, 41902660800, + 48886437600, 80313433200, 160626866400, 321253732800, 481880599200, + 642507465600, 963761198400, 1124388064800, 1927522396800, 2248776129600, + 3373164194400, 4497552259200, 4658179125600, 6746328388800, 9316358251200, + 13974537376800, 18632716502400, 27949074753600, 32607253879200, + 55898149507200, 65214507758400, 97821761637600, 130429015516800, + 144403552893600, 195643523275200, 288807105787200, 433210658680800, + 577614211574400, 866421317361600, 1010824870255200, 1732842634723200, + 2021649740510400, 3032474610765600, 4043299481020800, 6064949221531200, + 10685862914126400, 12129898443062400, 21371725828252800, 24259796886124800, + 30324746107656000, 32057588742379200, 37400520199442400, 64115177484758400, + 74801040398884800, 112201560598327200, 149602080797769600, + 224403121196654400, 448806242393308800, 897612484786617600, + 1122015605983272000, 1346418727179926400, 1533421328177138400, + 2244031211966544000, 3066842656354276800, 4600263984531415200, + 6133685312708553600, 9200527969062830400, 18401055938125660800, +} // A type of number (as determined by its factors) type NumberType byte @@ -35,10 +62,10 @@ const ( NotPractical NumberType = 0x40 ) -func Type(n uint32) NumberType { - if slices.Contains(colossallyAbundantNums[:], n) { +func Type(n uint) NumberType { + if slices.Contains(colossallyAbundantNums[:], uint64(n)) { return ColossallyAbundant - } else if isSAN(n) { + } else if slices.Contains(superabundantNums[:], uint64(n)) { return Superabundant } else if exponentsOrdered(n) { return OrderedExponent @@ -49,32 +76,7 @@ func Type(n uint32) NumberType { } } -func isSAN(n uint32) bool { - if n <= 2 { - return true - } else if n%4 != 0 && n%6 != 0 { - return false - } - - cachedMax := sanCache[len(sanCache)-1] - maxScore := Score(uint(cachedMax)) - nScore := Score(uint(n)) - for i := cachedMax + 1; i <= n; i++ { - iScore := Score(uint(i)) - if iScore > maxScore { - sanCache = append(sanCache, i) - maxScore = iScore - if maxScore > nScore { - return false - } - } - } - - _, found := slices.BinarySearch(sanCache, n) - return found -} - -func exponentsOrdered(n uint32) bool { +func exponentsOrdered(n uint) bool { if n <= 2 { return true } else if n%4 != 0 && n%6 != 0 { @@ -99,7 +101,7 @@ func exponentsOrdered(n uint32) bool { return true } -func practical(n uint32) bool { +func practical(n uint) bool { if n <= 2 { return true } else if n%4 != 0 && n%6 != 0 { |
