near-power_factorization_method.sf 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # Date: 03 June 2019
  4. # https://github.com/trizen
  5. # A simple factorization method for numbers close to a perfect power.
  6. # Very effective for numbers of the form:
  7. #
  8. # n^k - 1
  9. #
  10. # where k has many divisors.
  11. func near_power_factorization(n, bound=100) {
  12. var orig = n
  13. func f(r, e, k) {
  14. var factors = gather {
  15. e.divisors.each {|d|
  16. for j in (1, -1) {
  17. var t = (r**d - k*j)
  18. var g = gcd(t, n)
  19. if (g.is_between(2, n-1)) {
  20. while (g.divides(n)) {
  21. n /= g
  22. take(g)
  23. }
  24. }
  25. }
  26. }
  27. }
  28. factors << orig/factors.prod
  29. factors.sort
  30. }
  31. for j in (1..bound) {
  32. for k in (1, -1) {
  33. var u = (k * j**2)
  34. if (is_power(n + u)) {
  35. var r = perfect_root(n + u)
  36. var e = perfect_power(n + u)
  37. return f(r, e, j)
  38. }
  39. }
  40. }
  41. return [n]
  42. }
  43. if (ARGV) {
  44. say near_power_factorization(Num(ARGV[0]))
  45. return 1
  46. }
  47. say near_power_factorization(2**256 - 1) #=> [3, 5, 17, 257, 65537, 4294967297, 18446744073709551617, 340282366920938463463374607431768211457]
  48. say near_power_factorization(10**120 + 1) #=> [100000001, 9999999900000001, 99999999000000009999999900000001, 10000000099999999999999989999999899999999000000000000000100000001]
  49. say near_power_factorization(10**120 - 1) #=> [3, 9, 11, 37, 91, 101, 9091, 9901, 10001, 11111, 90090991, 99009901, 99990001, 109889011, 9999000099990001, 10099989899000101, 100009999999899989999000000010001]
  50. say near_power_factorization(10**120 - 25) #=> [3, 5, 5, 29, 2298850574712643678160919540229885057471264367816091954023, 199999999999999999999999999999999999999999999999999999999999]