; http://cap-lore.com/code/Scheme/reposIntro/rc4.html
(let (
     ;  (ex (lambda (m e) (write (list m e))(newline) e))
       (Do ((fileVal "Do") 'Do))) (letrec 
((root (lambda (key) (let ((nb (let ((s (make-string 256)))
  (Do 256 (lambda(n) (string-set! s n (integer->char n))))
  (let ((len (string-length key))(j 0))
      (Do 256 (lambda (k) (let ((i (- 255 k)))
        (set! j (bitwise-and (+ j (char->integer (string-ref s i))
          (char->integer (string-ref key (modulo i len)))) 255))
      (let ((t (string-ref s i))) (string-set! s i (string-ref s j))
        (string-set! s j t))))))
 (let ((i 0)(j 0)) (lambda () (set! i (bitwise-and (+ i 1) 255))
    (let* ((a (string-ref s i))(ai (char->integer a)))
      (set! j (bitwise-and (+ j ai) 255))
      (let ((b (string-ref s j))) (string-set! s i b)(string-set! s j a)
       (char->integer (string-ref s (bitwise-and
            (+ ai (char->integer b)) 255))))))))))

 (lambda (sy) (if (eq? sy 'child) (let ((nk (make-string 100)))
    (Do 100 (lambda (j) (string-set! nk j (integer->char (nb))))) (root nk))
 (cdr (assq sy (list
  (cons 'nb (lambda (n)(let ((v 0)) (Do n (lambda (dm)
         (set! v (+ (* 256 v) (nb))))) v)))
  (cons 'sb nb)

  (cons 'rbi (lambda (n) ; random big integer less than n
   ; recursive function that returns a sufficiently large array
   (let* ((a (let ma ((as 0)(n (- n 1))) (if (= n 0) (make-vector as)
             (let ((nv (ma (+ as 1) (quotient n 256))))
             (vector-set! nv as (bitwise-and n 255)) nv))))
         (vl (vector-length a))
         (fm (let pc ((p 1))(if (< (vector-ref a (- vl 1)) p) p (pc (+ p p))))))
   ;  (write (list 'dope vl (pt hd) n a hd))(newline)
    (lambda () (let sr () (let cd
       ((v 0)(ix vl)(td (lambda () (modulo (nb) fm)))(rn #f))
  ;  (write (list 'inter v ix lim fm))(newline)
    (if (= ix 0) v (let ((td (td))(lim (vector-ref a (- ix 1))))
    (if (or rn (< td lim)) (cd (+ td (* 256 v)) (- ix 1) nb #t)
    (if (= td lim) (cd (+ td (* 256 v)) (- ix 1) nb #f) (sr)))))))))))
  ))))))))) root))

; tests

(let ((Dos (fileVal "Do")) (g (((fileVal "RC4") "Seed stuff") 'sb)))
   ((Dos 'Do) (expt 2 20) (lambda (j) (g)))
   (list ((Dos 'DoL) 16 (lambda (j) (g)))
  (let* ((r ((fileVal "RC4") "Phoo")) (c (r 'child)) (nxb (c 'nb)))
     ((Dos 'DoL) 4 (lambda (j) (nxb 3))))))
=> ((42 78 166 252 61 253 166 28 211 174 230 36 44 109 135 221)
    (15218139 14738850 297282 11797637))
