C# 2 Array Split Amount Question - c#

My question is i have a certain money amount, lets say 552.
I wish to split that in its coins/bills => So the result would for example be 1x 500 1x 50 1x 2
I have made 2 arrays for this:
double[] CoinValue = {500, 200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01};
uint[] CoinAmount = new uint[CoinValue.Length];
My problem is how exactly do i "tell" the array the value for 500 should be 1 in the countAmount array.=> 1. So if i have 1000 the array CoinAmount array would know it would need to hold 2 as value(2x500 = 1000).
So my end result would be something like this, giving the amount of coin/bills:
1 x 500
1 x 50
1 x 2
.......
Thanks in advance.

Don't use doubles if you want exact answers. Use either decimals or integer arithmetic (by converting to cents).
I'm not going to provide full source code as this looks like homework or a learning exercise, so instead I'll just give a few hints.
To find out how many notes of a certain denomination you need, use division:
int number = (int)(total / sizeOfBill);
Start with the largest bills and work downwards to the smallest to get a small number of notes/coins, otherwise you could end up with thousands of cent coins instead of a few bills.

Not an answer: a harder version of the problem for you to consider.
The coinage system you describe has a nice property that when you repeatedly "take out" the largest denomination from the remaining total, you end up with the solution that has the smallest number of bills/coins. FYI, an algorithm which operates by repeatedly choosing the largest thing is called a "greedy algorithm"; in this case, the greedy algorithm give an optimal result, if you're optimizing for the smallest number of bills/coins.
Can you solve the problem for a coinage system where the coins are:
1 crown = 60 pence ("pence" is the plural of "penny")
1 half-crown = 30 pence
1 florin = 24 pence
1 shilling = 12 pence
1 tanner = 6 pence
The greedy algorithm for making change now does not work if you are optimizing for the smallest number of coins. For example, 48 pence by the greedy algorithm goes
take out a half-crown, leaving 18 pence
take out a shilling, leaving 6 pence
take out a tanner, leaving nothing
Three coins. But obviously 48 pence is two florins, which is only two coins.
Can you come up with an algorithm that handles this coinage system and gives the least number of coins possible for every problem?
(Note that the pre-decimal British coinage system is suitable for neither decimal nor double arithmetic; do it all in integers!)

PLEASE use decimal for this; double is rarely suitable for money types:
double value = 0.3;
value -= 0.1;
value -= 0.1;
value -= 0.1;
Console.WriteLine(value); //**not** zero
Anyway, a very crude approach (also assumes that the coins are sorted descending and that all values are non-negative) is below. It gets trickier if you don't have coins for the lowest values (i.e. you have 0.5M and 0.2M but no 0.1M and need to issue 0.8M - since this needs 4x0.2M, not 0.5M+0.2M+(damn))
decimal value = 10023.23M;
decimal[] CoinValue = { 500, 200, 100, 50, 20, 10, 5, 2, 1, 0.5M, 0.2M, 0.1M, 0.05M, 0.02M, 0.01M };
int[] counts = new int[CoinValue.Length];
for (int i = 0; i < CoinValue.Length; i++) {
decimal v = CoinValue[i];
while (value >= v) {
counts[i]++;
value -= v;
}
}
for (int i = 0; i < CoinValue.Length; i++) {
if (counts[i] > 0) {
Console.WriteLine(CoinValue[i] + "\t" + counts[i]);
}
}
Console.WriteLine("Untendered: " + value);

Given your array ... also works with decimals of course.
double[] CoinValue = { 500, 200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01 };
uint[] result = new uint[CoinValue.Length];
double ammount = 552.5;
double remaining = ammount;
for (int i = 0; i < CoinValue.Length; ++i) {
result[i] = (uint) (remaining / CoinValue[i]);
if (result[i] > 0)
remaining = remaining % CoinValue[i];
}

Related

Calculating number needed to reach a certain percentage

