Spread number of items equally across hours - c#

I have a variable number of items that I want to spread across a variable amount of hours. The issue I'm having is how to distribute the remainder so that the space between the "overhang" is as equal as possible. For example, if I have 13 items (X) spread across 5 hours I want to end up with
Hours: 1 2 3 4 5
---------------------------------
x x x x x
x x x x x
x x x
I'm not sure if I'm overthinking this. I'm currently checking if the number of items is greater than the number of hours. If that's true, I'm dividing (number of items/number of hours). Then I think that I have to divide (number of hours/remainder)... But for the above example: 5/3=1.6, which rounds to 2. I think that I have to use Math.Floor somehow, but I'm currently not really sure how.
For 4 items across 5 hours, I'd like to end up with the Xs
For 2 items with the Ys
For 1 item with the Zs
1 2 3 4 5
------------------------
x x x x
y y
z
The number of items and the number of hours are variable.
Okay, I think I'm currently on the right track. I'm now trying to split the bins in half and put one of the remainder in the center-bin. This repeats recursively until the remainder is 0.

EDIT: Fixed issue with even hours and items.
This is a hard problem and below is the solution. I've written solution for a completely generic problem so it works for arbitrary hours and number of items. Here's the example outputs:
Items=10, Hours=14
XX XX XX XX XX
Items=11, Hours=14
XX XXXXX XX XX
Items=12, Hours=14
XX XXXXXXXX XX
Items=16, Hours=13
XXXXXXXXXXXXX
XXX
Items=17, Hours=13
XXXXXXXXXXXXX
X X X X
Items=18, Hours=13
XXXXXXXXXXXXX
X XXX X
Items=19, Hours=13
XXXXXXXXXXXXX
X X X X X X
Items=20, Hours=13
XXXXXXXXXXXXX
X X XXX X X
Items=21, Hours=13
XXXXXXXXXXXXX
X XX X X XX X
Here's how below solution works:
Number of filled lines are trivial which you can get it by (items/hours) * hours.
The last line is where all the magic is required.
When number of remaining items are odd we want to turn on the center. If number of hours are also odd then center is well defined but otherwise we are out of luck and we would have some "imbalance" in that case.
For even items we make them in to pairs and distribute each pair in the order of balanced binary tree. This basically means we first put each pair at the end. Then next pair half way through and recursively follow the pattern. This might be the most difficult part to understand so paper and pen is recommended :).
And here's the code:
static void Main(string[] args)
{
var hours = 13;
for (var items = 16; items < 22; items++)
PrintDistribution(items, hours);
}
private static void PrintDistribution(int items, int hours)
{
Console.WriteLine(string.Format("\nItems={0}, Hours={1}", items, hours));
for (var i = 0; i < (items / hours) * hours; i++)
{
Console.Write('X');
if ((i + 1) % hours == 0)
Console.WriteLine();
}
var line = new StringBuilder(new string(' ', hours));
var remaining = items % hours;
var evens = remaining / 2;
var odd = remaining - (evens * 2);
var seq = BinaryTreeSequence(hours / 2).GetEnumerator();
for (var i = 0; i < evens; i++)
{
seq.MoveNext();
line[seq.Current] = 'X';
line[hours - seq.Current - 1] = 'X';
}
if (odd > 0)
if (hours % 2 == 0)
{
seq.MoveNext();
line[seq.Current] = 'X';
}
else
line[hours / 2] = 'X';
Console.WriteLine(line);
}
public static IEnumerable<int> BinaryTreeSequence(int count)
{
if (count > 1)
yield return count - 1;
if (count > 0)
yield return 0;
var seqQueue = new Queue<Tuple<int, int, int>>();
Enqueue(seqQueue, 0, count - 1);
for (var seqIndex = count - 2; seqIndex > 0; seqIndex--)
{
var moreNeeded = seqQueue.Count < seqIndex;
var seq = seqQueue.Dequeue();
yield return seq.Item1;
if (moreNeeded)
{
Enqueue(seqQueue, seq.Item1, seq.Item3);
Enqueue(seqQueue, seq.Item2, seq.Item1);
}
}
}
private static void Enqueue(Queue<Tuple<int, int, int>> q, int min, int max)
{
var midPoint = (min + max) / 2;
if (midPoint != min && midPoint != max)
q.Enqueue(Tuple.Create(midPoint, min, max));
}

