1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980 |
- ;; https://projecteuler.net/problem=27
- ;; Number spiral diagonals
- ;; Problem 28
- ;; Starting with the number 1 and moving to the right in a clockwise
- ;; direction a 5 by 5 spiral is formed as follows:
- ;; 21 22 23 24 25
- ;; 20 7 8 9 10
- ;; 19 6 1 2 11
- ;; 18 5 4 3 12
- ;; 17 16 15 14 13
- ;; It can be verified that the sum of the numbers on the diagonals is
- ;; 101.
- ;; What is the sum of the numbers on the diagonals in a 1001 by 1001
- ;; spiral formed in the same way?
- (import
- (except (rnrs base) let-values map)
- (only (guile)
- lambda* λ)
- (contract)
- (prefix (lib math) math:)
- (lib print-utils))
- ;; A square of odd width filled with the numbers from 1 to some
- ;; number, building up from the center as described, will have a
- ;; square number in one of the corners.
- ;; To get the numbers in the other corners, one can substract the
- ;; width of the square reduced by 1 from the previous corner:
- ;; c_1 = w^2 = w^2 - 0(w - 1)
- ;; c_2 = w^2 - 1(w - 1)
- ;; c_3 = w^2 - 2(w - 1)
- ;; c_4 = w^2 - 3(w - 1)
- ;; This results in the following function:
- (define-with-contract corner-num
- (require (integer? width)
- (math:odd? width)
- (integer? corner-ind)
- (and (>= corner-ind 0)
- (<= corner-ind 3)))
- (ensure (integer? <?>))
- (λ (width corner-ind)
- (- (math:square width)
- (* corner-ind
- (- width 1)))))
- (define-with-contract corner-sum
- (require (integer? width)
- (math:odd? width))
- (ensure (integer? <?>)
- (or (= <?> 1)
- (> <?> width)))
- (λ (width)
- (cond
- [(= width 1) 1]
- [else
- (+ (corner-num width 0)
- (corner-num width 1)
- (corner-num width 2)
- (corner-num width 3))])))
- (print "solution:"
- (let iter ([width 1001] [sum 0])
- (cond
- [(= width 1)
- (+ sum (corner-sum width))]
- [else
- (iter (- width 2) (+ sum (corner-sum width)))])))
|