I\'m currently trying to make a Set of all possible combinations from an Array of Strings, were each element contains only one letter.
This is quite similar to @vacawama's answer, but hopefully different enough that it deserves a separate answer :)
Here, an array with all combinations is built (explaining comments inline):
func combinations(array : [String]) -> [String] {
// Recursion terminates here:
if array.count == 0 { return [] }
// Concatenate all combinations that can be built with element #i at the
// first place, where i runs through all array indices:
return array.indices.flatMap { i -> [String] in
// Pick element #i and remove it from the array:
var arrayMinusOne = array
let elem = arrayMinusOne.removeAtIndex(i)
// Prepend element to all combinations of the smaller array:
return [elem] + combinations(arrayMinusOne).map { elem + $0 }
}
}
Then you can filter the strings with at least two letters, and
convert it to a Set:
let c = Set(combinations(["A", "B", "C"]).filter { $0.characters.count >= 2 })
print(c)
// ["BA", "AC", "ABC", "AB", "BCA", "CB", "BC", "CAB", "ACB", "CA", "CBA", "BAC"]
I made a simple performance comparison (compiled in Release mode on a Macbook Pro):
let array = ["A", "B", "C", "D", "E", "F", "G"]
let t1 = NSDate()
let c1 = Set(combinations(array).filter { $0.characters.count >= 2 })
let t2 = NSDate()
let c2 = permute(array)
let t3 = NSDate()
print(c1 == c2) // true
print(t2.timeIntervalSinceDate(t1))
print(t3.timeIntervalSinceDate(t2))
The result depends on the size of the input array, but @vacawama's updated method is the fastest:
# of array This vacawama's vacawama's elements: method: 1st method: 2nd method: 2 0.00016 0.00005 0.00001 3 0.00043 0.00013 0.00004 4 0.00093 0.00062 0.00014 5 0.00335 0.00838 0.00071 6 0.01756 0.24399 0.00437 7 0.13625 11.90969 0.03692