Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Collection Randomizer
import Foundation
public struct RandomGenerator<C: CollectionType> : GeneratorType, SequenceType {
private var backingGenerator : PermutationGenerator<C, [C.Index]>
public init(_ elements : C) {
var indices = Array(elements.startIndex..<elements.endIndex)
for index in 0..<count(indices) {
var swapIndex = index + Int(arc4random_uniform(UInt32(count(indices) - index)))
if swapIndex != index {
swap(&indices[index], &indices[swapIndex])
}
}
backingGenerator = PermutationGenerator(elements: elements, indices: indices)
}
public typealias Element = C.Generator.Element
public typealias Generator = PermutationGenerator<C, [C.Index]>
public mutating func next() -> Element? {return backingGenerator.next()}
public func generate() -> PermutationGenerator<C, [C.Index]> {return backingGenerator}
}
let a = "😤😣😨😭😱😷😸😽😾👣🙀👤😓"
let b = "Hello There"
let c = [1, 2, 3, 4, 5, 6, 7, 8, 9]
let d = ["A":"B", "C":"D", "E":"F", "G":"H"]
let e = ["A":1, "B":2, "C":3, "D":4]
var f = Set(1...10)
println(Array(RandomGenerator(a)))
println(Array(RandomGenerator(b)))
println(Array(RandomGenerator(c)))
println(Array(RandomGenerator(d)))
println(Array(RandomGenerator(e)))
println(Array(RandomGenerator(f)))
@lilyball

This comment has been minimized.

Copy link

lilyball commented Apr 24, 2015

Why is RandomGenerator a GeneratorType when it doesn't return itself from the generate() method? If you're returning the underlying PermutationGenerator then you can drop the GeneratorType conformance, the Element typealias, and the next() method.

Also, just a nitpick, but if you want to iterate over the indices of the array it's more idiomatic to say for index in indices(ary) (though you really need to rename the local indices variable in that case).

@lilyball

This comment has been minimized.

Copy link

lilyball commented Apr 24, 2015

Here's a version that should be more efficient. It uses the "inside-out" Fisher-Yates shuffle:

import Darwin // for arc4random_uniform

public struct RandomSequence<C: CollectionType>: SequenceType {
    public init(_ elements : C) {
        var indices = ContiguousArray<C.Index>()
        indices.reserveCapacity(numericCast(count(elements)))
        // "inside-out" Fisher-Yates shuffle
        for (i, idx) in enumerate(Swift.indices(elements)) {
            let j = Int(arc4random_uniform(UInt32(i)+1)) // in the range [0,i]
            indices.append(idx)
            if j != i {
                swap(&indices[j], &indices[i])
            }
        }
        backingGenerator = PermutationGenerator(elements: elements, indices: indices)
    }
    public typealias Generator = PermutationGenerator<C, ContiguousArray<C.Index>>
    public func generate() -> Generator {return backingGenerator}

    private var backingGenerator: Generator
}
@lilyball

This comment has been minimized.

Copy link

lilyball commented Apr 24, 2015

Note: I used ContiguousArray mostly for the heck of it. You can replace that with Array if you feel like it. They should be basically the same thing when the element type isn't an obj-c class/protocol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.