I'm trying to write a function that will tell me how many more is needed to reach a certain percentage.
This is the function I've gotten so far:
private static int CalculateHowManyNeeded(int TotalPallets, int PalletsDelivered, int MinReqPercentage = 25)
{
return Convert.ToInt32((MinReqPercentage / 100.00 * TotalPallets) - PalletsDelivered);
}
However, my method fails to give me the right answer if I have TotalPallets = 2, and palletsDelivered = 0. I'm expecting to get 1.. but my method returns 0...
What is the best way I can fix this problem?
Convert.ToInt32 as written in the docs will return next:
value, rounded to the nearest 32-bit signed integer. If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.
So in case of 0.5 you will get 0. Next depended on desired output, if you want to round also this halfway points to the "upper bound" you can use Math.Round with MidpointRounding.AwayFromZero (round to nearest mode: when a number is halfway between two others, it is rounded toward the nearest number that is away from zero.):
private static int CalculateHowManyNeeded(int TotalPallets, int PalletsDelivered, int MinReqPercentage = 25)
{
return (int)Math.Round((MinReqPercentage / 100.00 * TotalPallets) - PalletsDelivered, MidpointRounding.AwayFromZero);
}
If you want to get the smallest integral value greater than or equal to the specified number (i.e. 1 for 0.1, 0.2 etc.) the you can use Math.Ceiling as #Harsh suggested in his answer.
I believe this is all you need -
private static int CalculateHowManyNeeded(int TotalPallets, int PalletsDelivered, int MinReqPercentage = 25)
{
return (int) Math.Ceiling(MinReqPercentage * 0.01 * TotalPallets) - PalletsDelivered;
}
Do the following output look good to you -
Console.WriteLine(CalculateHowManyNeeded(2, 0)); // 1
Console.WriteLine(CalculateHowManyNeeded(2, 1, 49)); // 0
Console.WriteLine(CalculateHowManyNeeded(2, 1, 50)); // 0
Console.WriteLine(CalculateHowManyNeeded(2, 1, 51)); // 1
I suggest you try something like this:
private static int CalculateHowManyNeeded(int TotalPallets, int PalletsDelivered, int MinReqPercentage = 25)
{
int result = Convert.ToInt32((MinReqPercentage / 100.00 * TotalPallets) - PalletsDelivered);
result = result <= 0 ? 1 : result;
return result;
}

C# aggregation function for a non-linear series

I'm given two arrays, one representing a price, the other representing a number of units:
e.g.
decimal[] price = new decimal[] {1.65, 1.6, 1.55, 1.4, 1.3};
long[] quantity = new long[] {5000, 10000, 12000, 20000, 50000};
So the first 5000 units will cost 1.65 each, the next will cost 10000 will cost 1.6 each, and so on...
It's pretty easy to get the average price with an aggregate funct when you know the amount of units you wish to order e.g.Average price for 7000 units = (5000/7000 * 1.65) + (2000/7000 * 1.6), however, I'm having trouble coming up with an algorithm for when the total unit amount is the unknown variable, and we are given the target average price.
E.g. How many units would I have to order so the average unit price = 1.57
If you think geometrically about it, consider a chart showing the total price (ordinate axis) as a function of the total number of items (abscissa) bought. The plot starts in (0, 0) (buying zero costs zero). First we get a straight line segment of slope 1.65 and horizontal width 5000. Then from the end-point of that comes a new segment of slope 1.6 and width 10000. The total plot is continuous and piece-wise straight-lined but with bends where the unit price changes.
Then to solve your problem, find the intersection with the line of equation y == 1.57 * x, i.e. the line starting at (0, 0) and having slope 1.57. For each of the segments (whose two endpoints you know), check if this segment meets y == 1.57 * x, and if it does, there's your solution.
If the numbers in your price array are decreasing, there can be at most one solution (given that 1.57 is strictly less than the first price, price[0]), the plot representing a concave function.
EDIT: I tried to code this geometry in C#. I didn't add checks that price are all positive and decreasing, and that quantity are all positive. You must check that. Here's my code:
decimal[] price = { 1.65m, 1.6m, 1.55m, 1.4m, 1.3m, };
long[] quantity = { 5000, 10000, 12000, 20000, 50000, };
decimal desiredAverage = 1.57m;
int length = price.Length;
if (length != quantity.Length)
throw new InvalidOperationException();
var abscissaValues = new long[length + 1];
var ordinateValues = new decimal[length + 1];
for (int i = 1; i <= length; ++i)
{
for (int j = 0; j < i; ++j)
{
abscissaValues[i] += quantity[j];
ordinateValues[i] += price[j] * quantity[j];
}
} // calculation of plot complete
int segmentNumber = Enumerable.Range(1, length).FirstOrDefault(i => ordinateValues[i] / abscissaValues[i] <= desiredAverage);
if (segmentNumber > 1)
{
decimal x = (ordinateValues[segmentNumber - 1] * abscissaValues[segmentNumber] - abscissaValues[segmentNumber - 1] * ordinateValues[segmentNumber])
/ (desiredAverage * (abscissaValues[segmentNumber] - abscissaValues[segmentNumber - 1]) - (ordinateValues[segmentNumber] - ordinateValues[segmentNumber - 1]));
Console.WriteLine("Found solution x == " + x);
}
else
{
Console.WriteLine("No solution");
}
I don't know if someone can write it more beautifully, but it seems to work. Output is:
Found solution x == 29705.882352941176470588235294
I believe that's because there's no one answer, no one combination of prices which will result in one average, no close form equation. What we may be looking at is a variant of the Knapsack Problem. http://en.wikipedia.org/wiki/Knapsack_problem with a minimization of value instead of maximization.
EDIT: As correctly pointed out below, this is not a variant of the knapsack problem. There is a closed form solution:
If T = total units bought,
1.57 = 1.55 * (12000/T) + 1.6 * ((T-12000)/T). Solve for T.
The starting price block (here 1.55) is the block just below the average price per unit given in the problem (here 1.57).

