|
|
@ -2,15 +2,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
(in-package :cl-rng)
|
|
|
|
(in-package :cl-rng)
|
|
|
|
|
|
|
|
|
|
|
|
(defparameter *default-randomness-provider* #'urandom)
|
|
|
|
(defparameter *default-randomness-provider* #'urandom
|
|
|
|
|
|
|
|
"The default randomness provider used by cl-rng functions")
|
|
|
|
|
|
|
|
|
|
|
|
(defun chance (fraction &key (provider *default-randomness-provider*))
|
|
|
|
(defun chance (fraction &key (provider *default-randomness-provider*))
|
|
|
|
|
|
|
|
"Returns T if chance fraction is met"
|
|
|
|
(< (funcall provider) fraction))
|
|
|
|
(< (funcall provider) fraction))
|
|
|
|
|
|
|
|
|
|
|
|
(export '*default-randomness-provider*)
|
|
|
|
|
|
|
|
(export 'chance)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defun weighted (weights &key (default nil) (provider *default-randomness-provider*))
|
|
|
|
(defun weighted (weights &key (default nil) (provider *default-randomness-provider*))
|
|
|
|
|
|
|
|
"Interpret weights as an alist where the key is the item and the value is the chance. If no chances are met, return default"
|
|
|
|
(let ((previous 0)
|
|
|
|
(let ((previous 0)
|
|
|
|
(result (funcall provider))
|
|
|
|
(result (funcall provider))
|
|
|
|
(rval default))
|
|
|
|
(rval default))
|
|
|
@ -27,6 +27,7 @@
|
|
|
|
(export 'weighted)
|
|
|
|
(export 'weighted)
|
|
|
|
|
|
|
|
|
|
|
|
(defun shuffle! (sequence &key (provider *default-randomness-provider*))
|
|
|
|
(defun shuffle! (sequence &key (provider *default-randomness-provider*))
|
|
|
|
|
|
|
|
"In-place shuffle a sequence"
|
|
|
|
(if (listp sequence)
|
|
|
|
(if (listp sequence)
|
|
|
|
(loop for i from (1- (length sequence)) above 0 do
|
|
|
|
(loop for i from (1- (length sequence)) above 0 do
|
|
|
|
(rotatef (nth i sequence)
|
|
|
|
(rotatef (nth i sequence)
|
|
|
@ -36,5 +37,27 @@
|
|
|
|
(aref sequence (funcall provider :limit i :transform #'floor)))))
|
|
|
|
(aref sequence (funcall provider :limit i :transform #'floor)))))
|
|
|
|
sequence)
|
|
|
|
sequence)
|
|
|
|
|
|
|
|
|
|
|
|
(export 'shuffle!)
|
|
|
|
(defun within (sequence &key (provider *default-randomness-provider*))
|
|
|
|
|
|
|
|
"A random value withing a sequence. Can be setf()'d"
|
|
|
|
|
|
|
|
(if (listp sequence)
|
|
|
|
|
|
|
|
(nth (funcall provider :limit (1- (length sequence)) :transform 'round) sequence)
|
|
|
|
|
|
|
|
(aref sequence (funcall provider :limit (1- (length sequence)) :transform 'round))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defun within-set (sequence value)
|
|
|
|
|
|
|
|
(let ((index (funcall *default-randomness-provider* :limit (1- (length sequence)) :transform 'round)))
|
|
|
|
|
|
|
|
(if (listp sequence)
|
|
|
|
|
|
|
|
(setf (nth index sequence) value)
|
|
|
|
|
|
|
|
(setf (aref sequence index) value))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defun range (start end &key (integral nil) (provider *default-randomness-provider*))
|
|
|
|
|
|
|
|
"A random number in a range"
|
|
|
|
|
|
|
|
(+ start (funcall provider :limit (- end start) :transform (if integral 'round 'identity))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;; Exports
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(export '*default-randomness-provider*)
|
|
|
|
|
|
|
|
(defsetf within within-set)
|
|
|
|
|
|
|
|
(export 'range)
|
|
|
|
|
|
|
|
(export 'within)
|
|
|
|
|
|
|
|
(export 'shuffle!)
|
|
|
|
|
|
|
|
(export 'chance)
|
|
|
|