random.scm 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. (library (lib random)
  2. (export make-random-integer-generator
  3. try-for-probability
  4. choose-random-element)
  5. (import
  6. (except (rnrs base) error)
  7. (only (guile) lambda* λ values error
  8. ;; random numbers
  9. random:uniform
  10. )
  11. ;; SRFI-27 for random number utilities
  12. (srfi srfi-27)))
  13. (define make-random-integer-generator
  14. (lambda* (#:key seed)
  15. "Get a procedure for generating uniformly distributed
  16. random integers from 0 up to a not included bound, which is
  17. seeded by the keyword argument seed, which must be a
  18. positive integer."
  19. (cond
  20. [seed
  21. (let ([rand-src (make-random-source)])
  22. ;; Set the given seed to guarantee same results for
  23. ;; same invokations.
  24. (random-source-pseudo-randomize! rand-src 0 seed)
  25. ;; Obtain a procedure, which gives uniformly
  26. ;; distributed integers.
  27. (random-source-make-integers rand-src))]
  28. [else
  29. (let ([rand-src (make-random-source)])
  30. ;; Try to make the random source truly random. How
  31. ;; this works depends on the specific implementation
  32. ;; of SRFI-27.
  33. (random-source-randomize! rand-src)
  34. (random-source-make-integers rand-src))])))
  35. (define try-for-probability
  36. (lambda* (probability #:key (random-state #f))
  37. "Generate a random inexact uniformly distributed float
  38. between [0,1) and test, if it is less than the given
  39. PROBABILITY. Return #t if the number is smaller than the
  40. given PROBABILITY and #t if the number is equal of bigger
  41. the given PROBABILITY. If a RANDOM-STATE is given, use the
  42. RANDOM-STATE to generate the random number and return both
  43. the number and the updated RANDOM-STATE."
  44. (cond
  45. [random-state
  46. (values (< (random:uniform random-state) probability)
  47. random-state)]
  48. [else
  49. (< (random:uniform) probability)])))
  50. (define choose-random-element
  51. (lambda* (seq #:key (rand-int-gen (make-random-integer-generator)))
  52. (cond
  53. [(pair? seq)
  54. (let* ([vec (list->vector seq)]
  55. [random-index (rand-int-gen (vector-length vec))])
  56. (vector-ref vec random-index))]
  57. [(vector? seq)
  58. (vector-ref seq (rand-int-gen (vector-length seq)))]
  59. [else
  60. (error "expected sequence of type list or vector, got:" seq)])))