C# 用于生成(0)到(0,1,2,3,4,5,6,7,8,9)类所有集合的Clean算法

C# 用于生成(0)到(0,1,2,3,4,5,6,7,8,9)类所有集合的Clean算法,c#,algorithm,language-agnostic,permutation,C#,Algorithm,Language Agnostic,Permutation,基本上,我想要一组集合,包含从(0..9),然后(0,1..9),(1,2..9)…(8,9),等等,直到(0,1,2,3,4,5,6,7,8,9)。我知道这可以通过以下方式为循环嵌套来实现,但我想知道是否有更整洁的方法来实现 最好是能在C#内完成的,但我对任何算法都感兴趣 for (int i = 0; i < max; i++) { yield {i}; for (int j = i + 1; j < max; j++) { yield {i, j

基本上,我想要一组集合,包含从(0..9),然后(0,1..9),(1,2..9)…(8,9),等等,直到(0,1,2,3,4,5,6,7,8,9)。我知道这可以通过以下方式为循环嵌套来实现,但我想知道是否有更整洁的方法来实现

最好是能在C#内完成的,但我对任何算法都感兴趣

for (int i = 0; i < max; i++) {
    yield {i};
    for (int j = i + 1; j < max; j++) {
        yield {i, j};
        for (int k = j + 1; k < max; k++) {
            yield {i, j, k};
            for (int l = k + 1; l < max; l++) {
                yield {i, j, k, l};
                for (int m = l + 1; m < max; m++) {
                    yield {i, j, k, l, m};
                    // And so on and so forth
                }
            }
        }
    }
}
for(int i=0;i
这是我不久前写的。它使用堆栈。它是通用的,因此也可以用于其他序列

static IEnumerable<T[]> CombinationsAnyLength<T>(params T[] values)
{
    Stack<int> stack = new Stack<int>(values.Length);
    int i = 0;
    while (stack.Count > 0 || i < values.Length) {
        if (i < values.Length) {
            stack.Push(i++);
            int c = stack.Count;
            T[] result = new T[c];
            foreach (var index in stack) result[--c] = values[index];
            yield return result;
        } else {
            i = stack.Pop() + 1;
            if (stack.Count > 0) i = stack.Pop() + 1;
        }
    }
}

CombinationsAnyLength(1, 2, 3, 4) outputs:
静态IEnumerable组合SANYLENGTH(参数T[]值)
{
堆栈=新堆栈(值.Length);
int i=0;
while(stack.Count>0 | | i0)i=stack.Pop()+1;
}
}
}
组合SANYLENGTH(1、2、3、4)输出:
一, 12 123 1234 124 13 134 14 2. 23 234 24 3. 34
4

这是我不久前写的。它使用堆栈。它是通用的,因此也可以用于其他序列

static IEnumerable<T[]> CombinationsAnyLength<T>(params T[] values)
{
    Stack<int> stack = new Stack<int>(values.Length);
    int i = 0;
    while (stack.Count > 0 || i < values.Length) {
        if (i < values.Length) {
            stack.Push(i++);
            int c = stack.Count;
            T[] result = new T[c];
            foreach (var index in stack) result[--c] = values[index];
            yield return result;
        } else {
            i = stack.Pop() + 1;
            if (stack.Count > 0) i = stack.Pop() + 1;
        }
    }
}

CombinationsAnyLength(1, 2, 3, 4) outputs:
静态IEnumerable组合SANYLENGTH(参数T[]值)
{
堆栈=新堆栈(值.Length);
int i=0;
while(stack.Count>0 | | i0)i=stack.Pop()+1;
}
}
}
组合SANYLENGTH(1、2、3、4)输出:
一, 12 123 1234 124 13 134 14 2. 23 234 24 3. 34
4

为什么不将其视为位并从位生成集合

IEnumberable<List<int>> MakeSets()
{
    // count from 1 to 2^10 - 1 (if you want the empty set, start at 0
    for (uint i=1; i < (1 << 10); i++) {
        // enumerate the bits as elements in a set
        List<int> set = BitsIn(i);
        yield return set;
    }
}

