Created
September 15, 2017 09:07
-
-
Save superlopuh/e706ccd97e103a1b4abd5bfdfb7b58eb to your computer and use it in GitHub Desktop.
Random Number Generation in Swift
This file contains 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 | |
// MARK: Integers | |
extension UInt32 { | |
/// Returns a random number in `0...UInt32.max` | |
static func random() -> UInt32 { | |
return arc4random() | |
} | |
/// Returns a random number in `0..<upperBound` | |
static func random(_ upperBound: UInt32) -> UInt32 { | |
return arc4random_uniform(upperBound) | |
} | |
} | |
extension UInt64 { | |
private static func randomLowerHalf() -> UInt64 { | |
return UInt64(UInt32.random()) | |
} | |
private static func randomLowerHalf(_ upperBound: UInt32) -> UInt64 { | |
return UInt64(UInt32.random(upperBound)) | |
} | |
static func random() -> UInt64 { | |
return (randomLowerHalf() << 32) &+ randomLowerHalf() | |
} | |
static func random(_ upperBound: UInt64) -> UInt64 { | |
if let upperBound = UInt32(exactly: upperBound) { | |
return randomLowerHalf(upperBound) | |
} else if UInt64(UInt32.max) == upperBound { | |
return randomLowerHalf() | |
} else { | |
var result: UInt64 | |
repeat { | |
result = random() | |
} while result >= upperBound | |
return result | |
} | |
} | |
} | |
extension Int32 { | |
static func random() -> Int32 { | |
return Int32(bitPattern: UInt32.random()) | |
} | |
static func random(_ upperBound: Int32) -> Int32 { | |
assert(0 < upperBound, "upperBound(\(upperBound)) must be greater than 0") | |
return Int32(bitPattern: UInt32.random(UInt32(bitPattern: upperBound))) | |
} | |
} | |
extension Int64 { | |
static func random() -> Int64 { | |
return Int64(bitPattern: UInt64.random()) | |
} | |
static func random(_ upperBound: Int64) -> Int64 { | |
assert(0 < upperBound, "upperBound(\(upperBound)) must be greater than 0") | |
return Int64(bitPattern: UInt64.random(UInt64(bitPattern: upperBound))) | |
} | |
} | |
extension Int { | |
static func random() -> Int { | |
return Int(IntMax.random()) | |
} | |
static func random(_ upperBound: Int) -> Int { | |
assert(0 < upperBound, "upperBound(\(upperBound)) must be greater than 0") | |
return Int(IntMax.random(IntMax(upperBound))) | |
} | |
} | |
// MARK: Collections | |
extension RandomAccessCollection where IndexDistance == Int { | |
public func randomElement() -> Generator.Element? { | |
guard !isEmpty else { return nil } | |
return self[index(startIndex, offsetBy: Int.random(count))] | |
} | |
} | |
extension MutableCollection where Self: RandomAccessCollection, IndexDistance == Int, Indices.SubSequence: Sequence, Indices.SubSequence.Iterator.Element == Index { | |
public func shuffled() -> Self { | |
var copy = self | |
copy.shuffleInPlace() | |
return copy | |
} | |
public mutating func shuffleInPlace() { | |
guard 1 < count else { return } | |
for i in indices.dropLast() { | |
let j = self.index(i, offsetBy: Int.random(distance(from: i, to: endIndex))) | |
guard i != j else { continue } | |
swap(&self[i], &self[j]) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment