Apple Swift - Generate combinations with repetition

后端 未结 5 1926
自闭症患者
自闭症患者 2020-12-28 09:25

I\'m trying to generate a nested array containing all combinations with repetition in Apple\'s Swift programming language.

An detailed explanation of combinations wi

5条回答
  •  無奈伤痛
    2020-12-28 10:12

    Your example gives combinations with repetition. For the record I have written a non-repetitive combination in Swift. I based it on the JavaScript version here: http://rosettacode.org/wiki/Combinations#JavaScript

    I hope it helps others and if anyone can see improvement please do.. note this is my first attempt at Swift and was hoping for a neater way of doing the Swift equivalent of JavaScript slice.

    func sliceArray(var arr: Array, x1: Int, x2: Int) -> Array {
        var tt: Array = []
        for var ii = x1; ii <= x2; ++ii {
            tt.append(arr[ii])
        }
        return tt
    }
    
    func combinations(var arr: Array, k: Int) -> Array> {
        var i: Int
        var subI : Int
    
        var ret: Array> = []
        var sub: Array> = []
        var next: Array = []
        for var i = 0; i < arr.count; ++i {
            if(k == 1){
                ret.append([arr[i]])
            }else {
                sub = combinations(sliceArray(arr, i + 1, arr.count - 1), k - 1)
                for var subI = 0; subI < sub.count; ++subI {
                    next = sub[subI]
                    next.insert(arr[i], atIndex: 0)
                    ret.append(next)
                }
            }
    
        }
        return ret
    }
    
    
    var myCombinations = combinations([1,2,3,4],2)
    

    Per the OP's request, here is a version which removes the custom Array slicing routine in favor of functionality in the standard library

    // Calculate the unique combinations of elements in an array
    // taken some number at a time when no element is allowed to repeat
    func combinations(source: [T], takenBy : Int) -> [[T]] {
        if(source.count == takenBy) {
            return [source]
        }
    
        if(source.isEmpty) {
            return []
        }
    
        if(takenBy == 0) {
            return []
        }
    
        if(takenBy == 1) {
            return source.map { [$0] }
        }
    
        var result : [[T]] = []
    
        let rest = Array(source.suffixFrom(1))
        let sub_combos = combinations(rest, takenBy: takenBy - 1)
        result += sub_combos.map { [source[0]] + $0 }
    
        result += combinations(rest, takenBy: takenBy)
    
        return result
    }
    
    var myCombinations = combinations([1,2,3,4], takenBy: 2)
    // myCombinations = [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
    

提交回复
热议问题