Here's an approximate solution. It returns tuples with the zero-based index, and the item. (I assumed the items might be important, and not just dummy values like your xs) It doesn't choose the optimal spacing in some cases, but I think it'll always be close (i.e. gaps no more than 1 larger than necessary), and always return the correct number of items.
public static IEnumerable<Tuple<int, T>> SplitItems<T>(IEnumerable<T> items, int count)
{
var itemList = items.ToList();
int lastRowCount = itemList.Count % count;
int wholeRowItemCount = itemList.Count - lastRowCount;
// return full rows: 0 <= i < wholeRowCount * count
for (int i = 0; i < wholeRowItemCount; i++)
{
yield return Tuple.Create(i % count, itemList[i]);
}
if (lastRowCount > 0)
{
//return final row: wholeRowCount * count <= i < itemList.Count
double offset = (double)count / (lastRowCount + 1);
for (double j = 0; j < lastRowCount; j++)
{
int thisIntPos = (int)Math.Round(j * count / (lastRowCount + 1) + offset, MidpointRounding.AwayFromZero);
yield return Tuple.Create(thisIntPos, itemList[wholeRowItemCount + (int)j]);
}
}
}
As an example of how to use it:
Console.WriteLine(string.Join("\r\n", SplitItems(Enumerable.Range(1, 12), 5)));
// prints
(0, 1)
(1, 2)
(2, 3)
(3, 4)
(4, 5)
(0, 6)
(1, 7)
(2, 8)
(3, 9)
(4, 10)
(2, 11)
(3, 12)
(this is suboptimal because the last line has items at 2-3 and empty spaces/gaps at 0-1 and 4, while your solution with ys only has gaps of size 1)
Also, though it doesn't match your example (which would be 0, 2, 4 in my zero-based indexing), the following example satisfies the algorithm that you've defined so far, since it's minimized the gap size. (1-size gaps at indices 0 and 2, instead of yours, which has the gaps at 1 and 3) If 0, 2, 4 is indeed better than 1, 3, 4, you need to decide why exactly, and add that to your algorithm definition.
Console.WriteLine(string.Join("\r\n", SplitItems(Enumerable.Range(1, 3), 5)));
// prints
(1, 1)
(3, 2)
(4, 3)
Actually, this is a sort of restricted partition problem. For dividing d items across h hours, you want to find a partition of h-d with no more than h-d parts where max(parts) is the smallest it can be. E.g. dividing 2 items among 5 hours: the optimal solution is 1+1+1, because it has no more than 3 parts, and max(parts) == 1, which is the best you can do. As an example without a single solution, 3 items among 5 hours has 1+1, but there are different ways to arrange it, including 0,2,4, 1,3,4, and 0,2,3.

Related

Is it okay to exit a loop when an exception is thrown?

