Hi again Rodolfo, After a some mods, I ran several trials with n = 10000 on my ancient laptop and got the following results:
(define (pythagorean-triple n) (define a-limit (ceiling (/ n 3))) (let loop-ab ([a 1] [b 2]) (define c (- n a b)) (cond [(right-triangle? a b c) (list a b c)] [(>= a a-limit) '()] [(<= c b) (loop-ab (add1 a) (+ a 2))] [else (loop-ab a (add1 b))]))) Ave cpu time = 3.90 seconds (note that trying to limit b slowed down the performance considerably, but pre-defining a-limit helped a little compared to not limiting a at all) (define (pythagorean-triple2 n) (for*/first ([a (in-range 1 (ceiling (/ n 3)))] [b (in-range (add1 a) (ceiling (/ (- n a) 2)))] [c (in-value (- n a b))] #:when (and (< b c) (right-triangle? a b c))) (list a b c))) Ave cpu time = 5.25 seconds (pre-defining a-limit didn't improve performance like it did above) (define (pythagorean-triple3 n) (for*/or ([a (in-range 1 n)] [b (in-range a n)] #:when (< (* 2 b) (- n a))) (define c (- n a b)) (and (right-triangle? a b c) (list a b c)))) Ave cpu time = 4.90 seconds (define (pythagorean-triple4 n) (for*/or ([a (in-range 1 (ceiling (/ n 3)))] [b (in-range (add1 a) (ceiling (/ (- n a) 2)))]) (define c (- n a b)) (and (right-triangle? a b c) (list a b c)))) Ave cpu time = 2.50 seconds (!!, note that pre-defining a-limit didn't improve performance here either) I'm learning a lot from these examples. I'd love to see other idioms as well. Thanks, -Joe On Mon, Mar 19, 2012 at 12:44 AM, Rodolfo Carvalho <rhcarva...@gmail.com>wrote: > On Mon, Mar 19, 2012 at 04:35, Joe Gilray <jgil...@gmail.com> wrote: > >> Thanks Rodolfo and Eli for the education, very elegant solutions. >> >> I really like the clever use of the "(and (right-triangle? a b c) (list a >> b c))))" idiom. >> >> I had to look up in-value... unfortunately the manual is a bit sparse >> there, but I got the gift by running some examples... thanks. >> >> After going "D'oh" about the infinite loop, here is the code I ended up >> with: >> >> (define (pythagorean-triple n) >> (let loop-ab ([a 1] [b 2]) >> (define c (- n a b)) >> (cond [(>= a n) '()] >> [(<= c b) (loop-ab (add1 a) (+ a 2))] >> [(right-triangle? a b c) (list a b c)] >> [else (loop-ab a (add1 b))]))) >> >> I noticed that the sequence-based solutions are quite a bit slower than >> the code above probably because they don't short-cut on (<= c b), is there >> an elegant way to speed them up? >> >> > Before you asked I wrote this: > > ; by Rodolfo Carvalho > (define (pythagorean-triple/alt n) > (for*/first ([a (in-range 1 (ceiling (/ n 3)))] > [b (in-range (add1 a) (ceiling (/ (- n a) 2)))] > [c (in-value (- n a b))] > #:when (and (< b c) > (right-triangle? a b c))) > (list a b c))) > > > ; by Eli on the mailing list, modified by Rodolfo > (define (pythagorean-triple/alt2 n) > (for*/or ([a (in-range 1 n)] > [b (in-range (add1 a) n)]) ; start from `a+1' instead of `a'. > (define c (- n a b)) > (and (< b c) (right-triangle? a b c) (list a b c)))) ; added `(< b c)' > check. > > > > And counted how many times they call right-triangle -- the same number of > times. > Indeed your (first) solution with let loops seems slightly faster, but not > by a significant margin in my experiments. > > I didn't take the time to analyze it much, but looking at the code > expansion using the Macro Stepper suggested that the for macros generate a > lot more code to be executed than the nested lets. > > > []'s > > Rodolfo Carvalho > > > >
____________________ Racket Users list: http://lists.racket-lang.org/users