範囲指定の乱数
kからn-1の乱数を取得したかったのですが、
arc4random-uniformでは0...n-1の乱数しか取得できないので、
Swiftで1000から9999の間で乱数を生成したいを参考に、
作ってみました。
func arc4random(lower: UInt32, upper: UInt32) -> UInt32 {
guard upper >= lower else {
return 0
}
return arc4random_uniform(upper - lower) + lower
}
呼び出し
for _ in 0 ... 20 {
print(arc4random(lower: 10, upper: 15))
}
結果
11
13
14
14
14
12
14
11
12
10
11
11
14
10
11
11
12
11
14
11
13
Knuthのアルゴリズム
この乱数を使って、Knuthのシャッフルアルゴリズムを実装してみました。
参考:https://ja.wikipedia.org/wiki/フィッシャー_-_イェーツのシャッフル
extension Array {
func shuffled() -> [Element] {
var result = self
result.shuffle()
return result
}
// selfをシャッフルする
mutating func shuffle() {
// iを0からcount-2まで増加させながら、以下を実行する
for i in 0 ..< (count - 1) {
// jにi以上count未満のランダムな整数を代入する
let j = Int(arc4random(lower: UInt32(i), upper: UInt32(count)))
if i != j {
// self[i]とself[j]を交換する
swap(&self[i], &self[j])
}
}
}
}
実行
let shuffled = [0, 1, 2, 3, 4, 5].shuffled()
結果
[3, 0, 5, 2, 4, 1]
参考
https://teratail.com/questions/16489
https://ja.wikipedia.org/wiki/フィッシャー_-_イェーツのシャッフル
https://www.rosettacode.org/wiki/Knuth_shuffle#Swift