Bibi's DevLog ๐Ÿค“๐ŸŽ

[Swift] ์ˆœ์—ด๊ณผ ์กฐํ•ฉ ๊ตฌํ˜„ํ•˜๊ธฐ Permutation & Combination ๋ณธ๋ฌธ

ํ”„๋กœ๊ทธ๋ž˜๋ฐ/Data Structures ์ž๋ฃŒ๊ตฌ์กฐ

[Swift] ์ˆœ์—ด๊ณผ ์กฐํ•ฉ ๊ตฌํ˜„ํ•˜๊ธฐ Permutation & Combination

๋น„๋น„ bibi 2022. 10. 6. 15:08

์ฐธ๊ณ  ๋งํฌ
[์ฝ”๋”ฉํ…Œ์ŠคํŠธ ๋Œ€๋น„] ์ˆœ์—ด(Permutation)๊ณผ ์กฐํ•ฉ(Combination) ์•Œ๊ณ ๋ฆฌ์ฆ˜

์ˆœ์—ด ๊ตฌํ˜„ํ•˜๊ธฐ Permutation

/// ์ˆœ์—ด permutation
// ๊ธธ์ด๊ฐ€ n์ธ ๋ฐฐ์—ด์—์„œ r๊ฐœ์˜ ์š”์†Œ๋ฅผ ์ฐจ๋ก€๋Œ€๋กœ ๋ฝ‘์•„ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ ๋‹ค.
// ๋ฐ˜๋ณต๋ฌธ : for๋ฌธ์„ r๋ฒˆ ์ค‘์ฒฉ - i, j, k์˜ ์ค‘๋ณต์„ ๋ฐฐ์ œํ•œ๋‹ค
func permutation() {
    // (n = 4, r = 3)๊ธธ์ด 4์ธ ๋ฐฐ์—ด์—์„œ 3๊ฐœ์˜ ์š”์†Œ ๋ฝ‘๊ธฐ
    let array = [1, 2, 3, 4]
    var answer: [[Int]] = []
    for i in array.indices { // r๋ฒˆ ์ค‘์ฒฉ
        for j in array.indices {
            for k in array.indices {
                if (i == j || j == k || k == i) {
                    continue
                }
                let arr = [array[i], array[j], array[k]] // ๊ธธ์ด r
                answer.append(arr)
            }
        }
    }
    print(answer)
}

func getPermutation<T: Hashable> (array: [T],
                                  count: Int,
                                  tempArray: [T] = [], // ์ˆœ์—ด ์ค‘ ํ•˜๋‚˜๋ฅผ ์ž„์‹œ ์ €์žฅ
                                  answer: [[T]] = [],
                                  usingItems: Set<T> = []) -> [[T]] { // ์–ด๋–ค ์ˆซ์ž๊ฐ€ ์‚ฌ์šฉ์ค‘์ด๋ผ๋ฉด ์—ฌ๊ธฐ์— ํฌํ•จ, ์•„๋‹ˆ๋ผ๋ฉด ๋บ€๋‹ค
    var currentTempArray = tempArray
    var currentAnswer = answer
    var currentUsingItems = usingItems

    if currentTempArray.count == count { // ์ˆœ์—ด ์ค‘ ํ•˜๋‚˜๊ฐ€ ์™„์„ฑ๋œ ๊ฒฝ์šฐ
        currentAnswer.append(currentTempArray)
        print(currentAnswer)
        return currentAnswer
    }

    // ์‚ฌ์šฉ์ค‘์ด์ง€ ์•Š์€ ์š”์†Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•ด ์ˆœ์—ด์„ ๊ตฌ์„ฑ
    for item in array {
        if currentUsingItems.contains(item) {
            continue
        }
        currentUsingItems.insert(item)
        currentTempArray.append(item)
        currentAnswer = getPermutation(array: array, count: count, tempArray: currentTempArray, answer: currentAnswer, usingItems: currentUsingItems)
        currentTempArray.popLast()
        currentUsingItems.remove(item)
    }
    return currentAnswer
}

// usingItems๋ฅผ ์“ฐ์ง€ ์•Š๋Š” ํ’€์ด - Set์„ ์“ฐ์ง€ ์•Š์œผ๋ฏ€๋กœ ์†๋„๋Š” ์กฐ๊ธˆ ๋” ๋Š๋ฆฌ๋‹ค
// Set์„ ์“ฐ์ง€ ์•Š๋Š” ๋Œ€์‹  tempArray์— ํ•ด๋‹น ์›์†Œ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€(์‚ฌ์šฉ์ค‘์ธ์ง€)๋ฅผ ์ฒดํฌํ•จ
func getPermutation2<T: Hashable> (array: [T],
                                  count: Int,
                                  tempArray: [T] = [],
                                  answer: [[T]] = []) -> [[T]] {
    var currentTempArray = tempArray
    var currentAnswer = answer

    if currentTempArray.count == count {
        currentAnswer.append(currentTempArray)
        return currentAnswer
    }

    for item in array {
        if tempArray.contains(item) {
            continue
        }
        currentTempArray.append(item)
        currentAnswer = getPermutation2(array: array, count: count, tempArray: currentTempArray, answer: currentAnswer)
        currentTempArray.popLast()
    }
    return currentAnswer
}

์กฐํ•ฉ ๊ตฌํ˜„ํ•˜๊ธฐ Combination

/// ์กฐํ•ฉ combination
// ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜์ง€ ์•Š์Œ.
// ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ๊ตฌํ˜„ : for๋ฐ˜๋ณต๋ฌธ์„ r๋ฒˆ ๋ฐ˜๋ณตํ•ด ๊ตฌํ˜„
func combination() {
    let array = [1, 2, 3, 4]
    var answer: [[Int]] = []
    for i in 0..<array.count {
        for j in i + 1..<array.count { // ์ง์ „ ๋ฐ˜๋ณต๋ฌธ์—์„œ ์‚ฌ์šฉํ•œ ๋‹ค์Œ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•ด ์ค‘๋ณต ํ”ผํ•˜๊ธฐ
            for k in j + 1..<array.count {
                answer.append([array[i], array[j], array[k]])
            }
        }
    }
    print(answer)
}

// ์žฌ๊ท€๋กœ ๊ตฌํ˜„ : ๋งค ์ธ๋ฑ์Šค๊ฐ€ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌ
func getCombination<T: Comparable>(array: [T],
                                   count: Int,
                                   tempArray: [T] = [],
                                   answer: [[T]] = [],
                                   lastIndex: Int = 0) -> [[T]] {
    var currentTempArray = tempArray
    var currentAnswer = answer
    var currentLastIndex = lastIndex

    // ์กฐํ•ฉ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์™„์„ฑ๋œ ๊ฒฝ์šฐ
    if currentTempArray.count == count {
        currentAnswer.append(currentTempArray)
        return currentAnswer
    }

    for i in currentLastIndex..<array.count {
        let item = array[i]
        if tempArray.contains(item) {
            continue
        }
        currentTempArray.append(item)
        currentLastIndex += 1
        currentAnswer = getCombination(array: array, count: count, tempArray: currentTempArray, answer: currentAnswer, lastIndex: currentLastIndex)
        currentTempArray.popLast()
    }
    return currentAnswer
}