I solved a task on Hackerrank.com, where the problem was like this:
You have an Array. This Array contains numbers.
Now you enter two numbers:
The first one describes a sum
The second one describes the amount of indexes (sequence length) you add together
In the end you get the amount of sequences whose sum is your defined number
For example:
Your array is [ 1, 2, 3, 4], your sum is 3 and your sequence length is 2.
Now you take the first two indexes and output the sum: [1, 2] = 3.
This is equal to your sum, so now you have found one sequence.
The next sequence is [ 2, 3 ] = 5. This is not equal to 3, so your sequence counter stays 1.
The last sequence is [3, 4] = 7. This is also not equal to 3 and in the end, you found one sequence.
I wrote this code for that:
static int GetSequences(List<int> s, int d, int m)
{
//m = segment-length
//d = sum
int count = 0;
int j = 0;
int k = 0;
do
{
try
{
List<int> temp = new List<int>();
for (int i = 0; i < m; i++)
{
temp.Add(s[i + k]);
}
if (temp.Sum() == d)
{
count++;
}
j++;
k++;
}
catch (ArgumentOutOfRangeException)
{
break;
}
} while (true);
return count;
}
As I didn't know how often I have to count
(For example a 6-Length-Array with a sequence-length of 3 has 4 sequences (1,2,3 | 2,3,4 | 3,4,5 | 4,5,6)),
I am stopping the while loop when the index is out of range. but I'm not sure if this solution is okay. Not just with program speed, but also with code cleanliness. Is this code acceptable, or is it better to use a for loop, which loops for example exactly 4 times for a 6-length array with 3-Length sequences?
It's not recommended, no. Exceptions should be reserved for stuff that isn't supposed to happen, not flow control or validation.
What you want is to use conditional logic (if statements) and the break keyword.
Also, codereview.stackexchange.com is better suited for these kinds of questions.
It would be better to fix your code so that it doesn't routinely throw exceptions:
You sum each of these segments:
0 1 2 3 start = 0
| | summing indexes: 0, 1
+--+
0 1 2 3 start = 1
| | summing indexes: 1, 2
+--+
0 1 2 3 start = 2
| | summing indexes: 2, 3
+--+
The bracket starts at the index start, and has a size of m. The length of s is given by s.Count. Therefore we want to keep going until start + m == s.Count.
(I always find it's useful to draw these things out, and put sample numbers in, in order to make sure you've got the maths right. In the sample above, you can see that we stop when start (2) + m (2) == the array size (4))
static int GetSequences(List<int> s, int d, int m)
{
//m = segment-length
//d = sum
int count = 0;
for (int start = 0; start + m <= s.Count; start++)
{
List<int> temp = new List<int>();
for (int i = 0; i < m; i++)
{
temp.Add(s[start + i]);
}
if (temp.Sum() == d)
{
count++;
}
}
return count;
}
However, you can improve your code a bit:
Use meaningful variable names
Don't create a new temporary list each time, just to sum it
Check your inputs
static int GetSequences(List<int> numbers, int targetSum, int segmentLength)
{
if (numbers == null)
throw new ArgumentNullException(nameof(numbers));
if (segmentLength > numbers.Count)
throw new ArgumentException("segmentLength must be <= numbers.Count");
int count = 0;
for (int start = 0; start + segmentLength <= numbers.Count; start++)
{
int sum = 0;
for (int i = 0; i < segmentLength; i++)
{
sum += numbers[start + i];
}
if (sum == targetSum)
{
count++;
}
}
}
Usually except for switch/case there is often no real reason to use break.
Also an exception MUST be as the name says exceptional, so it MUST NOT be a part of your logic.
As said Jeppe you can use the methods and attributes the framework provides you to do as you like.
Here s.Count seems to be the way to go.
int[] arr = new[] { 1, 2, 1, 2 };
// Sum and len are given by the task.
// 'last' is the last index where we should stop iterating.
int sum = 3, len = 2, last = arr.Length - len;
// One of the overloads of Where accepts index, i.e. the position of element.
// 1) We check that we don't go after our stop-index (last).
// 2) Avoid exception by using '&&'.
// 3) We use C# 8 Range (..) to get the slice of the numbers we need:
// we start from the current position (index) till then index,
// calculated as current index + length given by the task.
// 4) Sum all the numbers in the slice (Sum()) and compare it with the target sum,
// given by the task (== sum).
// 5) The count of all matches (Count()) is the sought amount of sequences.
int count = arr.Where((z, index) => index <= last && arr[index..(index+len)].Sum() == sum).Count();

Formula to produce 1 for positive integers and 0 otherwise

