; the 37% rule

(define (take n xs)
  (let loop ((n n) (xs xs) (ys '()))
    (if (or (zero? n) (null? xs))
        (reverse ys)
        (loop (- n 1) (cdr xs)
              (cons (car xs) ys)))))

(define (drop n xs)
  (let loop ((n n) (xs xs))
    (if (or (zero? n) (null? xs)) xs
      (loop (- n 1) (cdr xs)))))

(define (range . args)
  (case (length args)
    ((1) (range 0 (car args) (if (negative? (car args)) -1 1)))
    ((2) (range (car args) (cadr args) (if (< (car args) (cadr args)) 1 -1)))
    ((3) (let ((le? (if (negative? (caddr args)) >= <=)))
           (let loop ((x(car args)) (xs '()))
             (if (le? (cadr args) x)
                 (reverse xs)
                 (loop (+ x (caddr args)) (cons x xs))))))
    (else (error 'range "unrecognized arguments"))))

(define random
  (let ((a 16807) (m 2147483647) (seed 20180921))
    (lambda args (if (pair? args) (set! seed (modulo (car args) m)))
      (set! seed (modulo (* a seed) m)) (/ seed m))))

(define (randint n)
  (round (* (random) n)))

(define (shuffle x)
  (do ((v (list->vector x)) (n (length x) (- n 1)))
      ((zero? n) (vector->list v))
    (let* ((r (randint n)) (t (vector-ref v r)))
      (vector-set! v r (vector-ref v (- n 1)))
      (vector-set! v (- n 1) t))))

(define (37percent n)
  (let* ((candidates (shuffle (range n)))
         (size (round (* 37/100 n)))
         (cutoff (apply max (take size candidates))))
    (display candidates) (display " ")
    (let loop ((cs (drop size candidates)) (prev #f))
      (cond ((null? cs) prev)
            ((< cutoff (car cs)) (car cs))
            (else (loop (cdr cs) (car cs)))))))

(display (37percent 20)) (newline)