p078.scm 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. ;; Coin partitions
  2. ;; Using Euler partition generating function
  3. (define-module (solved p078))
  4. (use-modules (euler macros))
  5. ;; Euler recursive generating function
  6. ;; Pretty messy looking, would be nice to clean up at some point
  7. (define (make-p)
  8. (let ([cache (make-hash-table)])
  9. (hashq-set! cache 0 1)
  10. (rec p
  11. (lambda (n)
  12. (let lp ([k 1] [acc 0])
  13. (cond
  14. [(< n 0) 0]
  15. [(hashq-ref cache n) (hashq-ref cache n)]
  16. [(> k n) (hashq-set! cache n acc) acc]
  17. [else
  18. (lp (1+ k)
  19. (+ acc
  20. (let* ([index1
  21. (- n (* (/ 1 2) k (- (* 3 k) 1)))]
  22. [index2
  23. (- n (* (/ 1 2) k (+ (* 3 k) 1)))]
  24. [p1 (hashq-ref cache index1)]
  25. [p2 (hashq-ref cache index2)])
  26. (* (expt -1 (+ k 1))
  27. (+
  28. (if p1 p1 (p index1))
  29. (if p2 p2 (p index2)))))))]))))))
  30. (define (make-p-mod modulus)
  31. (let ([cache (make-hash-table modulus)])
  32. (hashq-set! cache 0 1)
  33. (rec p
  34. (lambda (n)
  35. (let lp ([k 1] [acc 0])
  36. (cond
  37. [(< n 0) 0]
  38. [(hashq-ref cache n) (hashq-ref cache n)]
  39. [(> k n) (hashq-set! cache n (modulo acc modulus)) (modulo acc modulus)]
  40. [else
  41. (lp (1+ k)
  42. (+ acc
  43. (let* ([index1
  44. (- n (* (/ 1 2) k (- (* 3 k) 1)))]
  45. [index2
  46. (- n (* (/ 1 2) k (+ (* 3 k) 1)))]
  47. [p1 (hashq-ref cache index1)]
  48. [p2 (hashq-ref cache index2)])
  49. (* (expt -1 (+ k 1))
  50. (+
  51. (if p1 p1 (p index1))
  52. (if p2 p2 (p index2)))))))]))))))
  53. (define (modulo-n-v v start)
  54. (let [(p (make-p))]
  55. (let lp ([i start] [curr-val (p start)])
  56. (when (zero? (modulo i 1000)) (display i) (newline))
  57. (if (zero? (modulo curr-val v)) i
  58. (lp (1+ i) (p (1+ i)))))))
  59. ;; Interesting modulus style saving, not sure if it is faster though
  60. (define (modulo-n-v-mod v start)
  61. (let [(p (make-p-mod v))]
  62. (let lp ([i start] [curr-val (p start)])
  63. (when (zero? (modulo i 1000)) (display i) (newline))
  64. (if (zero? curr-val) i
  65. (lp (1+ i) (p (1+ i)))))))