I have a function (f) the takes a number of items (n) and a number of columns (c) and returns the optimal layout as an array of items per column. I define optimal as being as square as possible. So f(4,4) would return [4,4,4,4], f(17,4) would return [5,4,4,4], and f(1,4) would return [1,0,0,0]. My function works correctly in all my tests, but I am looking to alter it. My desire to do this is not because I am looking increase performance. I just want to do this, because I am experimenting and want to learn different techniques.
Here is the code:
public static int[] f(int n, int c){
int[] a = new int[c];
if(c>0 && n>=0){
int opt = (n-(n%c))/c;
n = n - (opt*c);
for(int i = 0;i<a.Length;i++){
a[i] = opt;
if(n>0){
a[i]++;
n--;
}
}
}
return a;
}
The function works by first determining the optimal number of items per col:
int opt = (n-(n%c))/c;
So f(17,4) would yield 4, f(19,4) would also yield 4, and f(3,4) would yield 0. Then the reminder is calculated:
n = n - (opt*c);
I then loop through the array (of length c) and assign a[i] equal to the optimal value. Finally, if the reminder is greater than 0 I add 1 to a[i]. This equally distributes the reminder across the array. This is the part I would like to alter.
Instead of checking if(n>0) and adding 1 to the array is there a formula I could use that might look like:
a[i] = opt + n*?????;
So n*??? would always equal 1 if n is greater than 0 and 0 if n is 0 or less?
The simple answer to your question is to use an expression with the conditional operator:
a[i] = opt + (n > 0 ? 1 : 0);
(n > 0 ? 1 : 0) will be 1 if n is greater than 0, and 0 otherwise.
On that note, there is a clearer and more concise way to implement your algorithm.
Determine the total number of items that can be distributed evenly between the slots (call this average). This has the value n / c (using integer division).
Determine the remainder that would be left after those are evenly distributed (call this remainder). This has the value n % c.
Put the value average + 1 in the first remainder slots, and put average in the rest.
The implementation for this would be:
public static int[] Distribute(int total, int buckets)
{
if (total < 0) { throw new ArgumentException("cannot be less than 0", "total"); }
if (buckets < 1) { throw new ArgumentException("cannot be less than 1", "buckets"); }
var average = total / buckets;
var remainder = total % buckets;
var array = new int[buckets];
for (var i = 0; i < buckets; i++)
{
array[i] = average + (i < remainder ? 1 : 0);
}
return array;
}
And the obligatory Linq version:
public static int[] DistributeLinq(int total, int buckets)
{
if (total < 0) { throw new ArgumentException("cannot be less than 0", "total"); }
if (buckets < 1) { throw new ArgumentException("cannot be less than 1", "buckets"); }
var average = total / buckets;
var remainder = total % buckets;
return Enumerable.Range(1, buckets)
.Select(v => average + (v <= remainder ? 1 : 0))
.ToArray();
}
If you want to use a formula:
Math.Max(n - Math.Abs(n - 1), 0)
should do the trick.
Your code should look like:
a[i] = opt + Math.Max(n - Math.Abs(n - 1), 0)
Another option for a formula would be
Math.Max(Math.Sign(n), 0)
If you are looking for a mathematical formula, I'm not sure you're going to find it as the function is discontinuous at n = 0.
How about a simple function which outputs int on a bool expression?
int IsPositive(int number)
{
//if number is > 0 return integer one (1), else return integer zero (0)
return number > 0 ? 1 : 0;
}
You can then use this in your code as such:
a[i] = opt + IsPositive(n);
//opt + 1 if n > 0, opt + 0 if n <= 0
Update: per your comment, you can just move the evaluation inline:
a[i] = opt + (n > 0 ? 1 : 0);
As an aside: you should make #BradleyDotNET's comment one of your programming mottos.

Solving modulo equations programmatically

My goal is to implement a (simple) check digit alglorithm as described Here
My implemantion is the following but I am not sure if it is optimal:
private int CheckDigit(string SevenDecimal)
{
///Get UPC check digit of a 7-digit URI
///Add odd and multiply by 3 =Odds
///Add even =Evens
///Add Odds+Evens=sum
///Check digit is the number that makes Sum divisble by 10
int Odds = 0;
int Evens = 0;
int sum = 0;
int index = 0;
foreach (char digit in SevenDecimal)
{
index++;
int Digit = int.Parse(digit.ToString());
if (index % 2 == 0)
{
Evens +=Digit;
}
else
{
Odds +=Digit;
}
}
Odds = Odds * 3;
sum = Odds + Evens;
for (int i = 0; i < 10; i++) ///Brute force way check for better implementation
{
int Localsum;
Localsum = sum + i;
if (Localsum % 10 == 0)
{
return i;
}
}
return -1;//error;
}
My main concern is in the final for loop which as I describe is totallly brute.
Is there a better way to obtaining the check digit?
More precisely which is the best way to solve programmatically, the equation:
(sum+x)%10=0 //solve for x
To find "how much i you have to add to make the last digit of a number a 0", you can subtract from 10:
int checkDigit = (10 - (sum % 10)) % 10;
The second modulo is used for the special case when sum % 10 == 0, because 10 - 0 = 10
You are asking the wrong question. The expression is not one of equivalence thus x is not a value. The solution is that x is an infinite number of values each of which correctly solve the equation. As such you don't really want to solve for x but just check if x is in this solution space. You can check this simply with:
remainder = base - (sum % base)
You can then test if x sums up to the remainder with:
if (x % base === base - (sum % base))
{
// (sum + x) % base = 0 is true
}
Replace base with 10and you'll have it.

Explain the Peak and Flag Algorithm