List<int> MakeSet(uint i)
{
    List<int> set = new List<int>();
    // this will give you values from 0..max
    // if you want 1, start with 1
    // if you want non-integers, pass in an array of values and index into that
    int val = 0;
    // for every bit in i
    while (i != 0)
    {
        // add the val if the corresponding bit is set
        if ((i & 1) != 0) set.Add(val);
        i = i >> 1;
        val++;
    }
    return set;
}
IEnumberable生成集()
{
//从1到2^10-1进行计数(如果需要空集,从0开始)
对于(uint i=1;i<(1>1;
val++;
}
返回集;
}
既然我喜欢上面的通用版本,让我们把它也变成通用版本:

IEnumerable<List<T>> MakeSets(params T[] values)
{
    if (values.Length > 63) throw new IllegalArgumentException("63 is the limit");
    for (ulong i = i; i < (1 << (values.Length + 1); i++) {
        List<T> set = new List<T>();
        int val = 0;
        ulong j = i;
        while (j != 0) {
            if ((j & 1) != 0) set.Add(values[val]);
            j = j >> 1;
            val++;
        }
        yield return set;
    }
}
IEnumerable生成集(参数T[]值)
{
如果(values.Length>63)抛出新的IllegalArgumentException(“63是限制”);
对于(ulong i=i;i<(1>1;
val++;
}
收益率回归集;
}
}

为什么不将其视为位并从位生成集合

IEnumberable<List<int>> MakeSets()
{
    // count from 1 to 2^10 - 1 (if you want the empty set, start at 0
    for (uint i=1; i < (1 << 10); i++) {
        // enumerate the bits as elements in a set
        List<int> set = BitsIn(i);
        yield return set;
    }
}

List<int> MakeSet(uint i)
{
    List<int> set = new List<int>();
    // this will give you values from 0..max
    // if you want 1, start with 1
    // if you want non-integers, pass in an array of values and index into that
    int val = 0;
    // for every bit in i
    while (i != 0)
    {
        // add the val if the corresponding bit is set
        if ((i & 1) != 0) set.Add(val);
        i = i >> 1;
        val++;
    }
    return set;
}
IEnumberable生成集()
{
//从1到2^10-1进行计数(如果需要空集,从0开始)
对于(uint i=1;i<(1>1;
val++;
}
返回集;
}
既然我喜欢上面的通用版本,让我们把它也变成通用版本:

IEnumerable<List<T>> MakeSets(params T[] values)
{
    if (values.Length > 63) throw new IllegalArgumentException("63 is the limit");
    for (ulong i = i; i < (1 << (values.Length + 1); i++) {
        List<T> set = new List<T>();
        int val = 0;
        ulong j = i;
        while (j != 0) {
            if ((j & 1) != 0) set.Add(values[val]);
            j = j >> 1;
            val++;
        }
        yield return set;
    }
}
IEnumerable生成集(参数T[]值)
{
如果(values.Length>63)抛出新的IllegalArgumentException(“63是限制”);
对于(ulong i=i;i<(1>1;
val++;
}
收益率回归集;
}
}

这里有一个生成子集的算法

让你有一个集合
S=[a,b,c,d,e,f]

如果要生成所有子集,则包含所有子集的数组长度将
2^n
其中
n
S
中的元素数

int A = [] //  array containing all sub-sets
for i = 0 --- 2^n
    x = binary(i) // like for i = 5 -> x = '000101' where x is a string of n digits.
    ns = []            // new array
    for j = 0 --- n
        if x[j] == '1'
            push S[j] into ns array
    push ns into A
return A

A将拥有您想要的所有集合,或者您可以修改它以获得新的结果。

下面是一个生成子集的算法

让你有一个集合
S=[a,b,c,d,e,f]

如果要生成所有子集,则包含所有子集的数组长度将
2^n
其中
n
S
中的元素数

int A = [] //  array containing all sub-sets
for i = 0 --- 2^n
    x = binary(i) // like for i = 5 -> x = '000101' where x is a string of n digits.
    ns = []            // new array
    for j = 0 --- n
        if x[j] == '1'
            push S[j] into ns array
    push ns into A
return A

A将拥有您想要的所有集合,或者您可以修改它以获得新结果。

使用Dennis签名:

    public static IEnumerable<T[]> CombinationsAnyLength<T>(params T[] values)
    {
        for(var i = 0; i < (1 << values.Length); i++)
        {
            var result = new List<T>();
            for(var j = 0; j < values.Length; j++)
            {
                if(((1 << j) & i) != 0)
                {
                    result.Add(values[j]);
                }
            }
            yield return result.ToArray();
        }
    }
公共静态IEnumerable组合SANYLENGH(参数T[]值)
{

对于(var i=0;i<(1使用Dennis签名:

    public static IEnumerable<T[]> CombinationsAnyLength<T>(params T[] values)
    {
        for(var i = 0; i < (1 << values.Length); i++)
        {
            var result = new List<T>();
            for(var j = 0; j < values.Length; j++)
            {
                if(((1 << j) & i) != 0)
                {
                    result.Add(values[j]);
                }
            }
            yield return result.ToArray();
        }
    }
公共静态IEnumerable组合SANYLENGH(参数T[]值)
{

对于(var i=0;i<(1)递归算法呢?@DStanley我认为OP表示(0-9)和(0,1-9),其中0-9表示0到9的一个数字,(0-9)表示10个一元素集。和(0,1-9)表示9个不同的两个元素集,其中第一个元素是0,第二个元素是1到9。-在从1到n迭代k时收集结果,您将得到您想要的。@DatRid递归算法会很好,但我不确定如何构造它。@DStanley Juharr说了什么。递归算法呢?@DStanley我认为表示(0-9)和(0,1-9),其中0-9表示数字0到9中的一个,而(0-9)表示10个一元素集。和(0,1-9)是指9个不同的两个元素集,其中第一个元素是0,第二个元素是1到9。-在从1到n迭代k时收集结果,您将得到您想要的。@DatRid递归算法会很好,但我不确定如何构造它。@DStanley Juharr说了什么。我希望有人提供递归解决方案,但t他的一个也非常令人印象深刻:)+1我确信它可以递归地完成。当我有更多的时间时,我会研究它。我认为它会很有趣。是的,我已经尝试过了,但我不熟悉
yield
,但遗憾的是,即使我真的试图理解它。期待着看到它:)递归解决方案:(不过,我更喜欢基于堆栈的解决方案)