imprimitive_carmichael_coin_change.sf 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #!/usr/bin/ruby
  2. # Generate imprimitive Carmichael numbers with n prime factors.
  3. func is_imprimitive(n) {
  4. n.factor.gcd_by { .dec }**2 > lambda(n)
  5. }
  6. var denominations = []
  7. func change(m, pos=0, solution=[]) {
  8. if (solution.len >= 2) {
  9. if (solution[-1] / solution[0] > 40) {
  10. #say '# here'
  11. return nil
  12. }
  13. }
  14. if (solution.len == m) {
  15. with (solution.prod) {|C|
  16. if (C.is_carmichael) {
  17. say C
  18. say "# Imprimitive: #{C}" if is_imprimitive(C)
  19. }
  20. }
  21. return nil
  22. }
  23. if (solution.len > m) {
  24. return nil
  25. }
  26. if (pos > denominations.end) {
  27. return nil;
  28. }
  29. change(m, pos + 1, solution);
  30. change(m, pos + 1, [solution..., denominations[pos]]);
  31. }
  32. func generate_imprimitive(p, m) {
  33. for z in (2..100) {
  34. var arr = []
  35. for k in (1 .. 2.sqrt**z) {
  36. k.is_smooth(5) || next
  37. #next if (2*5 > 40)
  38. var r = (2*k*p + 1)
  39. if (r.is_prime && (r.dec.gpf == p)) {
  40. arr << r
  41. }
  42. }
  43. var t = binomial(arr.len, m)
  44. t >= m || next
  45. t < 1e6 || break
  46. arr = arr.last(19448)
  47. var count = 0
  48. say "# Combinations: #{t}"
  49. denominations = arr
  50. change(m)
  51. #~ arr.combinations(m, {|*a|
  52. #~ with (a.prod) { |C|
  53. #~ break if (C > 325533792014488126487416882038879701391121)
  54. #~ #break if (C.gpf / C.lpf > 40)
  55. #~ if (C.is_carmichael) {
  56. #~ say C
  57. #~ say "# Imprimitive with p = #{p}: #{C}" if is_imprimitive(C)
  58. #~ }
  59. #~ }
  60. #~ #break if (++count > 1e5)
  61. #~ })
  62. }
  63. }
  64. for p in (primes(73..457)) {
  65. say "# p = #{p}"
  66. generate_imprimitive(p,10)
  67. }