p039.scm 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. ;; Integer right triangles
  2. (define-module (euler solved p039))
  3. (use-modules (srfi srfi-43)
  4. (euler utils)
  5. (wak foof-loop))
  6. ;;; Returns (number-of-triangles @perimeter) pair
  7. (define* (solve #:optional (max-perimeter 1001))
  8. "For which perimeter ≤ 1000, is the number of solutions maximised?"
  9. (let* ((right-triangles (right-triangles-under max-perimeter))
  10. (grouped-triangles (group-triangles-by-perimeter right-triangles
  11. max-perimeter)))
  12. (find-largest-triangle-group grouped-triangles)))
  13. (define (right-triangles-under perimeter)
  14. (loop continue ((a 1) (b 1) (triangles '()))
  15. (let ((c (sqrt (+ (* a a) (* b b)))))
  16. (cond
  17. ((> b (ceiling (/ perimeter 2)))
  18. triangles)
  19. ((> (+ a b c) perimeter)
  20. (continue (=> a 1)
  21. (=> b (1+ b))))
  22. ((> a b)
  23. (continue (=> a 1)
  24. (=> b (1+ b))))
  25. ((not (= c (floor c)))
  26. (continue (=> a (1+ a))))
  27. (else (continue (=> a (1+ a))
  28. (=> triangles (cons (list a b c)
  29. triangles))))))))
  30. ;;; returns vector where index is perimeter, and value is list
  31. ;;; of triangles with that perimeter.
  32. (define (group-triangles-by-perimeter right-triangles max-perimeter)
  33. (categorize right-triangles triangle-perimeter max-perimeter))
  34. (define (triangle-perimeter triangle)
  35. (apply + triangle))
  36. (define (find-largest-triangle-group triangle-groups)
  37. (loop ((for group perimeter
  38. (in-vector triangle-groups))
  39. (with curr-group (cons 0 0)
  40. (cons (group-size group) perimeter))
  41. (with largest-group (cons 0 0)
  42. (take-larger-group largest-group
  43. curr-group)))
  44. => largest-group))
  45. (define (group-size group)
  46. (length group))
  47. (define (take-larger-group g1 g2)
  48. (if (>= (car g1) (car g2))
  49. g1 g2))