[racket] making Racket code more idiomatic

From: Joe Gilray (jgilray at gmail.com)
Date: Tue Apr 17 16:39:10 EDT 2012

Cristian,

One more thing, since for*/fold in your code only takes one accumulator,
you don't need "values" at all.  Makes the code even shorter!

-Joe

On Tue, Apr 17, 2012 at 12:54 PM, Joe Gilray <jgilray at gmail.com> wrote:

> 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/60d61af8/attachment.html>

Posted on the users mailing list.