user1395543
user1395543

Reputation:

Split number into equal sized groups

Using this example:

var amount = x;
var maxPerGroup = y;
var amountGroups = Ceiling(amount/maxPerGroup);

Can someone help me how to split the Amount into AmountGroups with a max amount per group of maxAmount? These groups have to be almost the same size.

For example: amount = 45; maxPerGroup = 15; amountGroups = 3;

Result: 15 15 15

I am using C# as language.

Thanks in advance!

Upvotes: 7

Views: 13320

Answers (9)

Corrpside
Corrpside

Reputation: 99

private void button2_Click(object sender, EventArgs e)
    {
        // I wanted to get count from a datagridview (x)
        // and then split into groups based on the 
        // count from a combobox (n). In my example my
        // grid had 1771 rows and was split into: 25 groups
        // (4x of 70 and 21x of 71)

        // Driver code
        int x = myDataGridView.Rows.Count; //1771  
        int n = assemblies_cmbbox.Items.Count; //25

        split(x, n);
        //split(amount, maxPerGroup);
    }

    // Function that prints
    // the required sequence
    private void split(int x, int n)
    {

        // If we cannot split the
        // number into exactly 'N' parts
        if (x < n)
            Debug.WriteLine("-1 ");
        // If x % n == 0 then the minimum
        // difference is 0 and all
        // numbers are x / n
        else if (x % n == 0)
        {
            for (int i = 0; i < n; i++)
                Debug.WriteLine((x / n) + " ");

        }
        else
        {
            // upto n-(x % n) the values
            // will be x / n
            // after that the values
            // will be x / n + 1
            int zp = n - (x % n);
            int pp = x / n;
            for (int i = 0; i < n; i++)
            {

                if (i >= zp)
                    Debug.WriteLine((pp + 1) + " ");
                else
                    Debug.WriteLine(pp + " ");
            }
        }
    }

All credits to Sachin.

Visit https://www.geeksforgeeks.org/split-the-number-into-n-parts-such-that-difference-between-the-smallest-and-the-largest-part-is-minimum/

Upvotes: 0

Martin Domansk&#253;
Martin Domansk&#253;

Reputation: 11

private static int[] DistributeIntoGroups(int sum, int groupsCount)
{
    var baseCount = sum / groupsCount;
    var leftover = sum % groupsCount;
    var groups = new int[groupsCount];

    for (var i = 0; i < groupsCount; i++)
    {
        groups[i] = baseCount;
        if (leftover > 0)
        {
            groups[i]++;
            leftover--;
        }
    }

    return groups;
}

Upvotes: 1

usman tahir
usman tahir

Reputation: 301

Divide an integer into groups

public class Program
    {
        static void Main(string[] args)
        {
            List<int> results = DistributeInteger(20, 3).ToList();//output: 7,7,6
            foreach (var result in results)
            {
                Console.WriteLine(result);
            }
            Console.Read();
        }

        public static IEnumerable<int> DistributeInteger(int total, int divider)
        {
            if (divider == 0)
                yield return 0;

            int rest = total % divider;
            double result = total / (double)divider;

            for (int i = 0; i < divider; i++)
            {
                if (rest-- > 0)
                    yield return (int)Math.Ceiling(result);
                else
                    yield return (int)Math.Floor(result);
            }

        }
    }

Upvotes: 1

azuneca
azuneca

Reputation: 1063

    // For separating a collection into ranges
    static List<List<T>> Split<T>(List<T> source, int size)
    {
        // TODO: Prepopulate with the right capacity
        List<List<T>> ret = new List<List<T>>();
        for (int i = 0; i < source.Count; i += size)
        {
            ret.Add(source.GetRange(i, Math.Min(size, source.Count - i)));
        }
        return ret;
    }

    // For separating an int into a Tuple range
    static List<Tuple<int, int>> Split(int source, int size)
    {
        var ret = new List<Tuple<int, int>>();
        for (int i = 0; i < source; i += size)
        {
            ret.Add(new Tuple<int, int>(i, (i + Math.Min(size, source - i))));
        }
        return ret;
    }

Upvotes: 0

Liquid
Liquid

Reputation: 1871

NOTE not exact c# just to give you the idea.

I think you are looking for a way to grammatically divide a number in different groups. Without knowing how big the groups are and a random amount of groups.

so let's say x = 30 y = 15. 30/15 = 3 groups of 15 and let's say x= 43 so the number should be like ? 14 14 15

groups (since you already have this calculated correctly)(should be a double)
//   maxPerGroup = y
membersPerGroup = floor(amount/groups)



List a = new List
//Is the leftover value of the modulus
leftover = amount%groups;
//Loops for each group
for(int i=0;i<groups;i++){


//If there is a left over value
if(leftover>0){
  a.Add(membersPerGroup +1);
  leftover--;
}else{
  a.Add(membersPerGroup );
}

}

I could write in proper c# but It seems that you found the proper code for it

Upvotes: 1

Marek Musielak
Marek Musielak

Reputation: 27132

There are many ways of splitting the amount between groups. It all depends on whether the only factor is the number of groups or if there are any other factors. See:

    static void Main(string[] args)
    {
        List<int> list1 = Split1(48, 15); // result is: 15, 15, 15, 3
        List<int> list2 = Split2(48, 15); // result is 12, 12, 12, 12
    }

    public static List<int> Split1 (int amount, int maxPerGroup)
    {
        int amountGroups = amount / maxPerGroup;

        if (amountGroups * maxPerGroup < amount)
        {
            amountGroups++;
        }

        List<int> result = new List<int>();
        for (int i = 0; i < amountGroups; i++)
        {
            result.Add(Math.Min(maxPerGroup, amount));
            amount -= Math.Min(maxPerGroup, amount);
        }
        return result;
    }

    public static List<int> Split2 (int amount, int maxPerGroup)
    {
        int amountGroups = amount / maxPerGroup;

        if (amountGroups * maxPerGroup < amount)
        {
            amountGroups++;
        }

        int groupsLeft = amountGroups;
        List<int> result = new List<int>();
        while (amount > 0)
        {
            int nextGroupValue = amount / groupsLeft;
            if (nextGroupValue * groupsLeft < amount)
            {
                nextGroupValue++;
            }
            result.Add(nextGroupValue);
            groupsLeft--;
            amount -= nextGroupValue;
        }
        return result;
    }

Upvotes: 4

Mahdi Tahsildari
Mahdi Tahsildari

Reputation: 13582

int amount = x;
int maxPerGroup = y;
int amountGroups = new int[Ceiling(amount/maxPerGroup)];
for(int i=0; i<maxPerGroup; i++)
{
    if(x>maxPerGroup)
    {
        amountGroups[i]= maxPerGroup;
        x = x-maxPerGroup;
    }
    else
    {
        amountGroups[i] = x;
        x =0;
    }
}

Upvotes: -2

Colin D
Colin D

Reputation: 5661

simple non-optimized solution:

int i = amount;
int j = 0;
int [] groups = new  int[amountGroups];
while(i > 0) {
   groups[j] += 1;
   i--;
   j = (j+1)%amountGroups;
}

Upvotes: 1

Thom Smith
Thom Smith

Reputation: 14086

number of groups := ceiling(total / max group size)
number per group := floor(total / number of groups)
rem = total % number per group

You will have rem groups with number per group + 1 and number of groups - rem groups with number per group.

EDIT: Example:

total := 50
max group size := 15
number of groups := ceiling(50 / 15) // 4
number per group := floor(50 / 4) // 12
rem := 50 % 12 // 2

2 groups with 13 and 2 with 12.

Upvotes: 3

Related Questions