solution.scm 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. ;; https://projecteuler.net/problem=27
  2. ;; Number spiral diagonals
  3. ;; Problem 28
  4. ;; Starting with the number 1 and moving to the right in a clockwise
  5. ;; direction a 5 by 5 spiral is formed as follows:
  6. ;; 21 22 23 24 25
  7. ;; 20 7 8 9 10
  8. ;; 19 6 1 2 11
  9. ;; 18 5 4 3 12
  10. ;; 17 16 15 14 13
  11. ;; It can be verified that the sum of the numbers on the diagonals is
  12. ;; 101.
  13. ;; What is the sum of the numbers on the diagonals in a 1001 by 1001
  14. ;; spiral formed in the same way?
  15. (import
  16. (except (rnrs base) let-values map)
  17. (only (guile)
  18. lambda* λ)
  19. (contract)
  20. (prefix (lib math) math:)
  21. (lib print-utils))
  22. ;; A square of odd width filled with the numbers from 1 to some
  23. ;; number, building up from the center as described, will have a
  24. ;; square number in one of the corners.
  25. ;; To get the numbers in the other corners, one can substract the
  26. ;; width of the square reduced by 1 from the previous corner:
  27. ;; c_1 = w^2 = w^2 - 0(w - 1)
  28. ;; c_2 = w^2 - 1(w - 1)
  29. ;; c_3 = w^2 - 2(w - 1)
  30. ;; c_4 = w^2 - 3(w - 1)
  31. ;; This results in the following function:
  32. (define-with-contract corner-num
  33. (require (integer? width)
  34. (math:odd? width)
  35. (integer? corner-ind)
  36. (and (>= corner-ind 0)
  37. (<= corner-ind 3)))
  38. (ensure (integer? <?>))
  39. (λ (width corner-ind)
  40. (- (math:square width)
  41. (* corner-ind
  42. (- width 1)))))
  43. (define-with-contract corner-sum
  44. (require (integer? width)
  45. (math:odd? width))
  46. (ensure (integer? <?>)
  47. (or (= <?> 1)
  48. (> <?> width)))
  49. (λ (width)
  50. (cond
  51. [(= width 1) 1]
  52. [else
  53. (+ (corner-num width 0)
  54. (corner-num width 1)
  55. (corner-num width 2)
  56. (corner-num width 3))])))
  57. (print "solution:"
  58. (let iter ([width 1001] [sum 0])
  59. (cond
  60. [(= width 1)
  61. (+ sum (corner-sum width))]
  62. [else
  63. (iter (- width 2) (+ sum (corner-sum width)))])))