Reputation:
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
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.
Upvotes: 0
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
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
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
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
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
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
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
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