11module random
22
33import stream
4+ import array
5+ import option
6+ import exception
47import io/filesystem
58import io/error
69
@@ -38,7 +41,7 @@ def minstd(seed: Int): Unit / emit[Byte] = {
3841 if (result < 0) result + m else result
3942 }
4043
41- while (true) {
44+ forever {
4245 state = nextInt()
4346 val b = state.mod(256).toByte
4447 do emit(b)
@@ -88,14 +91,14 @@ def devurandom { randomnessReader: () => Unit / random }: Unit / Exception[IOErr
8891
8992def randomByte(): Byte / random = do random()
9093def randomBytes(): Unit / {emit[Byte], random} =
91- while (true) do emit(do random())
94+ forever { do emit(do random()) }
9295
9396def randomBool(): Bool / random = {
9497 val b = do random()
9598 b.toInt.mod(2) == 1
9699}
97100def randomBools(): Unit / {emit[Bool], random} =
98- while (true) do emit(randomBool())
101+ forever { do emit(randomBool()) }
99102
100103def randomInt32(): Int / random = {
101104 var result = 0
@@ -107,7 +110,7 @@ def randomInt32(): Int / random = {
107110 result.mod(1.bitwiseShl(31)).abs * if (signBit) 1 else -1
108111}
109112def randomInt32s(): Unit / {emit[Int], random} =
110- while (true) do emit(randomInt32())
113+ forever { do emit(randomInt32()) }
111114
112115/// `max` is _inclusive_!
113116def randomInt(min: Int, max: Int): Int / random = {
@@ -126,17 +129,36 @@ def randomInt(min: Int, max: Int): Int / random = {
126129 min + (abs(result).mod(range))
127130 }
128131}
132+
129133/// `max` is _inclusive_!
130134def randomInts(min: Int, max: Int): Unit / {emit[Int], random} =
131- while (true) do emit(randomInt(min, max))
135+ forever { do emit(randomInt(min, max)) }
132136
133137
134138/// Random double between 0.0 and 1.0
135139def randomDouble(): Double / random =
136140 (randomInt32().toDouble / 1.bitwiseShl(31).toDouble).abs
137141 // This is not perfect, but it will do for now.
138142def randomDoubles(): Unit / {emit[Double], random} =
139- while (true) do emit(randomDouble())
143+ forever { do emit(randomDouble()) }
144+
145+ /// Shuffle an array in-place using the Fisher-Yates algorithm.
146+ def shuffle[A](arr: Array[A]): Unit / random = {
147+ val n = arr.size
148+ each(0, n - 1) { i =>
149+ arr.swap(i, randomInt(i, n - 1))
150+ }
151+ }
152+
153+ /// Pick a random element from an array.
154+ ///
155+ /// Panics when called on an empty array.
156+ def pick[A](arr: Array[A]): A / random =
157+ if (arr.size == 0) {
158+ panic("Pick from an empty array")
159+ } else {
160+ arr.get(randomInt(0, arr.size - 1))
161+ }
140162
141163
142164namespace examples {
0 commit comments