Round a number to the next HIGHEST 10

I have a need to create a graph, where the scale of the Y-axis changes depending on the data input into the system. Conceivably this scale could be anywhere from 0-10, 0-100, or even have bottom limit of thousands and an upper limit of millions.
To properly determinethe scale of this axis, I need to work out the ratio of Points to Pixels (based on graph height/range).
Now a graphs' axis never start at the lowest value and go to the highest, usual practice is to go to the next nearest 2, 5 or 10 (above for upper limit, and below for lower) depending on the range of values.
So what I'd like to know is how to take the max value from the data set, and round it up to the nearest 10.
for clarification, the input values will always be integers.
what i have now is this
if ((rangeMax < 10) && (rangeMax > 5))
rangeMax = 10;
else if (rangeMax < 5)
rangeMax = 5;
Which is only useful for values less than 10, and doesn't allow the flexibility required to be truly dynamic. Ultimately this graph will be auto-generated during a page load event, with no user input.
I've read around a bit, and people talk about things like the modulus operator (%), but I can't find any reliable information about it's use, and talk of Math.Ceiling and Math.Round, but these go to the next nearest whole number, which isn't quite there, and don't seem to help much at all when dealing with integers anyway.
Any suggestions, pointers or help greatly appreciated.
i did find a similar question asked here How can i get the next highest multiple of 5 or 10 but i don't know java, so i can't understand any of what was said.
Cheers
if(rangeMax % 10 !=0)
rangeMax = (rangeMax - rangeMax % 10) + 10;
You could also use Math.Round() with MidpointRounding.AwayFromZero using a decimal number (otherwise integer division will truncate fractions):
decimal number = 55M;
decimal nextHighest = Math.Round(number/ 10, MidpointRounding.AwayFromZero) * 10;
If you want to go up to the next 10, you can use Math.Ceiling as follows:
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / 10) * 10);
If you need to generalize to go to the next n (for example 5 here) you can do:
int n = 5;
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / n) * n);
Something which might help is to divide the number by 10. This should round it to the nearest integer. Then multiply it by 10 again to get the number rounded to the nearest 10
I use THIS:
public static double RoundTo10(double number)
{
if (number > 0)
{
return Math.Ceiling(number / 10) * 10;
}
else
{
return Math.Floor(number / 10) * 10;
}
}
you can try this....
decimal val = 95;
//decimal val =Convert.ToDecimal( textBox1.Text);
decimal tmp = 0;
tmp = (val % 10);
//MessageBox.Show(tmp.ToString()+ "Final val:"+(val-tmp).ToString());
decimal finval = val - tmp;

Map an unbounded range of values to 10 colors?

