While answering a recent question I came up with the following code, implementing a variant of the sieve of Eratosthenes, repeatedly culling the initial 2...n sequence, stopping as early as possible:
(define (sieve2 n)
(let ((ls (makelist n)))
(let loop ((ls ls)
(next (sievehelper2 ls n)))
(if (null? next)
ls
(cons (car ls)
(loop next (sievehelper2 ls n)))))))
(define (sievehelper2 list n)
(if (> (* (car list) (car list)) n)
'()
(filterfunc (not-divisible-by (car list))
list)))
(define filterfunc filter)
(define (not-divisible-by n)
(let ((m n)) ; the current multiple of n
(lambda (x)
(let ((ret (not (= x m))))
(if (>= x m) (set! m (+ m n)) #f)
ret))))
(define (makelist n)
(range 2 (+ 1 n)))
Running (sieve 50)
in Racket results in '(2 3 3 5 5 7 7 11 11 13 17 19 23 29 31 37 41 43 47)
though.
It has some error in it, as is obvious in the results, and I don't immediately see where it is. It can either be some stupid mistake that I made or an expression of some fundamental misalignment of the algorithmic pieces in use, and I can't say which is which.
What is that error and how can it be fixed, please?
To be clear, I'm not asking for algorithmic improvements to the code, I want the computational structure expressed in it preserved. Moreover, the challenge that I saw in the linked question was to devise the missing functions -- and alter the sieve
itself -- while keeping the sievehelper
function as given, up to some minor alterations as evident in this question's code. This is also a requirement I'd like to make in this question.
I'm also not happy with the two calls to sievehelper2
in sieve2
. Perhaps fixing the code structure somehow will also make the error go away?