EDIT
Just was pointed that the requirements state peaks cannot be ends of Arrays.
So I ran across this site
http://codility.com/
Which gives you programming problems and gives you certificates if you can solve them in 2 hours. The very first question is one I have seen before, typically called the Peaks and Flags question. If you are not familiar
A non-empty zero-indexed array A consisting of N integers is given. A peak is an array element which is larger than its neighbours. More precisely, it is an index P such that
0 < P < N − 1 and A[P − 1] < A[P] > A[P + 1]
.
For example, the following array A:
A[0] = 1
A[1] = 5
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2
has exactly four peaks: elements 1, 3, 5 and 10.
You are going on a trip to a range of mountains whose relative heights are represented by array A. You have to choose how many flags you should take with you. The goal is to set the maximum number of flags on the peaks, according to certain rules.
Flags can only be set on peaks. What's more, if you take K flags, then the distance between any two flags should be greater than or equal to K. The distance between indices P and Q is the absolute value |P − Q|.
For example, given the mountain range represented by array A, above, with N = 12, if you take:
two flags, you can set them on peaks 1 and 5;
three flags, you can set them on peaks 1, 5 and 10;
four flags, you can set only three flags, on peaks 1, 5 and 10.
You can therefore set a maximum of three flags in this case.
Write a function that, given a non-empty zero-indexed array A of N integers, returns the maximum number of flags that can be set on the peaks of the array.
For example, given the array above
the function should return 3, as explained above.
Assume that:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [0..1,000,000,000].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N), beyond input storage (not counting the
storage required for input arguments).
Elements of input arrays can be modified.
So this makes sense, but I failed it using this code
public int GetFlags(int[] A)
{
List<int> peakList = new List<int>();
for (int i = 0; i <= A.Length - 1; i++)
{
if ((A[i] > A[i + 1] && A[i] > A[i - 1]))
{
peakList.Add(i);
}
}
List<int> flagList = new List<int>();
int distance = peakList.Count;
flagList.Add(peakList[0]);
for (int i = 1, j = 0, max = peakList.Count; i < max; i++)
{
if (Math.Abs(Convert.ToDecimal(peakList[j]) - Convert.ToDecimal(peakList[i])) >= distance)
{
flagList.Add(peakList[i]);
j = i;
}
}
return flagList.Count;
}
EDIT
int[] A = new int[] { 7, 10, 4, 5, 7, 4, 6, 1, 4, 3, 3, 7 };
The correct answer is 3, but my application says 2
This I do not get, since there are 4 peaks (indices 1,4,6,8) and from that, you should be able to place a flag at 2 of the peaks (1 and 6)
Am I missing something here? Obviously my assumption is that the beginning or end of an Array can be a peak, is this not the case?
If this needs to go in Stack Exchange Programmers, I will move it, but thought dialog here would be helpful.
EDIT
Obviously my assumption is that the beginning or end of an Array can
be a peak, is this not the case?
Your assumption is wrong since peak is defined as:
0 < P < N − 1
When it comes to your second example you can set 3 flags on 1, 4, 8.
Here is a hint: If it is possible to set m flags, then there must be at least m * (m - 1) + 1 array elements. Given that N < 100,000, turning the above around should give you confidence that the problem can be efficiently brute-forced.
Here is a hint: If it is possible to set m flags, then there must be
at least m * (m - 1) + 1 array elements. Given that N < 100,000,
turning the above around should give you confidence that the problem
can be efficiently brute-forced.
No, that is wrong. Codility puts custom solutions through a series of tests, and brute forcing can easily fail on time.
I give here my solution of the task that makes 100% score (correctness and performance) in codility, implemented in C++. To understand the solution you must realize for a given distance of indexes (for example, when first peak starts at index 2 and the last peak at index 58 the distance is 56), that contains n peaks there is an upper limit for the maximal number of peaks that can hold flags according to condition described in the task.
#include <vector>
#include <math.h>
typedef unsigned int uint;
void flagPeaks(const std::vector<uint> & peaks,
std::vector<uint> & flaggedPeaks,
const uint & minDist)
{
flaggedPeaks.clear();
uint dist = peaks[peaks.size() - 1] - peaks[0];
if (minDist > dist / 2)
return;
flaggedPeaks.push_back(peaks[0]);
for (uint i = 0; i < peaks.size(); ) {
uint j = i + 1;
while (j < (peaks.size()) && ((peaks[j] - peaks[i]) < minDist))
++j;
if (j < (peaks.size()) && ((peaks[j] - peaks[i]) >= minDist))
flaggedPeaks.push_back(peaks[j]);
i = j;
}
}
int solution(std::vector<int> & A)
{
std::vector<uint> peaks;
uint min = A.size();
for (uint i = 1; i < A.size() - 1; i++) {
if ((A[i] > A[i - 1]) && (A[i] > A[i + 1])) {
peaks.push_back(i);
if (peaks.size() > 1) {
if (peaks[peaks.size() - 1] - peaks[peaks.size() - 2] < min)
min = peaks[peaks.size() - 1] - peaks[peaks.size() - 2];
}
}
}
// minimal distance between 2 peaks is 2
// so when we have less than 3 peaks we are done
if (peaks.size() < 3 || min >= peaks.size())
return peaks.size();
const uint distance = peaks[peaks.size() - 1] - peaks[0];
// parts are the number of pieces between peaks
// given n + 1 peaks we always have n parts
uint parts = peaks.size() - 1;
// calculate maximal possible number of parts
// for the given distance and number of peaks
double avgOptimal = static_cast<double>(distance) / static_cast<double> (parts);
while (parts > 1 && avgOptimal < static_cast<double>(parts + 1)) {
parts--;
avgOptimal = static_cast<double>(distance) / static_cast<double>(parts);
}
std::vector<uint> flaggedPeaks;
// check how many peaks we can flag for the
// minimal possible distance between two flags
flagPeaks(peaks, flaggedPeaks, parts + 1);
uint flags = flaggedPeaks.size();
if (flags >= parts + 1)
return parts + 1;
// reduce the minimal distance between flags
// until the condition fulfilled
while ((parts > 0) && (flags < parts + 1)) {
--parts;
flagPeaks(peaks, flaggedPeaks, parts + 1);
flags = flaggedPeaks.size();
}
// return the maximal possible number of flags
return parts + 1;
}

