Permutations
Algorithms #algorithmsIn mathematics, a permutation is an arrangement of objects in a specific order. For example, if we have a set of three objects (A, B, and C), there are six possible permutations of those objects: (A, B, C), (A, C, B), (B, A, C), (B, C, A), (C, A, B), and (C, B, A).
Permutations can be used to solve problems in which the order of the objects is important. For example, if we have a list of words and we want to find all possible combinations of those words, we can use permutations to generate the different combinations.
Permutations can also be used to generate all possible combinations of a given set of elements. For example, if we have a set of numbers and we want to find all possible combinations of those numbers, we can use permutations to generate the different combinations.
In general, the number of permutations of a set of n objects is given by the formula n! (n factorial), where n! = n * (n-1) * (n-2) * ... * 2 * 1
. For example, the number of permutations of a set of three objects is 3!, or 6.
- Recursive solution
import java.util.*
//sampleStart
fun main() {
// click + to see full script
val arr = "ALAB".toCharArray().toList()
val result = mutableListOf<List<Char>>()
permute(arr, 0, arr.size.dec(), result)
result.also {
println("Total permutations: ${it.count()}")
}.forEach(::println)
}
//sampleEnd
fun <T> permute(list: List<T>, left: Int, right: Int, result: MutableList<List<T>>) {
if (left == right) {
result.add(list.toList())
} else {
val visited = mutableMapOf<T, Boolean>()
for (i in left..right) {
if (visited.getOrDefault(list[i], false)) {
continue
}
visited[list[i]] = true
Collections.swap(list, left, i)
permute(list, left.inc(), right, result)
Collections.swap(list, left, i)
}
}
}
- Non-recursive solution
import java.util.*
//sampleStart
fun main() {
// click + to see full script
Permutations().permute("ALAB".toCharArray().toMutableList()).also {
println("Total permutations: ${it.count()}")
}.forEach(::println)
}
//sampleEnd
class Permutations {
data class Frame<T>(
val index: Int, var swapCount: Int, var lastVisited: MutableMap<T, Boolean> = mutableMapOf()
)
fun <T> swap(list: MutableList<T>, it: Int, to: Int) {
val tmp = list[it]
list[it] = list[to]
list[to] = tmp
}
fun <T> permute(list: MutableList<T>): List<List<T>> {
val solutions = mutableListOf<List<T>>()
if (list.size == 1) {
solutions.add(list.toList())
return solutions
}
val stack: Stack<Frame<T>> = Stack()
stack.push(Frame(index = 0, swapCount = -1))
while (stack.isNotEmpty()) {
val f = stack.pop()
if (f.index.inc() == list.size) {
solutions.add(list.toList())
}
if (f.swapCount > 0) {
swap(list, f.index, f.index + f.swapCount)
}
if (f.swapCount.plus(f.index) != list.size.dec()) {
stack.push(f)
f.swapCount++
val nextSwap = f.index.plus(f.swapCount)
if (f.lastVisited.getOrDefault(list[nextSwap], false).not()) {
f.lastVisited[list[nextSwap]] = true
swap(list, f.index, nextSwap)
for (i in f.index.inc() until list.size) {
stack.push(
Frame(
index = i, swapCount = 0, lastVisited = mutableMapOf(list[i] to true)
)
)
}
}
}
}
return solutions
}
}