I am trying to find smallest non-divisor of numbers (https://codegolf.stackexchange.com/questions/105412/find-the-smallest-number-that-doesnt-divide-n). Following version using 'named let' works properly:
(define (f1 m)
(let loop ((n 2))
(cond
[(= 0 (modulo m n))
(loop (+ 1 n))]
[else n])))
I am testing with:
(f 24)
(f 1234567)
(f 12252240)
(f 232792560)
Above version produces prompt output of: 5 2 19 and 23.
However, following version which uses built-in for
loop is very slow and actually crashes with out of memory error with larger numbers:
(define (f2 m)
(for/first ((i (range 2 m))
#:when (not (= 0 (modulo m i)))
#:final (not (= 0 (modulo m i))))
i))
Is there some error in the code of second version or is for
loop inefficient as compared with named let in Racket?
The range
function actually allocates a list, so the time for your function is dominated by the huge list allocation. Use in-range
instead:
(define (f2 m)
(for/first ([i (in-range 2 m)]
#:when (not (= 0 (modulo m i)))
#:final (not (= 0 (modulo m i))))
i))
See also the section on for
performance in the Racket Guide for more notes on the relative speed of different sequence forms.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With