RosettaCodeData/Task/Pythagorean-triples/Racket/pythagorean-triples.rkt
Ingy döt Net 6f050a029e update
2013-06-05 21:47:54 +00:00

45 lines
1.5 KiB
Racket
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#lang racket
#| Euclid's enumeration formula and counting is fast enough for extra credit.
For maximum perimeter P₀, the primitive triples are enumerated by n,m with:
1 ≤ n < m
perimeter P(n, m) ≤ P₀ where P(n, m) = (m² - n²) + 2mn + (m² + n²) = 2m(m+n)
m and n of different parity and coprime.
Since n < m, a simple close non-tight bound on n is P(n, n) < P₀.
For each of these the exact set of m's can be enumerated.
Each primitive triple with perimeter p represents one triple for each kp ≤ P₀,
of which there are floor(P₀/p) k's. |#
(define (P n m) (* 2 m (+ m n)))
(define (number-of-triples P₀)
(for/fold ([primitive 0] [all 0])
([n (in-naturals 1)]
#:break (>= (P n n) P₀))
(for*/fold ([primitive primitive] [all all])
([m (in-naturals (+ n 1))]
#:break (> (P n m) P₀)
#:when (and (odd? (- m n)) (coprime? m n)))
(values (+ primitive 1)
(+ all (quotient P₀ (P n m)))))))
(define (print-results P₀)
(define-values (primitive all) (number-of-triples P₀))
(printf "~a ~a:\n ~a, ~a.\n"
"Number of Pythagorean triples and primitive triples with perimeter ≤"
P₀
all primitive))
(print-results 100)
(time (print-results (* 100 1000 1000)))
#|
Number of Pythagorean triples and primitive triples with perimeter ≤ 100:
17, 7.
Number of Pythagorean triples and primitive triples with perimeter ≤ 100000000:
113236940, 7023027.
cpu time: 11976 real time: 12215 gc time: 2381
|#