[英]Recursively finding all partitions of a set of n objects into k non-empty subsets
I want to find all partitions of an elements into k subsets, this is my algorithm based on recursive formula for finding all Stirling second numbers我想找到一个元素的所有分区到 k 个子集,这是我基于递归公式的算法,用于查找所有斯特林秒数
fun main(args: Array<String>) {
val s = mutableSetOf(1, 2, 3, 4, 5)
val partitions = 3
val res = mutableSetOf<MutableSet<MutableSet<Int>>>()
partition(s, partitions, res)
//println(res)
println("Second kind stirling number ${res.size}")
}
fun partition(inputSet: MutableSet<Int>, numOfPartitions: Int, result: MutableSet<MutableSet<MutableSet<Int>>>) {
if (inputSet.size == numOfPartitions) {
val sets = inputSet.map { mutableSetOf(it) }.toMutableSet()
result.add(sets)
}
else if (numOfPartitions == 1) {
result.add(mutableSetOf(inputSet))
}
else {
val popped: Int = inputSet.first().also { inputSet.remove(it) }
val r1 = mutableSetOf<MutableSet<MutableSet<Int>>>()
partition(inputSet, numOfPartitions, r1) //add popped to each set in solution (all combinations)
for (solution in r1) {
for (set in solution) {
set.add(popped)
result.add(solution.map { it.toMutableSet() }.toMutableSet()) //deep copy
set.remove(popped)
}
}
val r2 = mutableSetOf<MutableSet<MutableSet<Int>>>()
partition(inputSet, numOfPartitions - 1, r2) //popped is single elem set
r2.map { it.add(mutableSetOf(popped)) }
r2.map { result.add(it) }
}
}
Code works well for k = 2, but for bigger n and k it loses some partitions and I can't find a mistake here.代码适用于 k = 2,但对于更大的 n 和 k,它会丢失一些分区,我在这里找不到错误。 Example: n = 5 and k = 3 outputs
Second kind stirling number 19
the correct output would be 25.示例:n = 5 和 k = 3 输出
Second kind stirling number 19
正确的输出是 25。
If you can read Python code, consider the next algorithm which I've quickly adapted from my implementation of set partition into equal size parts.如果您可以阅读 Python 代码,请考虑下一个算法,该算法是我从我的将分区设置为相等大小的部分的实现中快速改编的。
Recursive function fills K parts with N values.递归函数用 N 个值填充 K 个部分。
The lastfilled
parameter helps to avoid duplicates - it provides an increasing sequence of leading (smallest) elements of every part. lastfilled
参数有助于避免重复 - 它提供了每个部分的前导(最小)元素的递增序列。
The empty
parameter is intended to avoid empty parts. empty
参数旨在避免空部分。
def genp(parts:list, empty, n, k, m, lastfilled):
if m == n:
print(parts)
global c
c+=1
return
if n - m == empty:
start = k - empty
else:
start = 0
for i in range(start, min(k, lastfilled + 2)):
parts[i].append(m)
if len(parts[i]) == 1:
empty -= 1
genp(parts, empty, n, k, m+1, max(i, lastfilled))
parts[i].pop()
if len(parts[i]) == 0:
empty += 1
def setkparts(n, k):
parts = [[] for _ in range(k)]
cnts = [0]*k
genp(parts, k, n, k, 0, -1)
c = 0
setkparts(5,3)
#setkparts(7,5)
print(c)
[[0, 1, 2], [3], [4]]
[[0, 1, 3], [2], [4]]
[[0, 1], [2, 3], [4]]
[[0, 1, 4], [2], [3]]
[[0, 1], [2, 4], [3]]
[[0, 1], [2], [3, 4]]
[[0, 2, 3], [1], [4]]
[[0, 2], [1, 3], [4]]
[[0, 2, 4], [1], [3]]
[[0, 2], [1, 4], [3]]
[[0, 2], [1], [3, 4]]
[[0, 3], [1, 2], [4]]
[[0], [1, 2, 3], [4]]
[[0, 4], [1, 2], [3]]
[[0], [1, 2, 4], [3]]
[[0], [1, 2], [3, 4]]
[[0, 3, 4], [1], [2]]
[[0, 3], [1, 4], [2]]
[[0, 3], [1], [2, 4]]
[[0, 4], [1, 3], [2]]
[[0], [1, 3, 4], [2]]
[[0], [1, 3], [2, 4]]
[[0, 4], [1], [2, 3]]
[[0], [1, 4], [2, 3]]
[[0], [1], [2, 3, 4]]
25
Not sured, what is the exact problem in your code, but finding all Stirling second numbers in recursive manner is much simplier:不确定,您的代码中的确切问题是什么,但以递归方式查找所有斯特林第二个数字要简单得多:
private val memo = hashMapOf<Pair<Int, Int>, BigInteger>()
fun stirling2(n: Int, k: Int): BigInteger {
val key = n to k
return memo.getOrPut(key) {
when {
k == 0 || k > n -> BigInteger.ZERO
n == k -> BigInteger.ONE
else -> k.toBigInteger() * stirling2(n - 1, k) + stirling2(n - 1, k - 1)
}
}
}
I improved Kornel_S' code.我改进了 Kornel_S 的代码。 There is a func which makes a list of all possible combinations.
有一个 func 可以列出所有可能的组合。 Be careful with big numbers :)
小心大数字:)
def Stirling2Iterate(List):
Result = []
def genp(parts:list, empty, n, k, m, lastfilled):
if m == n:
nonlocal Result
nonlocal List
Result += [ [[List[item2] for item2 in item] for item in parts] ]
return
if n - m == empty: start = k - empty
else: start = 0
for i in range(start, min(k, lastfilled + 2)):
parts[i].append(m)
if len(parts[i]) == 1: empty -= 1
genp(parts, empty, n, k, m + 1, max(i, lastfilled))
parts[i].pop()
if len(parts[i]) == 0: empty += 1
def setkparts(n, k):
parts = [ [] for _ in range(k) ]
cnts = [0] * k
genp(parts, k, n, k, 0, -1)
for i in range(len(List)): setkparts(len(List), i + 1)
return Result
Example:例子:
# EXAMPLE
print('\n'.join([f"{x}" for x in Stirling2Iterate(['A', 'B', 'X', 'Z'])]))
# OUTPUT
[['A', 'B', 'X', 'Z']]
[['A', 'B', 'X'], ['Z']]
[['A', 'B', 'Z'], ['X']]
[['A', 'B'], ['X', 'Z']]
[['A', 'X', 'Z'], ['B']]
[['A', 'X'], ['B', 'Z']]
[['A', 'Z'], ['B', 'X']]
[['A'], ['B', 'X', 'Z']]
[['A', 'B'], ['X'], ['Z']]
[['A', 'X'], ['B'], ['Z']]
[['A'], ['B', 'X'], ['Z']]
[['A', 'Z'], ['B'], ['X']]
[['A'], ['B', 'Z'], ['X']]
[['A'], ['B'], ['X', 'Z']]
[['A'], ['B'], ['X'], ['Z']]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.