I have the following list of 10 colors:
public static readonly IList<Brush> lineColors = new ReadOnlyCollection<Brush>
(new List<Brush> {
new SolidColorBrush(Color.FromRgb(35, 31, 32)),
new SolidColorBrush(Color.FromRgb(64, 64, 66)),
new SolidColorBrush(Color.FromRgb(89, 89, 91)),
new SolidColorBrush(Color.FromRgb(110, 111, 113)),
new SolidColorBrush(Color.FromRgb(129, 130, 132)),
new SolidColorBrush(Color.FromRgb(148, 149, 153)),
new SolidColorBrush(Color.FromRgb(168, 169, 173)),
new SolidColorBrush(Color.FromRgb(189, 190, 193)),
new SolidColorBrush(Color.FromRgb(210, 211, 213)),
new SolidColorBrush(Color.FromRgb(231, 231, 232))
});
Now I also have a range from 1 to n. I'd like to map these value equally to this 10 colors so that the smallest value is the first color and the highest value is mapped to the last color. All the other colors should cover an equal distance in the value range.
How to do that?
I think this will maybe do it:
int position = Math.floor( value / ((max - min) / lineColors.Count));
lineColors.ElementAt(position);
But I'm not sure if this is valid for all possibilities and if there isn't a simpler solution.
Mapping values can be expressed with a linear function: f(x) = ax + b
Both your ranges provide points on that function from which it can be calculated.
f(1) = 0
f(n) = 9 | The highest index in a list of ten colours.
0 = a * 1 + b
9 = a * n + b
9 = a * (n - 1)
a = 9 / (n - 1)
=> b = -9 / (n - 1)
=> f(x) = 9 / ( n - 1) * (x - 1)
The problem here is that if you round that right away less values will be mapped to 0 and 9 because the rounding range is only 0.5 (from 0 to 0.5 and from 8.5 to 9), so you could stretch the range and shift it back by 0.5 to account for that.
private int MapValue(int value, int n)
{
int output = (int)Math.Round((10.0 / (n - 1) * (value - 1)) - 0.5, 0);
if (output == -1) return 0;
else return output;
}
You didn't introduce value, min and max -- I'm assuming that min and max are the minimum and maximum, respectively, of the range of numbers you want to be able to map (in your textual exposition of the problem, that would mean min = 1 and max = n), and that value is the value you're trying to map.
Your suggested solution contains a couple of problems:
a) You need to substract min from value, too.
b) If these variables are declared as integers (which I imagine they would be), the division results will get truncated.
c) If value is max, you want lineColors.Count - 1, not lineColors.Count.
d) By using floor, you introduce an asymmetry -- a range of values is mapped to the lowest colour, but only max is mapped to the highest colour. It seems preferable to use round instead to treat both ends of the spectrum the same.
So a solution would be:
int position = Math.round ((value - min) / ((max - min) / (lineColors.Count - 1.)));
lineColors.ElementAt(position);
(The decimal point on "1." forces all arithmetic to be floating-point.)

Algorithm to calculate the number of combinations to form 100

