; mertens' conjecture

(define range
  (case-lambda
    ((stop) (range 0 stop (if (negative? stop) -1 1)))
    ((start stop) (range start stop (if (< start stop) 1 -1)))
    ((start stop step)
      (let ((le? (if (negative? step) >= <=)))
        (let loop ((x start) (xs (list)))
          (if (le? stop x) (reverse xs)
            (loop (+ x step) (cons x xs))))))
    (else (error 'range "too many arguments"))))

(define (factors n)
  (let ((wheel (vector 1 2 2 4 2 4 2 4 6 2 6)))
    (let loop ((n n) (f 2) (w 0) (fs (list)))
      (if (< n (* f f)) (reverse (cons n fs))
        (if (zero? (modulo n f))
            (loop (/ n f) f w (cons f fs))
            (loop n (+ f (vector-ref wheel w))
                  (if (= w 10) 3 (+ w 1)) fs))))))

(define (moebius n)
    (if (< n 1) (error 'moebius "must be positive")
      (if (= n 1) 1
        (let loop ((m 1) (f 0) (fs (factors n)))
          (if (null? fs) m
            (if (= f (car fs)) 0
              (loop (- m) (car fs) (cdr fs))))))))

(define (mertens n)
  (do ((k 1 (+ k 1))
       (m 0 (+ m (moebius k))))
      ((< n k) m)))

(define (a008683 n) ; moebius function
  (map moebius (range 1 (+ n 1))))

(display (a008683 25)) (newline)

(define (a002321 n) ; mertens function
  (map mertens (range 1 (+ n 1))))

(display (a002321 20)) (newline)

(define (a028442 n)
  ; numbers k such that mertens(k) == 0
  (let loop ((k 1) (M 0) (ks (list)))
    (if (< n k) (reverse ks)
      (let* ((m (moebius k)) (M (+ M m)))
        (if (zero? M)
            (loop (+ k 1) M (cons k ks))
            (loop (+ k 1) M ks))))))

(display (a028442 200)) (newline)

(define (a100306 n)
  ; numbers k such that moebius(k) == mertens(k)
  (let loop ((k 1) (M 0) (ks (list)))
    (if (< n k) (reverse ks)
      (let* ((m (moebius k)) (M (+ M m)))
        (if (= m M)
            (loop (+ k 1) M (cons k ks))
            (loop (+ k 1) M ks))))))

(display (a100306 200)) (newline)