(defclass dice ()
((prob-dist :initarg :prob-dist)
threshold))
(defmethod initialize-instance :after ((dice dice) &rest initargs)
(with-slots ((prob-dist prob-dist) (threshold threshold)) dice
(setf threshold
(nreverse (let ((sum (apply #'+ prob-dist)))
(reduce (lambda (a b) (cons (+ (car a) (/ b sum)) a))
prob-dist
:initial-value (list 0)))))))
(defmethod roll ((dice dice))
(position (random 1.0) (slot-value dice 'threshold)
:test #'<=))
(defun count-dice (prob-dist)
(loop with dice = (make-instance 'dice :prob-dist prob-dist)
with count = (make-array (length prob-dist) :initial-element 0)
repeat 1e5
do (incf (elt count (1- (roll dice))))
finally (loop for c across count
for i upfrom 1
do (format t "~a: ~a~%" i c))))
(count-dice '(1 2 1 2 1 2))
(count-dice (loop for i from 1 to 4 collect (sqrt i)))
KGRlZmNsYXNzIGRpY2UgKCkKICAoKHByb2ItZGlzdCA6aW5pdGFyZyA6cHJvYi1kaXN0KQogICB0aHJlc2hvbGQpKQoKKGRlZm1ldGhvZCBpbml0aWFsaXplLWluc3RhbmNlIDphZnRlciAoKGRpY2UgZGljZSkgJnJlc3QgaW5pdGFyZ3MpCiAgKHdpdGgtc2xvdHMgKChwcm9iLWRpc3QgcHJvYi1kaXN0KSAodGhyZXNob2xkIHRocmVzaG9sZCkpIGRpY2UKICAgIChzZXRmIHRocmVzaG9sZAoJICAobnJldmVyc2UgKGxldCAoKHN1bSAoYXBwbHkgIycrIHByb2ItZGlzdCkpKQoJCSAgICAgIChyZWR1Y2UgKGxhbWJkYSAoYSBiKSAoY29ucyAoKyAoY2FyIGEpICgvIGIgc3VtKSkgYSkpCgkJCSAgICAgIHByb2ItZGlzdAoJCQkgICAgICA6aW5pdGlhbC12YWx1ZSAobGlzdCAwKSkpKSkpKQoKKGRlZm1ldGhvZCByb2xsICgoZGljZSBkaWNlKSkKICAocG9zaXRpb24gKHJhbmRvbSAxLjApIChzbG90LXZhbHVlIGRpY2UgJ3RocmVzaG9sZCkKCSAgICA6dGVzdCAjJzw9KSkKCihkZWZ1biBjb3VudC1kaWNlIChwcm9iLWRpc3QpCiAgKGxvb3Agd2l0aCBkaWNlID0gKG1ha2UtaW5zdGFuY2UgJ2RpY2UgOnByb2ItZGlzdCBwcm9iLWRpc3QpCgl3aXRoIGNvdW50ID0gKG1ha2UtYXJyYXkgKGxlbmd0aCBwcm9iLWRpc3QpIDppbml0aWFsLWVsZW1lbnQgMCkKCXJlcGVhdCAxZTUKCWRvIChpbmNmIChlbHQgY291bnQgKDEtIChyb2xsIGRpY2UpKSkpCglmaW5hbGx5IChsb29wIGZvciBjIGFjcm9zcyBjb3VudAoJCSAgICAgIGZvciBpIHVwZnJvbSAxCgkJICAgICAgZG8gKGZvcm1hdCB0ICJ+YTogfmF+JSIgaSBjKSkpKQoKKGNvdW50LWRpY2UgJygxIDIgMSAyIDEgMikpCihjb3VudC1kaWNlIChsb29wIGZvciBpIGZyb20gMSB0byA0IGNvbGxlY3QgKHNxcnQgaSkpKQ==