Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Every possible combination of X split into N stacks

I am sure this problem has a formal name, and knowing that name would probably help me find the solution, but I don't know it, and wording the problem for Google keeps pointing me to the Knapsack Problem, which isn't the same thing.

I want to take some value X and find every possible combination of splitting that value into N stacks of whole integers.

In case my wording is confusing, here is an example of X = 4, N = 3

Stack -> 1 | 2 | 3 |
----------------------
#1-----> 4 | 0 | 0 |
----------------------
#2-----> 3 | 1 | 0 |
----------------------
#3-----> 2 | 1 | 1 |
----------------------
#4-----> 2 | 2 | 0 |

Duplication is acceptable, since its easy to remove, but ideally it would not be calculated. An algorithm for solving the problem would be perfect, but even finding out of the problem has a name would make research easier. Thanks.

like image 642
Kyeotic Avatar asked Jun 13 '12 16:06

Kyeotic


3 Answers

These are in fact integer partitions as a deleted answer remarks. Using Mathematica:

IntegerPartitions[4, 3] // PadRight //Grid

Output:

4   0   0
3   1   0
2   2   0
2   1   1

I could not find a C# implementation but here are a couple of related questions:

Elegant Python code for Integer Partitioning

Integer Partition in Java

Algorithm for generating integer partitions


Google hits:

Integer Partition Algorithm by Jerome Kelleher

Integer Partition Algorithm by Daniel Scocco

Fast Algorithms for Generating Integer Partitions (PDF) (looks heavy-duty)

Stony Brook Algorithm Repository - Partitions

like image 162
Mr.Wizard Avatar answered Nov 09 '22 20:11

Mr.Wizard


This seems to do the trick:

vector<vector<int> > partitions(int X, int N, int Y)
{
    vector<vector<int> > v;
    if(X<=1 || N==1)
    {
        if(X<=Y)
        {
            v.resize(1);
            v[0].push_back(X);
        }
        return v;
    }
    for(int y=min(X, Y); y>=1; y--)
    {
        vector<vector<int> > w = partitions(X-y, N-1, y);
        for(int i=0; i<w.size(); i++)
        {
          w[i].push_back(y);
          v.push_back(w[i]);
        }
    }
    return v;


   }

int main()
{
    vector<vector<int> > v = partitions(5, 3, 5);
    int i;
    for(i=0; i<v.size(); i++)
    {
        int x;
        for(x=0; x<v[i].size(); x++)
            printf("%d ", v[i][x]);
        printf("\n");
    }
    return 0;
}
like image 22
Eugene Smith Avatar answered Nov 09 '22 21:11

Eugene Smith


This is user434507's answer in C#:

class Program
{
    static void Main(string[] args)
    {
        var v = Partitions(5, 3, 5);

        for (int i = 0; i < v.Count; i++)
        {
            for (int x = 0; x < v[i].Count; x++)
                Console.Write(v[i][x] + " "); 
            Console.WriteLine();
        }
    }

    static private List<List<int>> Partitions(int total, int stacks, int max)
    {
        List<List<int>> partitions = new List<List<int>>();

        if (total <= 1 || stacks == 1)
        {
            if (total <= max)
            {
                partitions.Add(new List<int>());
                partitions[0].Add(total);
            }

            return partitions;
        }
        for (int y = Math.Min(total, max); y >= 1; y--)
        {
            var w = Partitions(total - y, stacks - 1, y);
            for (int i = 0; i < w.Count; i++)
            {
                w[i].Add(y);
                partitions.Add(w[i]);
            }
        }

        return partitions;
    }
}
like image 45
Alex Peck Avatar answered Nov 09 '22 19:11

Alex Peck