solution.scm 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. ;; https://projecteuler.net/problem=6
  2. ;; Sum square difference
  3. ;; Problem 6
  4. ;; The sum of the squares of the first ten natural numbers
  5. ;; is, $$1^2 + 2^2 + ... + 10^2 = 385$$
  6. ;; The square of the sum of the first ten natural numbers
  7. ;; is, $$(1 + 2 + ... + 10)^2 = 55^2 = 3025$$
  8. ;; Hence the difference between the sum of the squares of
  9. ;; the first ten natural numbers and the square of the sum
  10. ;; is $3025 - 385 = 2640$.
  11. ;; Find the difference between the sum of the squares of the
  12. ;; first one hundred natural numbers and the square of the
  13. ;; sum.
  14. (import
  15. (except (rnrs base) let-values)
  16. (only (guile) lambda* λ)
  17. (srfi srfi-1)
  18. (contract)
  19. (lib segment)
  20. (lib parallelism)
  21. (prefix (lib math) math:))
  22. (define-with-contract sum-of-squares
  23. (require (>= start 0)
  24. (>= end 0)
  25. (< start end)
  26. (integer? start)
  27. (integer? end))
  28. (ensure (> <?> 0)
  29. (integer? <?>))
  30. (λ (start end)
  31. (let iter ([sum 0] [num start])
  32. (cond
  33. [(= num end)
  34. (+ sum (math:square num))]
  35. [else
  36. (iter (+ sum (math:square num))
  37. (+ num 1))]))))
  38. (define get-sum-of-squares
  39. (λ (segments)
  40. (run-in-parallel segments
  41. ;; Calculate the sum of squares
  42. ;; for each segment.
  43. (λ (seg)
  44. (sum-of-squares (segment-start seg)
  45. (segment-end seg)))
  46. ;; Sum up all the sums.
  47. (λ (acc current)
  48. (+ acc current))
  49. ;; Sum starts with 0.
  50. 0)))
  51. (define get-square-of-sums
  52. (λ (segments)
  53. ;; Calculate square of sums.
  54. (math:square
  55. (run-in-parallel segments
  56. ;; Calculate the sum for each
  57. ;; segment.
  58. (λ (seg)
  59. (math:range-sum (segment-start seg)
  60. (segment-end seg)))
  61. ;; Sum all segment sums.
  62. (λ (acc current)
  63. (+ acc current))
  64. ;; Sum starts with 0.
  65. 0))))
  66. (define-with-contract diff-sum-sq-sq-sum
  67. (require (>= start 0)
  68. (>= end 0)
  69. (< start end))
  70. (ensure (> <?> 0))
  71. (λ (start end)
  72. ;; First split the range into segments.
  73. (let ([segment-count 8])
  74. (let ([segments (segment start end segment-count)])
  75. (abs
  76. (- (get-sum-of-squares segments)
  77. (get-square-of-sums segments)))))))
  78. (let* ([start 1]
  79. [end (expt 10 2)])
  80. (display
  81. (simple-format
  82. #f "~a\n"
  83. (diff-sum-sq-sq-sum start end))))