I\'m trying to generate seeded random numbers with Swift 4.2+, with the Int.random()
function, however there is no given implementation that allows for the random n
So I used Martin R's suggestion to use GamePlayKit
's GKMersenneTwisterRandomSource
to make a class that conformed to the RandomNumberGenerator protocol, which I was able to use an instance of in functions like Int.random()
:
import GameplayKit
class SeededGenerator: RandomNumberGenerator {
let seed: UInt64
private let generator: GKMersenneTwisterRandomSource
convenience init() {
self.init(seed: 0)
}
init(seed: UInt64) {
self.seed = seed
generator = GKMersenneTwisterRandomSource(seed: seed)
}
func next(upperBound: T) -> T where T : FixedWidthInteger, T : UnsignedInteger {
return T(abs(generator.nextInt(upperBound: Int(upperBound))))
}
func next() -> T where T : FixedWidthInteger, T : UnsignedInteger {
return T(abs(generator.nextInt()))
}
}
Usage:
// Make a random seed and store in a database
let seed = UInt64.random(in: UInt64.min ... UInt64.max)
var generator = Generator(seed: seed)
// Or if you just need the seeding ability for testing,
// var generator = Generator()
// uses a default seed of 0
let chars = ['a','b','c','d','e','f']
let randomChar = chars.randomElement(using: &generator)
let randomInt = Int.random(in: 0 ..< 1000, using: &generator)
// etc.
This gave me the flexibility and easy implementation that I needed by combining the seeding functionality of GKMersenneTwisterRandomSource
and the simplicity of the standard library's random functions (like .randomElement()
for arrays and .random()
for Int, Bool, Double, etc.)