[racket] making Racket code more idiomatic

From: Joe Gilray (jgilray at gmail.com)
Date: Tue Apr 17 15:54:04 EDT 2012

Hi Guys.

Thanks for the education on for/fold and for*/fold.

Cristian, your solution is very elegant, thanks, but unfortunately it does
generate all the numbers so is relatively slow and won't scale too well
with a and b.

-Joe

On Tue, Apr 17, 2012 at 11:01 AM, Cristian Esquivias <
cristian.esquivias at gmail.com> wrote:

> I used Project Euler to try out new languages as well. Here was my
> attempt at Problem 29 for reference.
>
> (define (prob29 a b)
>  (set-count
>   (for*/fold
>       ([nums (set)])
>     ([i (in-range 2 (add1 a))]
>      [j (in-range 2 (add1 b))])
>     (values (set-add nums (expt i j))))))
>
>
> - Cristian
>
> On Tue, Apr 17, 2012 at 9:54 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> > Blindly refactoring the code, I'd use `for/fold' and add a `lst'
> > accumulator to `loop':
> >
> > (define (euler29c)
> >  ; calculate 99^2 - duplicates
> >  (- (sqr 99)
> >     (for/sum ([d '(2 3 5 6 7 10)])
> >       (let loop ([lst '()] [exp 1])
> >         (if (> (expt d exp) 100)
> >             (- (length lst) (length (remove-duplicates lst)))
> >             (loop (for/fold ([lst lst]) ([i (in-range 2 101)])
> >                     (cons (* i exp) lst))
> >                   (add1 exp)))))))
> >
> > At Tue, 17 Apr 2012 09:45:50 -0700, Joe Gilray wrote:
> >> Hi,
> >>
> >> To continue our conversation about creating idiomatic Racket code, here
> is
> >> some code I wrote last night to solve projecteuler.net problem #29:
> >>
> >> (define (euler29a)
> >>   ; calculate 99^2 - duplicates
> >>   (- (sqr 99)
> >>      (for/sum ([d '(2 3 5 6 7 10)])
> >>               (let ([lst '()])
> >>                 (let loop ([exp 1])
> >>                   (if (> (expt d exp) 100) (- (length lst) (length
> >> (remove-duplicates lst)))
> >>                       (begin
> >>                         (for ([i (in-range 2 101)]) (set! lst (cons (* i
> >> exp) lst)))
> >>                         (loop (add1 exp)))))))))
> >>
> >> It's fast (it avoids calculating a bunch of huge numbers), it gives the
> >> correct answer, so what's not to love?!
> >>
> >> Well, it starts off OK, but my eye stumbles over the following:
> >>
> >> 1) predeclaring lst and accessing it twice, related to each other
> >> 2) ugly single parameter named-let loop
> >> 3) ugly "begin" - not a big deal, but I just dislike when having to use
> >> begin
> >> 4) use of set!
> >>
> >> Here is a quick rewrite:
> >>
> >> (define (euler29b)
> >>   ; calculate 99^2 - duplicates
> >>   (- (sqr 99)
> >>      (for/sum ([d '(2 3 5 6 7 10)])
> >>               (let ([lst '()])
> >>                 (do ([exp 1 (add1 exp)])
> >>                   ((> (expt d exp) 100) (- (length lst) (length
> >> (remove-duplicates lst))))
> >>                   (for ([i (in-range 2 101)]) (set! lst (cons (* i exp)
> >> lst))))))))
> >>
> >> It solves #2 and #3 above, but it is still fundamentally clunky.
> >>
> >> Can someone help and teach us all some tricks?  My instincts say it
> should
> >> be possible to use append-map, for/list and/or foldl to build a list of
> the
> >> duplicates then simply count them in the for/sum loop, but am still
> unable
> >> to do it.
> >>
> >> Thanks,
> >> -Joe
> >> ____________________
> >>   Racket Users list:
> >>   http://lists.racket-lang.org/users
> > ____________________
> >  Racket Users list:
> >  http://lists.racket-lang.org/users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120417/779a29f8/attachment-0001.html>

Posted on the users mailing list.