How to generate all possible combinations?

前端 未结 4 992
南旧
南旧 2020-12-09 12:12

I\'m currently trying to make a Set of all possible combinations from an Array of Strings, were each element contains only one letter.

4条回答
  •  南笙
    南笙 (楼主)
    2020-12-09 12:52

    Here's a Swift 3 function that is a bit faster. It is based on an extension to the Array type that can be used on arrays with any element type.

    public func allCombinations(_ array:[String], minLength:Int=2) -> [String]
    {
       var result:[String] = []
       for n in minLength...array.count
       {
          result = result + array.combinations(of:n).map{ $0.joined(separator:"") }
       }
       return result
    }
    
    extension Array
    {
        public func combinations(of group:Int) -> [[Element]]
        {
           if group > count  { return [] }
    
           if group == count { return [self] }
    
           var result:[[Element]] = []
    
           var comboIndexes = (0..= 0
           {
              if carry == fullCombo
              { result.append(comboIndexes.map{self[$0]}) }
    
              comboIndexes[carry] += 1
    
              if comboIndexes[carry] == carry + indexLimit 
              { carry -= 1 ; continue }
    
              while carry < fullCombo
              {
                 carry += 1
                 comboIndexes[carry] = comboIndexes[carry-1] + 1 
              }       
           }
    
           return result
       }
    }
    

    In my tests, it ran about 40x faster than vacawama's second version on 7 letters.

    [EDIT] I realized later that this function produces combinations (as requested in the OP) where vacawama's function produces permutations. I tested an equivalent algorithm for permutations and it was merely 55% faster than vacawama's.

    extension Array
    {
       public func permutations(of group:Int? = nil) -> [[Element]]
       {
          let group       = group ?? count
          var result      : [[Element]] = []
          var permutation : [Element]   = []
    
          func permute(from baseIndex:Int)
          {
             if baseIndex == permutation.count - 1
             { 
               result.append(permutation)
               return 
             }
    
             permute(from:baseIndex+1)
    
             for index in baseIndex+1..= 0
          {
             if carry == fullCombo
             { 
               permutation = comboIndexes.map{self[$0]}
               permute(from:0)
             }
    
             comboIndexes[carry] += 1
    
             if comboIndexes[carry] == carry + indexLimit 
             { carry -= 1 ; continue }
    
             while carry < fullCombo
             {
                carry += 1
                comboIndexes[carry] = comboIndexes[carry-1] + 1 
             }       
          }
    
          return result
       }
    }
    

提交回复
热议问题