C# 给定池中元素的所有n个分区

C# 给定池中元素的所有n个分区,c#,algorithm,linq,list,partitioning,C#,Algorithm,Linq,List,Partitioning,我正在尝试编写一个C#算法,该算法给出包含x元素的池中可能的n个分区的列表 为了更清楚,假设我有6个元素:1,2,3,4,5,6(x=6) 我应该给出3个数字的所有分区,即: 1,2,3 and 4,5,6 1,3,4 and 2,5,6 1,2,5 and 3,4,6 1,2,6 and 3,4,5 etc. 我的目标函数如下所示: List<List<List<int>>> GetAllPartitions(int x, int n) 列出GetAll

我正在尝试编写一个C#算法,该算法给出包含x元素的池中可能的n个分区的列表

为了更清楚,假设我有6个元素:1,2,3,4,5,6(x=6) 我应该给出3个数字的所有分区,即:

1,2,3 and 4,5,6
1,3,4 and 2,5,6
1,2,5 and 3,4,6
1,2,6 and 3,4,5
etc.
我的目标函数如下所示:

List<List<List<int>>> GetAllPartitions(int x, int n)
列出GetAllPartitions(intx,intn)
编辑:

我要找的不是组合。。。为此,我使用以下内容(取自本网站):

公共静态IEnumerable组合(此IEnumerable元素,int k)
{
返回k==0
?新建[]{new T[0]}
:elements.SelectMany((e,i)=>
元素.跳过(i+1).组合(k-1).选择(c=>(new[]{e}).Concat(c));
}

一般来说,我不做只链接的回答(通常我也希望您展示解决方案的尝试),但对于已经用c语言编写的任何类型的对象(不仅仅是int),都有一个完整的代码解决方案,可以在这里找到:

注意:这将为集合生成每种长度的所有分区,因此您需要在结果列表上进行简单的选择,以便仅为所需的“n”长度分区对其进行筛选,这可以是:

var result = from allResults select result where result.length = n || result.length = x-n
对于那些担心链接死亡的人,以下是链接代码:

/// <summary>
/// A enumeration of all possible partitions of a set of items.
/// </summary>
/// <typeparam name="T">The type of the items in the set being partitioned.</typeparam>
public sealed class AllPartitionsEnumerable<T> : IEnumerable<IEnumerable<IEnumerable<T>>>
{
    /// <summary></summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
    private IEnumerable<T> items;

    /// <summary>
    /// Creates and initializes an instance of the <see cref="AllPartitionsEnumerable{T}"/> type.
    /// </summary>
    /// <param name="items">The set of items to be partitioned.</param>
    public AllPartitionsEnumerable(IEnumerable<T> items)
        : base ()
    {
        this.items = items;
    }

    /// <summary>
    /// Gets an enumerator to iterate over the partitions in this enumeration.
    /// </summary>
    /// <returns>An instance of <see cref="IEnumerator{T}"/>.</returns>
    public IEnumerator<IEnumerable<IEnumerable<T>>> GetEnumerator()
    {
        return new AllPartitionsEnumerator<T>(this.items);
    }

    /// <summary>
    /// Gets an enumerator to iterate over the partitions in this enumeration.
    /// </summary>
    /// <returns>An instance of <see cref="IEnumerator{T}"/>.</returns>
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
 /// <summary>
/// An enumerator to iterate over the items in an instance of <see cref="AllPartitionsEnumerable{T}"/>.
/// </summary>
/// <typeparam name="T">The type of the items in the set being partitioned.</typeparam>
public sealed class AllPartitionsEnumerator<T> : IEnumerator<IEnumerable<IEnumerable<T>>>
{
    /// <summary>The original set of items over which partitions are created.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private T[] items;

    /// <summary>Flag to indicate if this enumerator has been disposed of.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private bool isDisposed;

    /// <summary>Flag to indicate if this enumerator is in its initial state.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private bool isFirst;

    /// <summary>The number of partitions in the current selection.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int nc;

    /// <summary>An array of values indicating the number of values in the partition at the specified index.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int[] p;

    /// <summary>An array of indices indicating to which partition the item at the specified index belongs.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int[] q;

    /// <summary>The current partition.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private T[][] current;

    /// <summary>
    /// Creates and initializes an instance of the <see cref="AllPartitionsEnumerator{T}"/> type.
    /// </summary>
    /// <param name="items">The original set of items over which partitions are enumerated.</param>
    public AllPartitionsEnumerator(IEnumerable<T> items)
        : base()
    {
        if (null == items)
        {
            throw new ArgumentNullException("items");
        }

        this.isFirst = true;
        this.items = items.ToArray();
        this.nc = 0;
        this.p = new int[this.items.Length];
        this.q = new int[this.items.Length];
        this.current = null;
    }

    /// <summary>
    /// Gets the current partition.
    /// </summary>
    public IEnumerable<IEnumerable<T>> Current
    {
        get
        {
            this.CheckIfDisposed();

            return this.current;
        }
    }

    /// <summary>
    /// Disposes of this enumerator and releases all resources held by it.
    /// </summary>
    public void Dispose()
    {
        if (this.isDisposed)
        {
            return;
        }

        this.isDisposed = true;
        this.items = null;
        this.p = null;
        this.q = null;
        this.nc = 0;
        this.current = null;
        this.isFirst = true;
    }

    /// <summary>
    /// Gets the current partition.
    /// </summary>
    object IEnumerator.Current
    {
        get
        {
            return this.Current;
        }
    }

    /// <summary>
    /// Selects the next item in the set of all partitions.
    /// </summary>
    /// <returns><c>true</c> if an item was selected; <c>false</c> if we are past the last element.</returns>
    public bool MoveNext()
    {
        this.CheckIfDisposed();

        if (this.isFirst)
        {
            this.isFirst = false;
            this.nc = 1;
            this.p[0] = this.items.Length;
            for (int i = 0; i < this.items.Length; ++i)
            {
                this.q[i] = this.nc;
            }
            this.Select();
            return true;
        }

        if (this.nc == this.items.Length )
        {
            return false;
        }

        int n = this.items.Length;
        int m = n;
        int l = this.q[m-1];

        while (this.p[l - 1] == 1)
        {
            this.q[m - 1] = 1;
            --m;
            l = this.q[m - 1];
        }

        this.nc += m - n;
        this.p[0] = this.p[0] + n - m;

        if (l == this.nc)
        {
            ++this.nc;
            this.p[this.nc - 1] = 0;
        }

        this.q[m - 1] = l + 1;
        this.p[l - 1] = this.p[l - 1] - 1;
        this.p[l] = this.p[l] + 1;

        this.Select();
        return true;
    }

    /// <summary>
    /// Resets this enumerator to its initial state.
    /// </summary>
    public void Reset()
    {
        this.CheckIfDisposed();

        this.current = null;
        this.isFirst = true;
        this.isDisposed = false;
        this.p = new int[this.items.Length];
        this.q = new int[this.items.Length];
        this.nc = 0;
    }

    /// <summary>
    /// Selects the items for the current partition.
    /// </summary>
    private void Select()
    {
        this.current = new T[this.nc][];

        for (int i = 0; i < this.nc; ++i)
        {
            int k = 0;
            this.current[i] = new T[this.p[i]];

            for (int j = 0; j < this.items.Length; ++j)
            {
                if (this.q[j] == i + 1)
                {
                    this.current[i][k] = this.items[j];
                    ++k;
                }
            }
        }
    }

    /// <summary>
    /// Checks and throws an exception if this enumerator has been disposed.
    /// </summary>
    private void CheckIfDisposed()
    {
        if (this.isDisposed)
        {
            throw new ObjectDisposedException(this.GetType().FullName);
        }
    }
}
    /// <summary>
    /// Retrieves all possible partitions of a set of items.
    /// </summary>
    /// <typeparam name="T">The type of the items in the original set.</typeparam>
    /// <param name="items">The original set of items over which partitions are created.</param>
    /// <returns>All possible partitions of the items in <paramref name="items"/>.</returns>
    public static IEnumerable<IEnumerable<IEnumerable<T>>> AllPartitions<T>(this IEnumerable<T> items)
    {
        return new AllPartitionsEnumerable<T>(items);
    }
//
///一组项目的所有可能分区的枚举。
/// 
///正在分区的集合中的项的类型。
公共密封类AllPartitionsEnumerable:IEnumerable
{
/// 
[DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
私人物品;
/// 
///创建并初始化类型的实例。
/// 
///要分区的项集。
public AllPartitionsEnumerable(IEnumerable项)
:base()
{
这个项目=项目;
}
/// 
///获取枚举数以在此枚举中的分区上迭代。
/// 
///一个例子。
公共IEnumerator GetEnumerator()
{
返回新的AllPartitionsEnumerator(this.items);
}
/// 
///获取枚举数以在此枚举中的分区上迭代。
/// 
///一个例子。
IEnumerator IEnumerable.GetEnumerator()
{
返回此.GetEnumerator();
}
}
/// 
///在的实例中迭代项的枚举数。
/// 
///正在分区的集合中的项的类型。
公共密封类AllPartitionsEnumerator:IEnumerator
{
///在其上创建分区的原始项集。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私人物品;
///指示此枚举数是否已被释放的标志。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私人住宅被出售;
///指示此枚举数是否处于其初始状态的标志。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私有布尔是第一位的;
///当前选择中的分区数。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私人内特北卡罗来纳州;
///一个值数组,指示分区中指定索引处的值数。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私有int[]p;
///索引数组,指示指定索引处的项属于哪个分区。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私有int[]q;
///当前分区。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私人T[][]电流;
/// 
///创建并初始化类型的实例。
/// 
///枚举分区的原始项集。
public AllPartitionsEnumerator(IEnumerable项)
:base()
{
if(null==项)
{
抛出新的异常(“项目”);
}
this.isFirst=true;
this.items=items.ToArray();
这是0.nc=0;
this.p=newint[this.items.Length];
this.q=newint[this.items.Length];
this.current=null;
}
/// 
///获取当前分区。
/// 
公共可数电流
{
得到
{
这个。CheckIfDisposed();
返回此.current;
}
}
/// 
///处置此枚举数并释放其持有的所有资源。
/// 
公共空间处置()
{
如果(此.isDisposed)
{
返回;
}
this.isDisposed=true;
this.items=null;
这个.p=null;
这个。q=null;
这是0.nc=0;
this.current=null;
this.isFirst=true;
}
/// 
///获取当前分区。
/// 
对象IEnumerator.Current
{
得到
{
返回此.Current;
}
}
/// 
///选择所有分区集中的下一项。
/// 
///如果选择了项目,则为true;如果超过最后一个元素,则为false。
公共图书馆
{
这个。CheckIfDisposed();
if(this.isFirst)
{
this.isFirst=false;
这1.nc=1;
this.p[0]=this.items.Length;
对于(int i=0;i/// <summary>
/// A enumeration of all possible partitions of a set of items.
/// </summary>
/// <typeparam name="T">The type of the items in the set being partitioned.</typeparam>
public sealed class AllPartitionsEnumerable<T> : IEnumerable<IEnumerable<IEnumerable<T>>>
{
    /// <summary></summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)]
    private IEnumerable<T> items;

    /// <summary>
    /// Creates and initializes an instance of the <see cref="AllPartitionsEnumerable{T}"/> type.
    /// </summary>
    /// <param name="items">The set of items to be partitioned.</param>
    public AllPartitionsEnumerable(IEnumerable<T> items)
        : base ()
    {
        this.items = items;
    }

    /// <summary>
    /// Gets an enumerator to iterate over the partitions in this enumeration.
    /// </summary>
    /// <returns>An instance of <see cref="IEnumerator{T}"/>.</returns>
    public IEnumerator<IEnumerable<IEnumerable<T>>> GetEnumerator()
    {
        return new AllPartitionsEnumerator<T>(this.items);
    }

    /// <summary>
    /// Gets an enumerator to iterate over the partitions in this enumeration.
    /// </summary>
    /// <returns>An instance of <see cref="IEnumerator{T}"/>.</returns>
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}
 /// <summary>
/// An enumerator to iterate over the items in an instance of <see cref="AllPartitionsEnumerable{T}"/>.
/// </summary>
/// <typeparam name="T">The type of the items in the set being partitioned.</typeparam>
public sealed class AllPartitionsEnumerator<T> : IEnumerator<IEnumerable<IEnumerable<T>>>
{
    /// <summary>The original set of items over which partitions are created.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private T[] items;

    /// <summary>Flag to indicate if this enumerator has been disposed of.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private bool isDisposed;

    /// <summary>Flag to indicate if this enumerator is in its initial state.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private bool isFirst;

    /// <summary>The number of partitions in the current selection.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int nc;

    /// <summary>An array of values indicating the number of values in the partition at the specified index.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int[] p;

    /// <summary>An array of indices indicating to which partition the item at the specified index belongs.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int[] q;

    /// <summary>The current partition.</summary>
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private T[][] current;

    /// <summary>
    /// Creates and initializes an instance of the <see cref="AllPartitionsEnumerator{T}"/> type.
    /// </summary>
    /// <param name="items">The original set of items over which partitions are enumerated.</param>
    public AllPartitionsEnumerator(IEnumerable<T> items)
        : base()
    {
        if (null == items)
        {
            throw new ArgumentNullException("items");
        }

        this.isFirst = true;
        this.items = items.ToArray();
        this.nc = 0;
        this.p = new int[this.items.Length];
        this.q = new int[this.items.Length];
        this.current = null;
    }

    /// <summary>
    /// Gets the current partition.
    /// </summary>
    public IEnumerable<IEnumerable<T>> Current
    {
        get
        {
            this.CheckIfDisposed();

            return this.current;
        }
    }

    /// <summary>
    /// Disposes of this enumerator and releases all resources held by it.
    /// </summary>
    public void Dispose()
    {
        if (this.isDisposed)
        {
            return;
        }

        this.isDisposed = true;
        this.items = null;
        this.p = null;
        this.q = null;
        this.nc = 0;
        this.current = null;
        this.isFirst = true;
    }

    /// <summary>
    /// Gets the current partition.
    /// </summary>
    object IEnumerator.Current
    {
        get
        {
            return this.Current;
        }
    }

    /// <summary>
    /// Selects the next item in the set of all partitions.
    /// </summary>
    /// <returns><c>true</c> if an item was selected; <c>false</c> if we are past the last element.</returns>
    public bool MoveNext()
    {
        this.CheckIfDisposed();

        if (this.isFirst)
        {
            this.isFirst = false;
            this.nc = 1;
            this.p[0] = this.items.Length;
            for (int i = 0; i < this.items.Length; ++i)
            {
                this.q[i] = this.nc;
            }
            this.Select();
            return true;
        }

        if (this.nc == this.items.Length )
        {
            return false;
        }

        int n = this.items.Length;
        int m = n;
        int l = this.q[m-1];

        while (this.p[l - 1] == 1)
        {
            this.q[m - 1] = 1;
            --m;
            l = this.q[m - 1];
        }

        this.nc += m - n;
        this.p[0] = this.p[0] + n - m;

        if (l == this.nc)
        {
            ++this.nc;
            this.p[this.nc - 1] = 0;
        }

        this.q[m - 1] = l + 1;
        this.p[l - 1] = this.p[l - 1] - 1;
        this.p[l] = this.p[l] + 1;

        this.Select();
        return true;
    }

    /// <summary>
    /// Resets this enumerator to its initial state.
    /// </summary>
    public void Reset()
    {
        this.CheckIfDisposed();

        this.current = null;
        this.isFirst = true;
        this.isDisposed = false;
        this.p = new int[this.items.Length];
        this.q = new int[this.items.Length];
        this.nc = 0;
    }

    /// <summary>
    /// Selects the items for the current partition.
    /// </summary>
    private void Select()
    {
        this.current = new T[this.nc][];

        for (int i = 0; i < this.nc; ++i)
        {
            int k = 0;
            this.current[i] = new T[this.p[i]];

            for (int j = 0; j < this.items.Length; ++j)
            {
                if (this.q[j] == i + 1)
                {
                    this.current[i][k] = this.items[j];
                    ++k;
                }
            }
        }
    }

    /// <summary>
    /// Checks and throws an exception if this enumerator has been disposed.
    /// </summary>
    private void CheckIfDisposed()
    {
        if (this.isDisposed)
        {
            throw new ObjectDisposedException(this.GetType().FullName);
        }
    }
}
    /// <summary>
    /// Retrieves all possible partitions of a set of items.
    /// </summary>
    /// <typeparam name="T">The type of the items in the original set.</typeparam>
    /// <param name="items">The original set of items over which partitions are created.</param>
    /// <returns>All possible partitions of the items in <paramref name="items"/>.</returns>
    public static IEnumerable<IEnumerable<IEnumerable<T>>> AllPartitions<T>(this IEnumerable<T> items)
    {
        return new AllPartitionsEnumerable<T>(items);
    }