; almost-primes

(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 (kap? k n) (= (length (factors n)) k))

(define (distinct? xs)
  (if (or (null? xs) (null? (cdr xs))) #t
    (if (= (car xs) (cadr xs)) #f
      (distinct? (cdr xs)))))

(define (sfkap? k n)
  (let ((fs (factors n)))
    (and (= (length fs) k) (distinct? fs))))

(define (seq test? k len)
  (let loop ((k k) (m len) (n 2) (ks (list)) (kss (list)))
    (if (zero? k) kss
      (if (zero? m)
          (loop (- k 1) len 2 (list) (cons (reverse ks) kss))
          (if (test? k n)
              (loop k (- m 1) (+ n 1) (cons n ks) kss)
              (loop k m (+ n 1) ks kss))))))

(for-each (lambda (ks) (display ks) (newline)) (seq kap? 5 10))
(newline)
(for-each (lambda (ks) (display ks) (newline)) (seq sfkap? 5 10))