I am struck in a tricky situation where I need to calculate the number of combinations to form 100 based on different factors.
Those are
Number of combinations
Multiplication factor
distance
Sample input 1: (2-10-20)
It means
list the valid 2 way combination to form 100.
the distance between the combination should be less than or equal to 20.
And all of the resultant combination must be divisible by the given multiplication factor 10
Output will be
[40,60]
[50,50]
[60,40]
here [30,70],[20,60] are invalid because the distance is above 20.
Sample Input 2: [2-5-20]
[40,60]
[45,55]
[50,50]
[55,45]
[60,40]
I would really appreciate if you guided me to the right direction.
Cheers.
I hope it's not a homework problem!
def combinations(n: Int, step: Int, distance: Int, sum: Int = 100): List[List[Int]] =
if (n == 1)
List(List(sum))
else
for {
first <- (step until sum by step).toList
rest <- combinations(n - 1, step, distance, sum - first)
if rest forall (x => (first - x).abs <= distance)
} yield first :: rest
If you need to divide 100 over 2 with a maximum distance of N, the lowest value in the combination is
100 / 2 - N / 2
If you need to divide 100 over 3 values with a maximum distance of N, this becomes more tricky. The average of the 3 values will be 100/3, but if one of them is much lower than this average, than the other can only be slightly bigger than this average, meaning that the minimum value is not the average minus the maximum distance divided by two, but probably
100 / 3 - 2N / 3
In general with M values, this becomes
100 / M - (M-1)N / M
Which can be simplified to
(100 - (M-1)N) / M
Similarly we can calculate the highest possible value:
(100 + (M-1)N) / M
This gives you a range for first value of your combination.
To determine the range for the second value, you have to consider the following constraints:
the distance with the first value (should not be higher than your maximum distance)
can we still achieve the sum (100)
The first constraint is not a problem. The second is.
Suppose that we divide 100 over 3 with a maximum distance of 30 using multiples of 10
As calculated before, the minimum value is:
(100 - (3-1)30) / 3 --> 13 --> rounded to the next multiple of 10 --> 20
The maximum value is
(100 + (3-1)30) / 3 --> 53 --> rounded to the previous multiple of 10 --> 50
So for the first value we should iterate over 20, 30, 40 and 50.
Suppose we choose 20. This leaves 80 for the other 2 values.
Again we can distribute 80 over 2 values with a maximum distance of 30, this gives:
Minimum: (80 - (2-1)30) / 2 --> 25 --> rounded --> 30
Maximum: (80 + (2-1)30) / 2 --> 55 --> rounded --> 50
The second constraint is that we don't want a distance larger than 30 compared with our first value. This gives a minimum of -10 and a maximum of 50.
Now take the intersection between both domains --> 30 to 50 and for the second value iterate over 30, 40, 50.
Then repeat this for the next value.
EDIT:
I added the algorithm in pseudo-code to make it clearer:
calculateRange (vector, remainingsum, nofremainingvalues, multiple, maxdistance)
{
if (remaingsum==0)
{
// at this moment the nofremainingvalues should be zero as well
// found a solution
print vector
return;
}
minvalueaccordingdistribution = (remainingsum-(nofremainingvalues-1)*maxdistance)/nofremaingvalues;
maxvalueaccordingdistribution = (remainingsum+(nofremainingvalues-1)*maxdistance)/nofremaingvalues;
minvalueaccordingdistance = max(values in vector) - maxdistance;
maxvalueaccordingdistance = min(values in vector) + maxdistance;
minvalue = min (minvalueaccordingdistribution, minvalueaccordingdistance);
maxvalue = max (minvalueaccordingdistribution, minvalueaccordingdistance);
for (value=minvalue;value<=maxvalue;value+=multiple)
{
calculaterange (vector + value, remainingsum - value, nofremainingvalues-1, multiple, maxdistance);
}
}
main()
{
calculaterange (emptyvector, 100, 2, 20);
}
Why can't you use a brute force approach with few optimization? For example, say
N - Number of combinations
M - Multiples
D - Max possible Distance
So possible values in combinations can be M, 2M, 3M and so on. You need to generate this set and then start with first element from set and try to find out next two from choosing values from same set (provided that they should be less than D from first/second value).
So with i/p of 3-10-30 would
Create a set of 10, 20, 30, 40, 50, 60, 70, 80, 90 as a possible values
Start with 10, choice for second value has to be 20, 30, 40, 50 (D < 30)
Now choose second value from set of 20, 30, 40, 50 and try to get next value and so on
If you use a recursion then solution would become even simpler.
You have to find N values from a
list of possible values within MIN &
MAX index.
So try first value at
MIN index (to MAX index). Say we
have chosen value at X index.
For every first value, try to find
out N-1 values from the list where MIN =
X + 1 and MAX.
Worst performance will happen when M = 1 and N is sufficiently large.
Is the distance between all the additive factors, or between each of them? For example, with 3-10-20, is [20-40-60] a valid answer? I'll assume the latter, but the solution below can be modified pretty trivially to work for the former.
Anyway, the way to go is to start with the most extreme answer (of one sort) that you can manage, and then walk the answers along until you get to the other most extreme.
Let's try to place numbers as low as possible except for the last one, which will be as high as possible (given that the others are low). Let the common divisor be d and divide 100 by it, so we have S = 100/d. This quantizes our problem nicely. Now we have our constraint that spacing is at most s, except we will convert that to a number of quantized steps, n = s/d. Now assume we have M samples, i1...iM and write the constraints:
i1 + i2 + i3 + ... + iM = S
0 <= i1 <= n
0 <= i2 <= n
. . .
0 <= iM <= n
i1 <= i2
i2 <= i3
. . .
i(M-1) <= iM
We can solve the first equation to get iM given the others.
Now, if we make everything as similar as possible:
i1 = i2 = ... = iM = I
M*I = S
I = S/M
Very good--we've got our starting point! (If I is a fraction, make the first few I and the remainder I+1.) Now we just try to walk each variable down in turn:
for (i1 = I-1 by -1 until criteria fails)
sum needs to add to S-i1
i2 >= i1
i2 <= i1 +n
solve the same problem for M-1 numbers adding to S-i1
(while obeying the above constraint on i2)
Well, look here--we've got a recursive algorithm! We just walk through and read off the answers.
Of course, we could walk i1 up instead of down. If you need to print off the answers, may as well do that. If you just need to count them, note that counting up is symmetric, so just double the answer you get from counting down. (You'll also have a correction factor if not all values started the same--if some were I and some were I+1, you need to take that into account, which I won't do here.)
Edit: If the range is what every value has to fit within, instead of all the
0 <= i1 <= n
conditions, you have
max(i1,i2,...,iM) - min(i1,i2,...,iM) <= n
But this gives the same recursive condition, except that we pass along the max and min of those items we've already selected to throw into the mix, instead of adding a constraint on i2 (or whichever other variable's turn it is).
Input:
(2-10-20)
Divide the number by param 1
(50,50)
2 Check whether the difference rule allows this combination. If it hurts the rule, then STOP, if it allows, then add this and it's combinations to the result list
For example: abs(50-50)<20, so it is ok
3 Increase the the first value by param 2, decrease the second value by param 2
Go 2. point

Categories