carmichael_generation_erdos_method.sf 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. #!/usr/bin/ruby
  2. # Erdos construction method for Carmichael numbers:
  3. # 1. Choose an integer L with many prime factors.
  4. # 2. Let P be the set of primes d+1, where d|L and d+1 does not divide L.
  5. # 3. Find a subset S of P such that prod(S) == 1 (mod L). Then prod(S) is a Carmichael number.
  6. # Alternatively:
  7. # 3. Find a subset S of P such that prod(S) == prod(P) (mod L). Then prod(P) / prod(S) is a Carmichael number.
  8. func lambda_primes(L) {
  9. L.divisors.map { .inc }.grep { .is_odd && .is_coprime(L) && .is_prime }
  10. }
  11. func method_1(L, callback) { # small numbers first
  12. var P = lambda_primes(L)
  13. for k in (3..P.len) {
  14. P.combinations(k, {|*S|
  15. if (S.prodmod(L) == 1) {
  16. callback(S.prod)
  17. }
  18. })
  19. }
  20. return nil
  21. }
  22. func method_2(L, callback) { # large numbers first
  23. var P = lambda_primes(L)
  24. var T = P.prod
  25. var B = T%L
  26. for k in (1 .. (P.len-3)) {
  27. P.combinations(k, {|*S|
  28. if (S.prodmod(L) == B) {
  29. var c = idiv(T, S.prod)
  30. callback(c) if (c > 1)
  31. }
  32. })
  33. }
  34. return nil
  35. }
  36. method_1(720, {|c| say c })
  37. method_2(720, {|c| say c })
  38. __END__
  39. 15841
  40. 115921
  41. 488881
  42. 41041
  43. 172081
  44. 5310721
  45. 12262321
  46. 16778881
  47. 18162001
  48. 76595761
  49. 609865201
  50. 133205761
  51. 561777121
  52. 1836304561
  53. 832060801
  54. 1932608161
  55. 20064165121
  56. 84127131361
  57. 354725143201
  58. 1487328704641
  59. 3305455474321
  60. 1945024664401
  61. 2110112460001
  62. 8879057210881
  63. 65121765643441
  64. 30614445878401