KO EN

[Kotlin] Algorithms - Permutation

by 민갤

Back End /

Permutation

Choose r from different n elements without duplication and list them in order.

It is an extended concept from the combination, and unlike the combination, there is an order.

npr.png

Processing using visit or not array

  1. Visit all indexes with Depth-First Search (DFS).
  2. Check the visit to avoid duplicating the value.
  3. Repeat the above process until the depth matches r.
permutation_visited_dfs.jpg

Code 1. n!

private const val alphabets = "ABC"
private lateinit var result: Array<Char> // Altered Alphabet
private lateinit var visited: Array<Boolean> // Permutation visit status

fun main() {
    result = Array(alphabets.length) { '_' }
    visited = Array(alphabets.length) { false }

    permutation()
}

fun permutation(depth: Int = 0) {
    if (depth == alphabets.length) {
        println(result.contentDeepToString()) // a complete permutation
        return
    }
    
    for (i in alphabets.indices) {
        if (visited[i]) continue
        
        result[depth] = alphabets[i]
        visited[i] = true
        permutation(depth + 1)
        visited[i] = false
    }
}

Code 2. nPr + generic type for all data types

fun main() {
    permutation(arrayOf("A", "B", "C"), 3).forEach {
        println(it)
    }
}

/**
 * Permutation
 *
 * @param elements: an array of n elements
 * @param r: Number of elements to extract
 */
fun <T> permutation(elements: Array<T>, r: Int): List<List<T>> {
    val visited = BooleanArray(elements.size) // Visit or not
    val results = mutableListOf<List<T>>() // the number of all cases

    val result = elements.sliceArray(0 until r) // As a result of sorting r

    fun recursionPermutation(depth: Int = 0) {
        if (depth == r) {
            results.add(result.toList())
            return
        }

        for (i in elements.indices) {
            if (visited[i]) continue
            
            visited[i] = true
            result[depth] = elements[i]
            recursionPermutation(depth + 1)
            visited[i] = false
        }
    }

    recursionPermutation()
    return results
}

Code 3. nPr + Processing using swap

fun main() {
    permutation(arrayOf("A", "B", "C"), 3).forEach {
        println(it)
    }
}

fun <T> permutation(elements: Array<T>, r: Int): List<List<T>> {
    val n = elements.size
    val results = mutableListOf<List<T>>() // 모든 경우의 수

    fun swapPermutation(depth: Int = 0) {
        if (depth == r) {
            results.add(elements.takeLast(r).toList())
            return
        }

        for (i in range(depth, n)) {
            var tmp = elements[i]
            elements[i] = elements[depth]
            elements[depth] = tmp

            swapPermutation(depth + 1)

            // 원위치
            tmp = elements[i]
            elements[i] = elements[depth]
            elements[depth] = tmp
        }
    }

    swapPermutation()
    return results
}

Result

[A, B, C]
[A, C, B]
[B, A, C]
[B, C, A]
[C, A, B]
[C, B, A]

Reference

https://velog.io/@chayezo/Algorithm-순열-조합

https://hanyeop.tistory.com/455

https://notepad96.tistory.com/111

https://programming4myself.tistory.com/94

https://velog.io/@soyeon207/알고리즘-순열-yaxs0hh7

https://gyeong-log.tistory.com/51

https://soopeach.tistory.com/157

https://velog.io/@heyday_7/알고리즘-순열과-조합

Author

민갤

민갤

Back-End Developer

꾸잉꾸잉하고 웁니다.

로그인

디코에 오신 것을 환영해요!
전문가들의 수많은 아티클 창고 🤓