Search code examples
swiftswift2arc4random

How to have 10 characters total and make sure at least one character from 4 different sets is used randomly


I have a text field and a button that generates a random set of characters. Set 1 = lowercase, set 2 = uppercase, set 3 = numbers, set 4 = symbols

I want the the button to generate no more no less that 10 characters and minimum pull from each of the sets at least once.

My idea of how to do it so far is

let roomIDGenerated = uniqueRoomID.text

let roomIDCount = roomIDGenerated?.characters.count

let randomCharacterSet = arc4random() upp

   while roomIDCount < 10 {
        <#code#>
    }

But I don't see how to do it...i don't always want the first 4 characters to always be one of each.. maybe one of the required sets is used last.

I'm kinda stuck in general, any help would be appreciated


Solution

  • Martin commented with the same approach I was taking. Here is my implementation:

    extension CollectionType {
        var random: Generator.Element {
            guard !isEmpty else { fatalError("array cannot be empty") }
            let array = Array(self)
            return array[Int(arc4random_uniform(UInt32(array.count)))]
        }
    }
    
    // from http://stackoverflow.com/a/24029847/1223781
    extension MutableCollectionType where Index == Int {
        func shuffled() -> Self {
            var copy = self
            copy.shuffle()
            return copy
        }
    
        mutating func shuffle() {
            guard count >= 2 else { return }
    
            for i in 0..<count - 1 {
                let j = Int(arc4random_uniform(UInt32(count - i))) + i
                guard i != j else { continue }
                swap(&self[i], &self[j])
            }
        }
    }
    
    let sets = ["abc", "ABC", "123", "#$%"].map { Array($0.characters) }
    let size = 10
    
    var randoms = sets.map { $0.random }
    while randoms.count < 10 {
        randoms.append(sets.random.random)
    }
    print(randoms.shuffled()) // ["b", "b", "3", "c", "#", "%", "A", "#", "1", "%"]