[racket] making Racket code more idiomatic
Oops: I had scaled it to 1000 (also runs in under .1 seconds). Here is
the right code:
(define (euler29d)
(- (sqr 399)
(for/sum ([base '(2 3 5 6 7 10 11 12 13 14 15 17 18 19 20)])
(define lst
(for*/list ([exp (stop-before (in-naturals 1) (λ (exp) (>
(expt base exp) 400)))]
[i (in-range 2 401)]) (* i exp)))
(- (length lst) (length (remove-duplicates lst))))))
2012/4/18 Joe Gilray <jgilray at gmail.com>
> Thanks for more food for thought.
>
> 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.
>
> 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).
>
> Here's Cristian's code scaled to 400. It runs in under .1 seconds:
>
> (define (euler29d)
> (- (sqr 999)
> (for/sum ([base '(2 3 5 6 7 10 11 12 13 14 15 17 18 19 20)])
> (define lst
> (for*/list ([exp (stop-before (in-naturals 1) (λ (exp) (>
> (expt base exp) 400)))]
> [i (in-range 2 401)]) (* i exp)))
> (- (length lst) (length (remove-duplicates lst))))))
>
> On Wed, Apr 18, 2012 at 5:33 AM, Maxim Romashchenko <max at anahoret.com>wrote:
>
>> What about for*/set ?
>>
>> #lang racket
>> (require racket/set)
>> (define (generate-powers lower upper)
>> (for*/set ([a (in-range lower (add1 upper))]
>> [b (in-range lower (add1 upper))])
>> (expt a b)))
>> (set-count (generate-powers 2 5))
>> (set-count (generate-powers 2 100))
>>
>> Best regards, Maxim.
>>
>>
>>
>> On 2012-04-17 21:01, Cristian Esquivias 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<http://lists.racket-lang.org/users>
>>>>>
>>>> ____________________
>>>> Racket Users list:
>>>> http://lists.racket-lang.org/**users<http://lists.racket-lang.org/users>
>>>>
>>>
>>> ____________________
>>> Racket Users list:
>>> http://lists.racket-lang.org/**users<http://lists.racket-lang.org/users>
>>>
>> ____________________
>> Racket Users list:
>> http://lists.racket-lang.org/**users<http://lists.racket-lang.org/users>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120418/720ce7bb/attachment.html>