Thanks for more food for thought.<div><br></div><div>Cristian, I really like the form of your solution with the answer being produced at the bottom. You also taught me about stop-before and stop-after. Very nice.</div><div>
<br></div><div>Maxim, Thanks for bringing up for*/set. Your solution is elegant, but unfortunately is relatively slow because it calculates all the numbers and so doesn't scale very well with a and b (try upper = 1000).</div>
<div><br></div><div>Here's Cristian's code scaled to 400. It runs in under .1 seconds:</div><div><br></div><div><div>(define (euler29d)</div><div> (- (sqr 999)</div><div> (for/sum ([base '(2 3 5 6 7 10 11 12 13 14 15 17 18 19 20)])</div>
<div> (define lst </div><div> (for*/list ([exp (stop-before (in-naturals 1) (ë (exp) (> (expt base exp) 400)))]</div><div> [i (in-range 2 401)]) (* i exp)))</div><div>
(- (length lst) (length (remove-duplicates lst))))))</div><br><div class="gmail_quote">On Wed, Apr 18, 2012 at 5:33 AM, Maxim Romashchenko <span dir="ltr"><<a href="mailto:max@anahoret.com">max@anahoret.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">What about for*/set ?<br>
<br>
#lang racket<br>
(require racket/set)<br>
(define (generate-powers lower upper)<br>
(for*/set ([a (in-range lower (add1 upper))]<br>
[b (in-range lower (add1 upper))])<br>
(expt a b)))<br>
(set-count (generate-powers 2 5))<br>
(set-count (generate-powers 2 100))<br>
<br>
Best regards, Maxim.<div class="HOEnZb"><div class="h5"><br>
<br>
<br>
On 2012-04-17 21:01, Cristian Esquivias wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I used Project Euler to try out new languages as well. Here was my<br>
attempt at Problem 29 for reference.<br>
<br>
(define (prob29 a b)<br>
(set-count<br>
(for*/fold<br>
([nums (set)])<br>
([i (in-range 2 (add1 a))]<br>
[j (in-range 2 (add1 b))])<br>
(values (set-add nums (expt i j))))))<br>
<br>
<br>
- Cristian<br>
<br>
On Tue, Apr 17, 2012 at 9:54 AM, Matthew Flatt<<a href="mailto:mflatt@cs.utah.edu" target="_blank">mflatt@cs.utah.edu</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Blindly refactoring the code, I'd use `for/fold' and add a `lst'<br>
accumulator to `loop':<br>
<br>
(define (euler29c)<br>
; calculate 99^2 - duplicates<br>
(- (sqr 99)<br>
(for/sum ([d '(2 3 5 6 7 10)])<br>
(let loop ([lst '()] [exp 1])<br>
(if (> (expt d exp) 100)<br>
(- (length lst) (length (remove-duplicates lst)))<br>
(loop (for/fold ([lst lst]) ([i (in-range 2 101)])<br>
(cons (* i exp) lst))<br>
(add1 exp)))))))<br>
<br>
At Tue, 17 Apr 2012 09:45:50 -0700, Joe Gilray wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi,<br>
<br>
To continue our conversation about creating idiomatic Racket code, here is<br>
some code I wrote last night to solve <a href="http://projecteuler.net" target="_blank">projecteuler.net</a> problem #29:<br>
<br>
(define (euler29a)<br>
; calculate 99^2 - duplicates<br>
(- (sqr 99)<br>
(for/sum ([d '(2 3 5 6 7 10)])<br>
(let ([lst '()])<br>
(let loop ([exp 1])<br>
(if (> (expt d exp) 100) (- (length lst) (length<br>
(remove-duplicates lst)))<br>
(begin<br>
(for ([i (in-range 2 101)]) (set! lst (cons (* i<br>
exp) lst)))<br>
(loop (add1 exp)))))))))<br>
<br>
It's fast (it avoids calculating a bunch of huge numbers), it gives the<br>
correct answer, so what's not to love?!<br>
<br>
Well, it starts off OK, but my eye stumbles over the following:<br>
<br>
1) predeclaring lst and accessing it twice, related to each other<br>
2) ugly single parameter named-let loop<br>
3) ugly "begin" - not a big deal, but I just dislike when having to use<br>
begin<br>
4) use of set!<br>
<br>
Here is a quick rewrite:<br>
<br>
(define (euler29b)<br>
; calculate 99^2 - duplicates<br>
(- (sqr 99)<br>
(for/sum ([d '(2 3 5 6 7 10)])<br>
(let ([lst '()])<br>
(do ([exp 1 (add1 exp)])<br>
((> (expt d exp) 100) (- (length lst) (length<br>
(remove-duplicates lst))))<br>
(for ([i (in-range 2 101)]) (set! lst (cons (* i exp)<br>
lst))))))))<br>
<br>
It solves #2 and #3 above, but it is still fundamentally clunky.<br>
<br>
Can someone help and teach us all some tricks? My instincts say it should<br>
be possible to use append-map, for/list and/or foldl to build a list of the<br>
duplicates then simply count them in the for/sum loop, but am still unable<br>
to do it.<br>
<br>
Thanks,<br>
-Joe<br>
____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/<u></u>users</a><br>
</blockquote>
____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/<u></u>users</a><br>
</blockquote>
<br>
____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/<u></u>users</a><br>
</blockquote>
____________________<br>
Racket Users list:<br>
<a href="http://lists.racket-lang.org/users" target="_blank">http://lists.racket-lang.org/<u></u>users</a><br>
</div></div></blockquote></div><br></div>