Evenly divide in c#

In c# how do I evenly divide 100 into 7?
So the result would be
16
14
14
14
14
14
14
The code below is incorrect as all 7 values are set to 15 (totalling 105).
double [] vals = new double[7];
for (int i = 0; i < vals.Length; i++)
{
vals[i] = Math.Ceiling(100d / vals.Length);
}
Is there an easy way to do this in c#?
Thanks
To get my suggested result of 15, 15, 14, 14, 14, 14, 14:
// This doesn't try to cope with negative numbers :)
public static IEnumerable<int> DivideEvenly(int numerator, int denominator)
{
int rem;
int div = Math.DivRem(numerator, denominator, out rem);
for (int i=0; i < denominator; i++)
{
yield return i < rem ? div+1 : div;
}
}
Test:
foreach (int i in DivideEvenly(100, 7))
{
Console.WriteLine(i);
}
Here you go:
Func<int, int, IEnumerable<int>> f = (a, b) =>
Enumerable.Range(0,a/b).Select((n) => a / b + ((a % b) <= n ? 0 : 1))
Good luck explaining it in class though :)
Since this seems to be homework, here is a hint and not the full code.
You are doing Math.Ceiling and it converts 14.28 into 15.
The algorithm is this
Divide 100 by 7, put the result in X
Get the highest even number below X and put this in Y.
Multiply Y by 7 and put the answer in Z.
Take Z away from 100.
The answer is then 6 lots of Y plus whatever the result of step 4 was.
This algorithm may only work for this specific instance.
I'm sure you can write that in C#
Not sure if this is exactly what you are after, but I would think that if you use Math.ceiling you will always end up with too big a total. Math.floor would underestimate and leave you with a difference that can be added to one of your pieces as you see fit.
For example by this method you might end up with 7 lots of 14 giving you a remainder of 2. You can then either put this 2 into one of your pieces giving you the answer you suggested, or you could split it out evenly and add get two pieces of 15 (as suggested in one of the comments)
Not sure why you are working with doubles but wanting integer division semantics.
double input = 100;
const int Buckets = 7;
double[] vals = new double[Buckets];
for (int i = 0; i < vals.Length; i++)
{
vals[i] = Math.Floor(input / Buckets);
}
double remainder = input % Buckets;
// give all of the remainder to the first value
vals[0] += remainder;
example for ints with more flexibility,
int input = 100;
const int Buckets = 7;
int [] vals = new int[Buckets];
for (int i = 0; i < vals.Length; i++)
{
vals[i] = input / Buckets;
}
int remainder = input % Buckets;
// give all of the remainder to the first value
vals[0] += remainder;
// If instead you wanted to distribute the remainder evenly,
// priority to first
for (int r = 0; r < remainder;r++)
{
vals[r % Buckets] += 1;
}
It is worth pointing out that the double example may not be numerically stable in that certain input values and bucket sizes could result in leaking fractional values.

Categories

Resources