(defklass bounded () all (bound 20) ; make size of 'all' (n 0) ; current size of 'all' (max *least*) ; key of top item of 'all' ready ; false if "all" needs a sort (key #'identity) (value #'identity) ) (defmethod print-object ((b bounded) str) (in bounded b (format str "bound= ~a~%max= ~a~%ready= ~a~%n=~a~%all=~a" bound max ready n all))) (defun boundeds (b) (in bounded b (unless ready (setf all (sort all #'> :key key) ready t)) all)) (defun boundedp (b) (boundeds b) (in bounded b (and (<= n bound) (= max (funcall key (first all)))))) (defun bounded-pair+ (key value b) (bounded+ (cons key value) b)) (defun bounded+ (new b) (in bounded b (if (< n bound) (setf n (1+ n) all (cons new all) max (max (funcall key new) max) ready nil) (when (< (funcall key new) max) (pop all) (setf all (sort (cons new all) #'> :key key) max (funcall key (first all)) ready t)))) b) (defun bounded-pairs () (make-instance 'bounded :key #'car :value #'cdr)) (deftest ?bounded-nums () (let ((b (make-instance 'bounded))) (reset-seed) (dotimes (i 1000) (bounded+ (randi 100) b)) (test (format nil "b:~a~%boundedp=~a" b (boundedp b)) " b:bound= 20 max= 2 ready= T n=20 all=(2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 0 0 0 0) boundedp=T" ))) (deftest ?bounded-pairs () (let ((b (bounded-pairs))) (reset-seed) (dotimes (i 1000) (bounded+ (cons (randi 100) 'a) b)) (format nil "b:~a~%boundedp=~a" b (boundedp b))))