Skip to content

Instantly share code, notes, and snippets.

@Azoy
Last active January 22, 2018 02:06
Show Gist options
  • Save Azoy/bb2c4fa4ca64d015b4a59ca375545542 to your computer and use it in GitHub Desktop.
Save Azoy/bb2c4fa4ca64d015b4a59ca375545542 to your computer and use it in GitHub Desktop.
import Darwin
public protocol RandomGenerator {
func next<T : FixedWidthInteger>(_ type: T.Type) -> T
func next<T : FixedWidthInteger>(_ type: T.Type, upperBound: T) -> T
}
public enum Random : RandomGenerator {
case `default`
public func next<T : FixedWidthInteger>(_ type: T.Type) -> T {
var random: T = 0
arc4random_buf(&random, MemoryLayout<T>.size)
return random
}
public func next<T : FixedWidthInteger>(_ type: T.Type, upperBound: T) -> T {
let range = T.max % upperBound
var random: T = 0
repeat {
arc4random_buf(&random, MemoryLayout<T>.size)
} while random >= range
return random % upperBound
}
}
public protocol RandomizableCollection: Collection {
var random: Element { get }
func random(using generator: RandomGenerator) -> Element
}
// public protocol RandomAccessCollection : RandomizableCollection {}
extension RandomAccessCollection {
public var random: Element {
return self.random(using: Random.default)
}
public func random(using generator: RandomGenerator) -> Element {
assert(!self.isEmpty, "Empty collection")
var random = generator.next(Int.self, upperBound: Int(self.count))
if random < 0 {
random *= -1
}
let index = self.index(
self.startIndex,
offsetBy: IndexDistance(random),
limitedBy: self.endIndex
)
return self[index!]
}
}
public protocol Randomizable {
static var random: Self { get }
static func random(using generator: RandomGenerator) -> Self
}
extension Randomizable {
public static var random: Self {
return self.random(using: Random.default)
}
}
// public protocol FixedWidthInteger : Randomizable {}
extension FixedWidthInteger {
public static var random: Self {
return self.random(using: Random.default)
}
public static func random(using generator: RandomGenerator) -> Self {
return generator.next(Self.self)
}
}
// public protocol BinaryFloatingPoint : Randomizable {}
extension BinaryFloatingPoint {
public static var random: Self {
return self.random(using: Random.default)
}
public static func random(using generator: RandomGenerator) -> Self {
let random = generator.next(UInt64.self)
return Self(random) / Self(UInt64.max)
}
}
// public struct Bool : Randomizable {}
extension Bool {
public static var random: Bool {
return self.random(using: Random.default)
}
public static func random(using generator: RandomGenerator) -> Bool {
let random = generator.next(UInt8.self, upperBound: 2)
return random == 1
}
}
let nums = Array(UInt64(0) ..< UInt64.max)
print(nums.random)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment