Last active
January 22, 2018 02:06
-
-
Save Azoy/bb2c4fa4ca64d015b4a59ca375545542 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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