Frage

I need to distribute a remainder of items over a fixed number of days. e.g. say I have 197 items and 75 days to distribute them over. If I display 2 items for 75 days then I have 47 items not displayed. How do I distribute the remaining 47 items over the 75 days evenly so that I will get a sequence like 2,3,3,2,3,3,2,2,3.... i.e. the 3's are evenly distributed over the whole display. This is what I have so far

const double num = (double)197/75;
double temp = num;
var list = new List<int>();
for (var t = 1; t <= days; t++)
{
    var intPart = int.Parse(Math.Truncate(temp).ToString());

    list.Add(intPart);

    var remainder = num - intPart;

    temp = num + remainder;
}

but I only end up with 187 items displayed. I'm missing 10.

War es hilfreich?

Lösung

The original answer that turned out to give suboptimal results in some cases, as noted by AlexD:

int numItems = 197;
int numDays = 75;
var list = new List<int>();
for (int t = 0; t < numDays; t++)
{
    int numItemsInDay = ((t+1)*numItems+numDays/2)/numDays - (t*numItems+numDays/2)/numDays;
    list.Add(numItemsInDay);
}

The idea is that every item goes into the day defined by the rounded value of itemIndex*numDays/numItems, and you can calculate the number of items in a day directly, without keeping track of previous items.


Another approach.

To spread numItems items among numDays days as evenly as possible, you need to group the days into spans of days with floor(numItems/numDays) items and spans of days with ceil(numItems/numDays) items, spreading the spans as evenly as possible. So the problem can be solved by recursively reducing the number of days to the number of spans.

static List<int> Spread(int numDays, int numItems)
{
    List<int> result = new List<int>();
    if (numDays <= 1)
    {
        if (numDays == 1)
            result.Add(numItems);
        return result;
    }
    int numItemsInDayLower = numItems/numDays;
    int numItemsInDayHigher = numItemsInDayLower+1;
    int numDaysHigher = numItems - numItemsInDayLower * numDays;
    int numDaysLower = numDays-numDaysHigher;
    int numSpansLower = numDaysLower > numDaysHigher ? numDaysHigher + 1 : numDaysLower;
    int numSpansHigher = numDaysHigher > numDaysLower ? numDaysLower + 1 : numDaysHigher;
    bool isStartingFromSpanLower = numDaysLower > numDaysHigher;
    List<int> spanLehgthsLower = Spread(numSpansLower, numDaysLower);
    List<int> spanLehgthsHigher = Spread(numSpansHigher, numDaysHigher);
    for (int iSpan = 0; iSpan < spanLehgthsLower.Count + spanLehgthsHigher.Count; iSpan++)
    {
        if ((iSpan % 2 == 0) == isStartingFromSpanLower)
        {
            for (int i = 0; i < spanLehgthsLower[iSpan/2]; i++)
                result.Add(numItemsInDayLower);
        }
        else
        {
            for (int i = 0; i < spanLehgthsHigher[iSpan/2]; i++)
                result.Add(numItemsInDayHigher);
        }
    }
    return result;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top