I am writing a program where I put different students in different classrooms. I'm having some trouble figuring out how to use probabilities in C#, and programming in general. I want it to be a 5% probability to become a student in Alpha, 10& for Omega & 60% for Nightwalkers. I don't understand what numbers to put in.My method right now:
public string AssignClassroom()
{
int rand = random.Next(0, 100);
{
if (rand < 5) // or >95%?
{
student.Classroom = "Alpha";
}
if (rand < 10) // or >90?
{
student.Classroom = "Omega";
}
if (rand < 60) // or >40?
{
student.Classroom = "Nightwalkers";
}
}
}
You should add up figures in ifs:
if (rand < 5) {
student.Classroom = "Alpha";
}
else if (rand < 10 + 5)
{
student.Classroom = "Omega";
}
else if (rand < 60 + 10 + 5)
{
student.Classroom = "Nightwalkers";
}
Note, that 5, 10, 60 are differencies:
0 .. 5 .. 15 .. 75
| 5 | | | -> 5% top students go to the 1st class
| 10 | | -> 10% next go to the 2nd
| 60 | -> 60% goes to the 3d
Related
I'm looking to "truncate" 0's from long values.
For example, for long value "1234560000", I'd like to drop the last four 0's (to 123456) and also need to know how many 0's have been dropped.
I can achieve this with a % 10 operations:
void Main()
{
Console.WriteLine(Truncate(1234560000));
}
public static long Truncate(long mantissa)
{
int droppedZeros = 0;
while (mantissa % 10 == 0)
{
mantissa /= 10;
droppedZeros++;
}
return mantissa;
}
This piece of code getting is getting called millions of times and is performance critical and I'm looking for ways to improve performance to achieve the same without modulo (can this be done with bit shifts?).
Per request, I added some benchmarks numbers including a benchmark that performs division with compile time known constant to showcase the relative overhead of the modulo operation:
Method | Mean | Error | StdDev | Median | Gen 0/1k Op | Gen 1/1k Op | Gen 2/1k Op | Allocated Memory/Op |
---------------- |----------:|----------:|----------:|----------:|------------:|------------:|------------:|--------------------:|
DivideNoModulo | 1.863 ms | 0.0431 ms | 0.1272 ms | 1.855 ms | - | - | - | - |
ModuloBasic | 21.342 ms | 0.8776 ms | 2.5876 ms | 20.813 ms | - | - | - | - |
DivisionBasic | 18.159 ms | 1.7218 ms | 5.0768 ms | 15.937 ms | - | - | - | - |
DivisionSmarter | 7.510 ms | 0.5307 ms | 1.5649 ms | 7.201 ms | - | - | - | - |
ModuloSmarter | 8.517 ms | 0.1673 ms | 0.2886 ms | 8.531 ms | - | - | - | - |
StringTruncate | 42.370 ms | 1.7358 ms | 5.1181 ms | 40.566 ms | 1000.0000 | - | - | 8806456 B |
Benchmark code:
[SimpleJob(RunStrategy.ColdStart, 1)]
[MemoryDiagnoser]
public class EncoderBenchmark
{
private long _mantissa;
[Benchmark]
public void DivideNoModulo()
{
for (var i = 0; i < 100000; i++)
{
_mantissa = 12345600000000;
_mantissa /= 100000000;
}
}
[Benchmark]
public void ModuloBasic()
{
for (var i = 0; i < 100000; i++)
{
_mantissa = 12345600000000;
while (_mantissa % 10 == 0)
{
_mantissa /= 10;
}
}
}
[Benchmark]
public void DivisionBasic()
{
for (var i = 0; i < 100000; i++)
{
_mantissa = 12345600000000;
for (;;)
{
long temp = _mantissa / 10;
if (temp * 10 != _mantissa)
break;
_mantissa = temp;
}
}
}
[Benchmark]
public void DivisionSmarter()
{
for (var i = 0; i < 100000; i++)
{
_mantissa = 12345600000000;
for (; ; )
{
long temp = _mantissa / 1000000;
if (temp * 1000000 != _mantissa)
break;
_mantissa = temp;
}
for (; ; )
{
long temp = _mantissa / 10;
if (temp * 10 != _mantissa)
break;
_mantissa = temp;
}
}
}
[Benchmark]
public void ModuloSmarter()
{
for (var i = 0; i < 100000; i++)
{
_mantissa = 12345600000000;
while (_mantissa % 1000000 == 0)
{
_mantissa /= 1000000;
}
while (_mantissa % 10 == 0)
{
_mantissa /= 10;
}
}
}
[Benchmark]
public void StringTruncate()
{
for (var i = 0; i < 100000; i++)
{
_mantissa = 12345600000000;
_mantissa = long.Parse(_mantissa.ToString().TrimEnd('0'));
}
}
}
You'll be very unlikely to get it working efficiently with bit shifting since that's ideal for dividing by powers of two, of which 10 is not one.
A possibility for improvement, where you may often get numbers with lots of trailing zeros, is to use multiple loops to do the work in bigger chunks, such as:
if (mantissa != 0) {
while (mantissa % 1000000 == 0) {
mantissa /= 1000000;
droppedZeros += 6;
}
while (mantissa % 1000 == 0) {
mantissa /= 1000;
droppedZeros += 3;
}
while (mantissa % 10 == 0) {
mantissa /= 10;
droppedZeros++;
}
}
This will usually result in fewer instructions being performed but, as with all optimisations, measure, don't guess! It may be that the added code complexity is not worth the gains you get (if any).
Note that I've also caught the mantissa == 0 case since that will result in an infinite loop in your original code.
Another possibility you may want to consider is if you're doing this operation to the same item multiple times. For example, let's say you have a collection of integers and, each time you need to process one of them, you have to strip off and count the trailing zeros.
In that case, you could actually store them in a different way. For example, consider the (pseudo-code) structure:
struct item:
int originalItem
int itemWithoutZeroes
int zeroCount
Basically, whenever you first receive an item (such as 1234560000), you immediately convert it to the structure once and once only:
{ 1234560000, 123456, 4 }
This provides a cached version of the zero-stripped item so you never have to calculate it again.
So, if you want the stripped mantissa, you just use item.itemWithoutZeros. If you want to output the number in its original form, you can use item.originalItem. And, if you want the count of zeros, use item.zeroCount.
Obviously, this will take up more storage space but you'll often find that optimisation is a time/space trade-off.
A bit faster replace '%' with '*'
public static long T(long mantissa)
{
if (mantissa == 0)
return 0;
int droppedZeros = 0;
for (; ; )
{
long temp = mantissa / 1000000;
if (temp * 1000000 != mantissa)
break;
mantissa = temp;
droppedZeros += 6;
}
for (; ; )
{
long temp = mantissa / 1000;
if (temp * 1000 != mantissa)
break;
mantissa = temp;
droppedZeros += 3;
}
for (; ; )
{
long temp = mantissa / 10;
if (temp * 10 != mantissa)
break;
mantissa = temp;
droppedZeros++;
}
return mantissa;
}
Update your Truncate logic as below.
public static long Truncate(long mantissa)
{
if (mantissa == 0)
return 0;
var mantissaStr = mantissa.ToString();
var mantissaTruncated = mantissaStr.TrimEnd('0');
int droppedZeros = mantissaStr.Length - mantissaTruncated.Length;
return Convert.ToInt64(mantissaTruncated);
}
GetMaximum = Gain.Max(); <-- List of Value Numbers Random takes out the maximum
GetMinumumVal = Gain.Min(); <-- takes out the minimum
XAxisScale = GainCounter;
if (XAxisScale % 10 != 0)
{
XAxisScale = (XAxisScale - XAxisScale % 10) + 10; <-- round off to nearest highest 10th
}
intervalXaxis = XAxisScale / 5; <-- divide interval by 5
//------------- Y Axis ---- which needs a 0 neutral ----- //
if(GetMinumumVal > -40)
{
GetMinumumVal = -40;
ConvertToPos = -40; <-- default lowest -40
}
else
{
if (GetMinumumVal % 10 != 0)
{
GetMinumumVal = (GetMinumumVal - GetMinumumVal % 10) - 10;
}
ConvertToPos = Convert.ToInt32(GetMinumumVal) * -1;
}
//-------------//
if(GetMaximum > 60)
{
GetMaximum = Gain.Max();
if (GetMaximum % 10 != 0)
{
GetMaximum = (GetMaximum - GetMaximum % 10) + 10;
}
}
else
{
GetMaximum = 60; <-- Default highest 60
}
Getinterval = (Convert.ToInt32(GetMaximum) + ConvertToPos) / 10; <-- divide by 10 but i need to have zero neutral on it?? this is the problem
Trade_Analyzer_Panel.chart1a.ChartAreas.Add("Area1a");
Trade_Analyzer_Panel.chart1a.Titles.Add("Gain / Loss for Product XYZ");//
Trade_Analyzer_Panel.chart1a.Series.Add("Gain/Loss");
Trade_Analyzer_Panel.chart1a.Legends.Add("Gain/Loss");
Trade_Analyzer_Panel.chart1a.Series["Gain/Loss"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Column;
Count = 0;
for (int i = 0; i < Trade_Analyzer_Panel.dataGridView1.Rows.Count - 1; i++)
{
Trade_Analyzer_Panel.chart1a.Series["Gain/Loss"].Color = Color.Blue;
//Trade_Analyzer_Panel.chart1a.Series["Gain/Loss"].Points[Count].AxisLabel = Convert.ToInt32(Gain[Count]).ToString();
Trade_Analyzer_Panel.chart1a.Series["Gain/Loss"].Points.AddXY(Count, Convert.ToInt32(Gain[Count]));
Count++;
}
// -------- Horizontal ---------- //
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.Minimum = 1;
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.Maximum = XAxisScale;
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.Interval = 5; //intervalXaxis;
// -------- Vertical ---------- //
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisY.Minimum = Convert.ToInt32(GetMinumumVal);
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisY.Maximum = Convert.ToInt32(GetMaximum);
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisY.Interval = 20;
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.ScrollBar.ButtonStyle = System.Windows.Forms.DataVisualization.Charting.ScrollBarButtonStyles.SmallScroll;
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.MajorGrid.Enabled = false;
// set view range to [0,max]
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.Minimum = 0;
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.Maximum = XAxisScale;
// enable autoscroll
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].CursorX.AutoScroll = true;
// let's zoom to [0,blockSize] (e.g. [0,5])
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.ScaleView.Zoomable = true;
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.ScaleView.SizeType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.ScaleView.Zoom(0, 5);
// disable zoom-reset button (only scrollbar's arrows are available)
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.ScrollBar.ButtonStyle = System.Windows.Forms.DataVisualization.Charting.ScrollBarButtonStyles.SmallScroll;
// set scrollbar small change to blockSize (e.g. 100)
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisX.ScaleView.SmallScrollSize = 100;
Should i use an interval on this? or what any idea how can i get a 0 neutral for the highest and lowest value of my Y Axis in the Chart.. i need help bad i got runned out of ideas sorry
Example:
60
40
20
0
-20
-40
but then if example lower gets a -70 it looks like this:
50
30
10
-10
-30
-50
-70
How can I get a neutral 0 on it no matter how the changes are?
Note that the vertical interval is 20
Trade_Analyzer_Panel.chart1a.ChartAreas["Area1a"].AxisY.Interval = 20;
this means your steps up the axis will be the lowest value plus multiples of 20. You will get 0 on one of the steps if your bottom value is a multiple of 20. What may work is
if(GetMinumumVal > -40)
{
GetMinumumVal = -40;
ConvertToPos = -40; <-- default lowest -40
}
else
{
if (GetMinumumVal % 20 != 0)
{
GetMinumumVal = (GetMinumumVal - GetMinumumVal % 20) - 20;
}
ConvertToPos = Convert.ToInt32(GetMinumumVal) * -1;
}
Using 20 rather than 10.
Note that the modulus operator % behaves strangely for negative numbers see http://en.wikipedia.org/wiki/Modulo_operation. If x is negative the x % 20 is a negative number. You may find things easier to use Math.Floor(GetMinumumVal / 20)*20 which is the smallest multiple of 20 less than GetMinumumVal.
I have text file like
Time amplitude index
1 0,25 25
2 0,68 28
3 -2,5 69
4 2,5 94
5 3 45
6 5 26
What in need to get is this.
Time amplitude index classified
1 0,25 25 1
2 0,68 28 1
3 -2,5 69 2
4 2,5 94 1
5 3 45 1
6 5 26 1
It need to write additional column (classified) with statement 1 (column classified) we classifies that amplitude is increasing during the time, with statement 2 (column classified) we classifies that amplitude is decreasing during the time. I have a big text file and it need to be written in new text file. I was try with code like this:
private void button3_Click(object sender, EventArgs e)
{
StreamReader dat = new StreamReader(textBox1.Text, System.Text.Encoding.Default);
StreamWriter sw = new StreamWriter(textBox2.Text, true);
{
while (!dat.EndOfStream)
{
string mainLine1 = dat.ReadLine();
string[] originalLine1 = mainLine1.Split(new string[] { "\t" }, StringSplitOptions.None);
for (int i = 1; i < mainLine1.Length; i++)
{
if (originalLine1[i] > originalLine1[i-1])
{
sw.WriteLine(originalLine1[0] + "\t" + originalLine1[1] + "\t"+"1");
}
}
}
sw.Close();
}
I know that the code is not right but that is what I figured it.
Solve the problem. If Someone need it.
Example tex file:
1
2
3
2
1
-1
-2
-3
-2
-1
1
2
3
Need to get additional column and write tex file:
1 1
2 1
3 1
2 2
1 2
-1 3
-2 3
-3 3
-2 4
-1 4
1 1
2 1
3 1
Code
string niz;
int j=0;
string[] vrstica, vrstica_prej=null;
while (!dat.EndOfStream)
{
niz = dat.ReadLine();
vrstica = niz.Split('\t');
j++;
if (j < 2)
{
sw.WriteLine(vrstica[0] + "\t" + vrstica[1] + "\t" + "0");
}
else
{
double a = Convert.ToDouble(vrstica[0]);
double a_pre = Convert.ToDouble(vrstica_prej[0]);
if (a > a_pre && a > 0)
{sw.WriteLine(vrstica[0] + "\t" + "1"); }
else if (a < a_pre && a > 0)
{sw.WriteLine(vrstica[0] + "\t" + "2"); }
else if (a < a_pre && a < 0)
{sw.WriteLine(vrstica[0] +"\t" + "3"); }
else if (a > a_pre && a < 0)
{sw.WriteLine(vrstica[0] + "\t" + "4"); }
}
vrstica_prej = vrstica;
}
}
sw.Close();
I hope someone will be glad for it.
I am sure this problem has a formal name, and knowing that name would probably help me find the solution, but I don't know it, and wording the problem for Google keeps pointing me to the Knapsack Problem, which isn't the same thing.
I want to take some value X and find every possible combination of splitting that value into N stacks of whole integers.
In case my wording is confusing, here is an example of X = 4, N = 3
Stack -> 1 | 2 | 3 |
----------------------
#1-----> 4 | 0 | 0 |
----------------------
#2-----> 3 | 1 | 0 |
----------------------
#3-----> 2 | 1 | 1 |
----------------------
#4-----> 2 | 2 | 0 |
Duplication is acceptable, since its easy to remove, but ideally it would not be calculated. An algorithm for solving the problem would be perfect, but even finding out of the problem has a name would make research easier. Thanks.
These are in fact integer partitions as a deleted answer remarks. Using Mathematica:
IntegerPartitions[4, 3] // PadRight //Grid
Output:
4 0 0
3 1 0
2 2 0
2 1 1
I could not find a C# implementation but here are a couple of related questions:
Elegant Python code for Integer Partitioning
Integer Partition in Java
Algorithm for generating integer partitions
Google hits:
Integer Partition Algorithm by Jerome Kelleher
Integer Partition Algorithm by Daniel Scocco
Fast Algorithms for Generating Integer Partitions (PDF) (looks heavy-duty)
Stony Brook Algorithm Repository - Partitions
This seems to do the trick:
vector<vector<int> > partitions(int X, int N, int Y)
{
vector<vector<int> > v;
if(X<=1 || N==1)
{
if(X<=Y)
{
v.resize(1);
v[0].push_back(X);
}
return v;
}
for(int y=min(X, Y); y>=1; y--)
{
vector<vector<int> > w = partitions(X-y, N-1, y);
for(int i=0; i<w.size(); i++)
{
w[i].push_back(y);
v.push_back(w[i]);
}
}
return v;
}
int main()
{
vector<vector<int> > v = partitions(5, 3, 5);
int i;
for(i=0; i<v.size(); i++)
{
int x;
for(x=0; x<v[i].size(); x++)
printf("%d ", v[i][x]);
printf("\n");
}
return 0;
}
This is user434507's answer in C#:
class Program
{
static void Main(string[] args)
{
var v = Partitions(5, 3, 5);
for (int i = 0; i < v.Count; i++)
{
for (int x = 0; x < v[i].Count; x++)
Console.Write(v[i][x] + " ");
Console.WriteLine();
}
}
static private List<List<int>> Partitions(int total, int stacks, int max)
{
List<List<int>> partitions = new List<List<int>>();
if (total <= 1 || stacks == 1)
{
if (total <= max)
{
partitions.Add(new List<int>());
partitions[0].Add(total);
}
return partitions;
}
for (int y = Math.Min(total, max); y >= 1; y--)
{
var w = Partitions(total - y, stacks - 1, y);
for (int i = 0; i < w.Count; i++)
{
w[i].Add(y);
partitions.Add(w[i]);
}
}
return partitions;
}
}
I want to calculate the amount to charge my customers, when they buy licenses of my product.
I sell it in ranges of licenses:
1-10 : $50/user
11-20 : $40/user
21-30 : $30/user
31-50 : $20/user
So when someone purchases 136 licenses, I will charge him:
50 x 2 x $20 = $2000
30 x 1 x $30 = $900
6 x $50 = $300
I'm looking for an algorithm on how to process the given number and break it into number of occurrences in a range..
How can I do this in plain C# or LINQ?
------------ EDIT ----------------------------
I started a less confusing question (Algorithm for Fogbugz pricing scheme) and I got the answer I've been looking for.
Thank you all..
If presented with this price structure I would think that it is in the customer's best interest to minimize the cost by buying the package that best suits their need. The following algorithm uses dynamic programming to calculate the minimal possible price to exactly buy a certain number of licenses (you can save money by buying more than you need, although I haven't implemented that):
int getPrice(int n)
{
if (n >= 1 && n <= 10) return 50 * n;
if (n >= 11 && n <= 20) return 40 * n;
if (n >= 21 && n <= 30) return 30 * n;
if (n >= 31 && n <= 50) return 20 * n;
throw new Exception("Impossible");
}
int minimizePrice(int n)
{
int[] minimumPrice = new int[n + 1];
for (int i = 1; i <= n; ++i)
{
minimumPrice[i] = int.MaxValue;
for (int j = Math.Max(0, i - 50); j < i; ++j)
{
minimumPrice[i] = Math.Min(minimumPrice[i],
minimumPrice[j] + getPrice(i - j));
}
}
return minimumPrice[n];
}
For 70 licenses the minimal price is $1400 which can be obtained by buying 2 blocks of 35 licenses. You are suggesting a greedy algorithm. This will confuse your customers. A clever customer will place two orders instead of one large order and save $400.
I'd suggest changing your prices so that there is no upper limit to the number of licenses you can buy at $20 each.
This looks like it would be very similar to algorithms that make change for purchases (which coins to choose). The only difference is that you're comparing against a range instead of a single number.
The code could look something like this:
var val = 136;
var price = 0;
while (val > 0)
{
var range = FindMatchingRange(val); // Use a dictionary, list, or array.
var number = Math.Min(val, range.Max);
price += range.CostPerUser * number;
val -= number;
}
If I were a person who needed 10 licenses, under your suggested pricing plan why would I ever buy just 10 licenses?
10 licenses * $50/license = $500
11 licenses * $40/license = $440
What you would want is plan that lowers the cost for the most recently purchased licenses. So that for person wanting 11 licenses they would pay:
(10 licenses * $50/license) + (1 license * $40/license) = $540
A possible plan would look like this:
first 10 licenses (1-10): $50/user
next 10 licenses (11-20): $40/user
next 10 licenses (21-30): $30/user
all licenses after that (31+) : $20/user
Writing code to compute final cost for any number of users is a simple exercise. The calculation for someone purchasing 136 licenses would look like this:
(10 licenses * $50/license) + (10 licenses * $40/license) + (10 licenses * $30/license) + (106 licenses * $20/license) = $500 + $400 + $300 + $2120 = $3,220.
The original pricing plan is wacky, in my opinion. Take the customer who purchased 130 licenses last year who comes back and wants 10 more. What justification is there for charging them the highest rate? They are a high volume customer, you want to sell them (and they justifiably expect to receive) additional licenses at the lowest "marginal" price.
I made a calculation class for you... just more customer-orientated.
It calculates the cheapest price possible with your defined priceranges.
Example: 136 Licenses
50 Licenses 20$ each ( because: 31-50 : $20/user )
50 Licenses 20$ each ( because: 31-50 : $20/user )
36 Licenses 20$ each ( because: 31-50 : $20/user )
TOTAL: 1720
Example 130 Licenses
50 Licenses 20$ each
50 Licenses 20$ each
30 Licenses 30$ each
TOTAL: 1900
Code for the class:
public class PriceCalculator
{
public List<OrderPackage> CalculateCheapestPrice(Int32 AmountOfLicenses,
List<PriceRange> PriceRanges, out Double Total)
{
List<OrderPackage> result = new List<OrderPackage>();
Total = 0;
Int32 AmountsOfLicensesleft = AmountOfLicenses;
PriceRanges.Sort(ComparePrice);
for (int i = 0; i < PriceRanges.Count; i++)
{
for (int j = PriceRanges[i].MaxAmount; j >= PriceRanges[i].MinAmount; j--)
{
if (j <= AmountsOfLicensesleft)
{
OrderPackage Order = new OrderPackage();
Int32 AmountOfThisPackage = AmountsOfLicensesleft / j;
//Int32 AmountForThisPrice = Convert.ToInt32(Math.Floor(tmp));
Order.PriceRange = PriceRanges[i];
Order.AmountOfLicenses = j;
Total += Order.AmountOfLicenses * Order.PriceRange.PricePerLicense;
for (int k = 0; k < AmountOfThisPackage; k++)
{
result.Add(Order);
}
AmountsOfLicensesleft = AmountsOfLicensesleft - (AmountOfThisPackage * j);
}
}
}
return result;
}
private static int ComparePrice(PriceRange x, PriceRange y)
{
if (x.PricePerLicense == y.PricePerLicense)
return 0;
if (x.PricePerLicense > y.PricePerLicense)
return 1;
if (x.PricePerLicense < y.PricePerLicense)
return -1;
return 0;
}
public class OrderPackage
{
public PriceRange PriceRange { get; set; }
public Int32 AmountOfLicenses { get; set; }
}
public class PriceRange
{
public int MinAmount { get; set; }
public int MaxAmount { get; set; }
public Double PricePerLicense { get; set; }
}
}
Usage example:
private void button1_Click(object sender, EventArgs e)
{
// Preparing PriceRangeDefinitions
List<PriceCalculator.PriceRange> PriceRangeDefinitions = new List<PriceCalculator.PriceRange>();
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 1, MaxAmount = 10, PricePerLicense = 50 });
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 11, MaxAmount = 20, PricePerLicense = 40 });
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 21, MaxAmount = 30, PricePerLicense = 30 });
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 31, MaxAmount = 50, PricePerLicense = 20 });
// Start the Calculation
PriceCalculator calculator = new PriceCalculator();
Double Total;
List<PriceCalculator.OrderPackage> Packages =
calculator.CalculateCheapestPrice(130, PriceRangeDefinitions, out Total);
// Show Proof of Concept
String ProofOfConcept = String.Empty;
for (int i = 0; i < Packages.Count; i++)
{
ProofOfConcept += Packages[i].AmountOfLicenses.ToString() + " Licenses " +
Packages[i].PriceRange.PricePerLicense.ToString() + "$ each" + Environment.NewLine;
}
ProofOfConcept += Environment.NewLine + "TOTAL: " + Total.ToString();
MessageBox.Show(ProofOfConcept);
}
A KeyValuePair collection or dictionary maybe?