Reputation: 13
I've got a problem I can't seem to crack. It's not that easy to explain so I'll do my best :
I have a really big array of values I have already sorted :
[ 2, 8, 26, ..., 1456, 1879, ..., 7812, 9614, ..., 20 408, 26 584 ]
I have 8 empty "silos" (kind of like an array) with unlimited capacity.
My goal is to fill those silo with all my values in order to make them as balanced as possible. When I say "balanced", I mean that I want the sum of all the values in a silo to be almost equal to one another.
For example, if my silo 1 has a total sum of 52 000
and my silo 8 has a sum of 30 000
then it's not good. I'd rather have something like 41 000
and 43 500
if possible.
I've already done a round Robin, but it doesn't seem precise enough because I get a quite big difference between my silos. I've looked up bin-packing also but it doesn't seem appropriate to me.
Thank you for any help or advice you may provide!
Upvotes: 1
Views: 200
Reputation: 13394
Optimization problems are never easy, but since you want to minimize the deviation from the average you simply iterate your values from highest to lowest value and add it to the silo with the lowest sum. That way you don't waste too much time on optimization and should (depending on your values) have a relatively good result.
// Generate some random data
int[] values = new int[1000];
Random r = new Random();
for (int i = 0; i < values.Length; i++)
{
values[i] = r.Next(1, 30000);
}
// Initialize silos
const int siloCount = 8;
List<int>[] result = new List<int>[siloCount];
for (int i = 0; i < siloCount; i++)
{
result[i] = new List<int>();
}
int[] sums = new int[siloCount];
int[] indices = Enumerable.Range(0, siloCount).ToArray();
// Iterate all values in descending order
foreach (int value in values.OrderByDescending(i => i).ToList())
{
// Find silo with lowest sum (or one of them)
int siloIndex = indices.First(i => sums[i] == sums.Min());
// Add to collection and sum - so we don't have to call .Sum() every iteration
sums[siloIndex] += value;
result[siloIndex].Add(value);
}
Debug.WriteLine(String.Join("\r\n", result.Select(s => s.Sum())));
Upvotes: 2