Waiting list time calculation - c#

Imagine I had a waiting list with the following in the queue
Service 1 - 5 minutes
Service 2 - 10 minutes
Service 3 - 5 minutes
Service 4 - 15 minutes
Service 5 - 20 minutes
If I have two staff to service these 5 clients in the queue how could I estimate the waiting time for the next person to walk in the store.

Actually it's pretty simple - it's the "W" queue model as described by Eric Lippert.
Set up an array two "staff" members:
List<int>[] staff = new [] {new List<int>(), new List<int>()};
define your queue:
int[] queue = new int[] {5, 10, 5, 15, 20};
Then simulate the processing - each subsequent customer will go to the servicer that is done first:
foreach (int i in queue)
{
List<int> shortest = staff.OrderBy(s=>s.Sum()).First();
shortest.Add(i);
}
The "next" person to come in will have to wait until the first servicer is free, which is the sum of each of the customers served:
int nextTime = staff.Min(s=>s.Sum());
Console.WriteLine("The wait time for the next customer is {0} minutes",nextTime);
Output:
The wait time for the next customer is 25 minutes.

Here's a not-so-elegant way to do it...
private static int GetEstimatedWaitTime(Queue<int> currentQueue, int numServers)
{
int waitTime = 0;
// Short-circuit if there are more servers than items in the queue
if (currentQueue.Count < numServers) return waitTime;
// Create a copy of the queue so we can dequeue from it
var remainingItems = new Queue<int>();
foreach (var item in currentQueue)
{
remainingItems.Enqueue(item);
}
// Grab an item for each server
var itemsBeingServiced = new List<int>();
for (int i = 0; i < numServers; i++)
{
itemsBeingServiced.Add(remainingItems.Dequeue());
}
do
{
// Get the shortest item left, increment our wait time, and adjust other items
itemsBeingServiced.Sort();
var shortestItem = itemsBeingServiced.First();
waitTime += shortestItem;
itemsBeingServiced.RemoveAll(item => item == shortestItem);
for (int i = 0; i < itemsBeingServiced.Count; i++)
{
itemsBeingServiced[i] = itemsBeingServiced[i] - shortestItem;
}
// Add more items for available servers if there are any
while (itemsBeingServiced.Count < numServers && remainingItems.Any())
{
itemsBeingServiced.Add(remainingItems.Dequeue());
}
} while (itemsBeingServiced.Count >= numServers);
return waitTime;
}

Related

C#, For Loop Inside Parallel For Loop Not Working Correctly

This is my code, and not working correctly.
Normal for loop from 0 to UrlList Count. Maybe 1500 - 2000;
After Every 10 loop, controlling session. If not exists or timeout, going and refresh. And This point first parallel loop working correctly.
i = 10 and x = between 0 and 9.
And Later, parallel for not working. I'm watching with "add watch" for x.
x is not changing. The last number in the first loop remains what it is.
What can I do?
TokenController control = new TokenController();
for (int i = 0; i < UrlList.Count; i++)
{
if(control.SessionControl(false, 0))
{
Parallel.For(i, 10, x => {
//HttpRequest
});
i += 9;
}
}
The second parameter for Parallel.For is the "to" (exclusive) value, not the "number of repetitions":
public static ParallelLoopResult For(
int fromInclusive,
int toExclusive,
Action<int> body
)
In your code that means that after the first iteration, the from will be equal or larger than the to value.
So your code should be:
Parallel.For(i, i + 10, x => {
//HttpRequest
});
It seems that you have problems with ranges; depending on what you want it's either
for (int i = 0; i < UrlList.Count; i++) {
// at 0th, 10th, 20th ... N * 10 ... position
if (i % 10 == 0) {
// Control session:
// HttpRequest ...
}
}
or
int step = 10;
for (int i = 0; i < UrlList.Count; ++i) {
// Control session can appear at any moment, indepent on i
if (control.SessionControl(false, 0)) {
// When we at i-th postion we want 10 loops more: i + step
// not from i to step
Parallel.For(i, i + step, x => {
//HttpRequest
});
i += (step - 1);
}
}

Substract 1 from x-axis of all elements of List<PointF>

I am reading samples from a serial port continously and I want to show the last 400 samples in a graph.
So when the number of received samples becomes 400 I should shift the myPointFsList to left by 1 and add the last received sample
to the end of it. My below code works successfully while the first 400 samples.
List<PointF> myPointFs = new List<PointF>();
uint sampleNumber = 0; PointF Current_PointFs;
private void UpdateVar(object sender, EventArgs e){
...
Current_PointFs = new PointF((float)(sampleNumber), (float)newSample);
if (sampleNumber < 400)
{
myPointFs .Add(Current_PointFs);
++sampleNumber;
}
else
{
myPointFs = myPointFs .ShiftLeft(1); //ShiftLeft is an Extension Method
myPointFs.Add(Current_PointFs);
}
if (myPointFs.Count >= 2)
{
Configure_Graphs();// using Graphics.DrawLines(thin_pen, myPointFs.ToArray()) to draw chart
}
}
But after that the first 400 samples recieved, I need to substract 1 from myPointFs[i].X to shift X-axis to left by 1. Maybe a way is to run a for loop.
How can I implement it? Or is there any more elegant way? Or something that it exists out-of-the-box in C#?
Edit: (To make my question more clear)
myPointFs contains something like this:
myPointFs[0] = {X = 1, Y = 21}
myPointFs[1] = {X = 2, Y = 50}
myPointFs[2] = {X = 3, Y = 56}
now I will remove the first element by shifting left by 1 and add a new sample to the end.
myPointFs[0] = {X = 2, Y = 50}
myPointFs[1] = {X = 3, Y = 56}
myPointFs[2] = {X = 4, Y = 68}
But I need finally something like this:
myPointFs[0] = {X = 1, Y = 50}
myPointFs[1] = {X = 2, Y = 56}
myPointFs[2] = {X = 3, Y = 68}
So, you want to remove the first element and decrement the X value of each remaining point. You can do that in one go:
myPointFs = myPointFs.Skip(1).Select(p => new PointF(p.X-1, p.Y)).ToList();
That is job for Queue<T>. In your case X will be index and Y will be data inserted into Queue.
Here's some code to show how that works:
static void Main(string[] args)
{
var queue = new Queue<int>(10); //Capacity of Queue is 10
Console.WriteLine("=== Writing to Queue ===");
for (int i = 0; i < 23; ++i) //22 rounds for inserting data
{
DequeueIfFull(i, queue);
Console.WriteLine("Inserting number {0} into Queue", i);
queue.Enqueue(i); //Read and remove the first item in Queue
}
FlushQueue(queue); //Last time read all values from queue
Console.ReadKey();
}
private static void DequeueIfFull(int i, Queue<int> queue)
{
var tenthItemInserted = (i != 0) && (i % 10 == 0);
if (tenthItemInserted)
{
Console.WriteLine("Dequeuing from Queue");
for (int j = 0; j < 10; ++j)
{
Console.WriteLine(" Number dequeued on position {0} is {1}", j, queue.Dequeue());
}
}
}
private static void FlushQueue(Queue<int> queue)
{
Console.WriteLine();
Console.WriteLine("=== Reading final Queue state ===");
var index = 0;
foreach (var itemInQueue in queue)
{
Console.WriteLine("At position {0} is number {1} ", index, itemInQueue);
index++;
}
}
Documentation for Queue and link to nice articles about Data Structures.

Pagination of multiple sorted lists

I have an unknown number of ordered lists that I need to do paging on.
For example, the pages for these 3 lists should look like this when the page size is 6.
List1: 01,02,03,04,05,06,07,08,09,10
List2: 11,12,13,14,15
List3: 16,17,18,19,20,21,22,23,24,25,26,27,28
Result Pages:
Page1: 01,11,16,02,12,17
Page2: 03,13,18,04,14,19
Page3: 05,15,20,06,21,07
Page4: 22,08,23,09,24,10
page5: 25,26,27,28
What will be the most efficient way to get which items should I take from each list (start index and number of items) when given the page number?
Take in consideration that each list can have a few hundred thousand of items so iterating through all of them will not be efficient.
I can't say if it's the most efficient way or not, but here is an algorithm with O(M*Log2(M)) time complexity where M is the number of the lists. It works as follows. The input set is grouped and sorted in ascending order by the item Count, which is iterated until the effective start index fits into current range, skipping the previous ranges. This is possible because at every step we know that it is the minimum count, hence all the remaining lists have items in that range. Once we are done with that, we emit the page items from the remaining lists.
Here is the function:
static IEnumerable<T> GetPageItems<T>(List<List<T>> itemLists, int pageSize, int pageIndex)
{
int start = pageIndex * pageSize;
var counts = new int[itemLists.Count];
for (int i = 0; i < counts.Length; i++)
counts[i] = itemLists[i].Count;
Array.Sort(counts);
int listCount = counts.Length;
int itemIndex = 0;
for (int i = 0; i < counts.Length; i++)
{
int itemCount = counts[i];
if (itemIndex < itemCount)
{
int rangeLength = listCount * (itemCount - itemIndex);
if (start < rangeLength) break;
start -= rangeLength;
itemIndex = itemCount;
}
listCount--;
}
if (listCount > 0)
{
var listQueue = new List<T>[listCount];
listCount = 0;
foreach (var list in itemLists)
if (itemIndex < list.Count) listQueue[listCount++] = list;
itemIndex += start / listCount;
int listIndex = 0;
int skipCount = start % listCount;
int nextCount = 0;
int yieldCount = 0;
while (true)
{
var list = listQueue[listIndex];
if (skipCount > 0)
skipCount--;
else
{
yield return list[itemIndex];
if (++yieldCount >= pageSize) break;
}
if (itemIndex + 1 < list.Count)
{
if (nextCount != listIndex)
listQueue[nextCount] = list;
nextCount++;
}
if (++listIndex < listCount) continue;
if (nextCount == 0) break;
itemIndex++;
listIndex = 0;
listCount = nextCount;
nextCount = 0;
}
}
}
and test:
static void Main(string[] args)
{
var data = new List<List<int>>
{
new List<int> { 01, 02, 03, 04, 05, 06, 07, 08, 09, 10 },
new List<int> { 11, 12, 13, 14, 15 },
new List<int> { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 },
};
int totalCount = data.Sum(list => list.Count);
int pageSize = 6;
int pageCount = 1 + (totalCount - 1) / pageSize;
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++)
Console.WriteLine("Page #{0}: {1}", pageIndex + 1, string.Join(", ", GetPageItems(data, pageSize, pageIndex)));
Console.ReadLine();
}
I think it could be done nicely in two steps:
Flatten your lists to a single list (ordered in the way you describe).
Take items from that list for the desired page.
To accomplish step 1, I'd do something like what was suggested here: Merging multiple lists
So, (assuming your page items are ints, as in your example), here's a nice method that finds exactly the ones you want:
static IEnumerable<int> GetPageItems(IEnumerable<List<int>> itemLists, int pageSize, int page)
{
var mergedOrderedItems = itemLists.SelectMany(x => x.Select((s, index) => new { s, index }))
.GroupBy(x => x.index)
.SelectMany(x => x.Select(y => y.s));
// assuming that the first page is page 1, not page 0:
var startingIndex = pageSize * (page - 1);
var pageItems = mergedOrderedItems.Skip(startingIndex)
.Take(pageSize);
return pageItems;
}
Note - you don't have to worry about passing in a page# that exceeds the total number of pages that could exist given the total item count... Thanks to the magic of Linq, this method will simply return an empty IEnumerable. Likewise, if Take(pageSize) results in less than "pageSize" items, it simply returns the items that it did find.
I'll submit another implementation, based on Bear.S' feedback on my first answer. This one's pretty low-level and very performant. There are two major parts to it:
Figure out which item should appear first on the page (specifically what is the index of the list that contains it, and what is the item's index within that list).
Take items from all lists, in the correct order, as needed (until we have all that we need or run out of items).
This implementation doesn't iterate the individual lists during step 1. It does use List.Count property, but that is an O(1) operation.
Since we're going for performance here, the code isn't necessarily as self-descriptive as I'd like, so I put in some comments to help explain the logic:
static IEnumerable<T> GetPageItems<T>(List<List<T>> itemLists, int pageSize, int page)
{
if (page < 1)
{
return new List<T>();
}
// a simple copy so that we don't change the original (the individual Lists inside are untouched):
var lists = itemLists.ToList();
// Let's find the starting indexes for the first item on this page:
var currItemIndex = 0;
var currListIndex = 0;
var itemsToSkipCount = pageSize * (page - 1); // <-- assuming that the first page is page 1, not page 0
// I'll just break out of this loop manually, because I think this configuration actually makes
// the logic below a little easier to understand. Feel free to change it however you see fit :)
while (true)
{
var listsCount = lists.Count;
if (listsCount == 0)
{
return new List<T>();
}
// Let's consider a horizontal section of items taken evenly from all lists (based on the length of
// the shortest list). We don't need to iterate any items in the lists; Rather, we'll just count
// the total number of items we could get from this horizontal portion, and set our indexes accordingly...
var shortestListCount = lists.Min(x => x.Count);
var itemsWeAreConsideringCount = listsCount * (shortestListCount - currItemIndex);
// Does this horizontal section contain at least as many items as we must skip?
if (itemsWeAreConsideringCount >= itemsToSkipCount)
{ // Yes: So mathematically find the indexes of the first page item, and we're done.
currItemIndex += itemsToSkipCount / listsCount;
currListIndex = itemsToSkipCount % listsCount;
break;
}
else
{ // No: So we need to keep going. Let's increase currItemIndex to the end of this horizontal
// section, remove the shortest list(s), and the loop will continue with the remaining lists:
currItemIndex = shortestListCount;
lists.RemoveAll(x => x.Count == shortestListCount);
itemsToSkipCount -= itemsWeAreConsideringCount;
}
}
// Ok, we've got our starting indexes, and the remaining lists that still have items in the index range.
// Let's get our items from those lists:
var pageItems = new List<T>();
var largestListCount = lists.Max(x => x.Count);
// Loop until we have enough items to fill the page, or we run out of items:
while (pageItems.Count < pageSize && currItemIndex < largestListCount)
{
// Taking from one list at a time:
var currList = lists[currListIndex];
// If the list has an element at this index, get it:
if (currItemIndex < currList.Count)
{
pageItems.Add(currList[currItemIndex]);
}
// else... this list has no more elements.
// We could throw away this list, since it's pointless to iterate over it any more, but that might
// change the indices of other lists... for simplicity, I'm just gonna let it be... since the above
// logic simply ignores an empty list.
currListIndex++;
if (currListIndex == lists.Count)
{
currListIndex = 0;
currItemIndex++;
}
}
return pageItems;
}
Here's some test code, using three lists. I can grab 6 items off of page 1,000,000 in just a few milliseconds :)
var list1 = Enumerable.Range(0, 10000000).ToList();
var list2 = Enumerable.Range(10000000, 10000000).ToList();
var list3 = Enumerable.Range(20000000, 10000000).ToList();
var lists = new List<List<int>> { list1, list2, list3 };
var timer = new Stopwatch();
timer.Start();
var items = GetPageItems(lists, 6, 1000000).ToList();
var count = items.Count();
timer.Stop();

Compare current and last value in list

There is a moving average suppose: 2, 4, 6 , 8 , 10...n;
Then add the current value (10) to list
List<int>numHold = new List<int>();
numhold.Add(currentvalue);
Inside the list:
the current value is added
10
and so on
20
30
40 etc
by using
var lastdigit = numHold[numhold.Count -1];
I can get the last digit but the output is
current: 10 last: 10
current: 20 last: 20
the output should be
current: 20 last: 10
Thanks
Typically, C# indexers start from 0, so the first element has index 0. On the other hand, Count/Length will use 1 for one element. So your
numHold[numhold.Count - 1]
actually takes the last element in the list. If you need the one before that, you need to use - 2 - though be careful you do not reach outside of the bounds of the list (something like Math.Max(0, numhold.Count - 2) might be appropriate).
You can also store the values in separate variables:
List<int> nums = new List<int> { 1 };
int current = 1;
int last = current;
for (int i = 0; i < 10; i++)
{
last = current;
current = i * 2;
nums.Add(current);
}
Console.WriteLine("Current: {0}", current);
Console.WriteLine("Last: {0}", last);
Question is so unclear, but if ur using moving average to draw a line graph 📈 you would use a circular buffer which can be implemented by urself utilizing an object that contains an array of specified size, and the next available position. You could also download a nuget package that already has it done.
A relatively simple way to calculate a moving average is to use a circular buffer to hold the last N values (where N is the number of values for which to compute a moving average).
For example:
public sealed class MovingAverage
{
private readonly int _max;
private readonly double[] _numbers;
private double _total;
private int _front;
private int _count;
public MovingAverage(int max)
{
_max = max;
_numbers = new double[max];
}
public double Average
{
get { return _total / _count; }
}
public void Add(double value)
{
_total += value;
if (_count == _max)
_total -= _numbers[_front];
else
++_count;
_numbers[_front] = value;
_front = (_front+1)%_max;
}
};
which you might use like this:
var test = new MovingAverage(11);
for (int i = 0; i < 25; ++i)
{
test.Add(i);
Console.WriteLine(test.Average);
}
Note that this code is optimised for speed. After a large number of iterations, you might start to get rounding errors. You can avoid this by adding to class MovingAverage a slower method to calculate the average instead of using the Average property:
public double AccurateAverage()
{
double total = 0;
for (int i = 0, j = _front; i < _count; ++i)
{
total += _numbers[j];
if (--j < 0)
j = _max - 1;
}
return total/_count;
}
Your last item will always be at position 0.
List<int>numHold = new List<int>();
numHold.add(currentvalue); //Adding 10
numHold[0]; // will contain 10
numHold.add(currentvalue); //Adding 20
numHold[0]; // will contain 10
numHold[numhold.Count - 1]; // will contain 20
the better way to get first and last are
numHold.first(); //Actually last in your case
numHold.last(); //first in your case

Calculate all possible permutations/combinations, then check if the result is equal to a value

Best way I can explain it is using an example:
You are visiting a shop with $2000, your goal is to have $0 at the end of your trip.
You do not know how many items are going to be available, nor how much they cost.
Say that there are currently 3 items costing $1000, $750, $500.
(The point is to calculate all possible solutions, not the most efficient one.)
You can spend $2000, this means:
You can buy the $1000 item 0, 1 or 2 times.
You can buy the $750 item 0, 1 or 2 times.
You can buy the $500 item 0, 1, 2, 3 or 4 times.
At the end I need to be able to have all solutions, in this case it will be
2*$1000
1*$1000 and 2*$500
2*$750 and 1*$500
4*$500
Side note: you can't have a duplicate solution (like this)
1*$1000 and 2*$500
2*$500 and 1*$1000
This is what I tried:
You first call this function using
goalmoney = convert.ToInt32(goalMoneyTextBox.Text);
totalmoney = Convert.ToInt32(totalMoneyTextBox.Text);
int[] list = new int[usingListBox.Items.Count];
Calculate(0, currentmoney, list);
The function:
public void Calculate(int level, int money, int[] list)
{
string item = usingListBox.Items[level].ToString();
int cost = ItemDict[item];
for (int i = 0; i <= (totalmoney / cost); i++)
{
int[] templist = list;
int tempmoney = money - (cost * i);
templist[level] = i;
if (tempmoney == goalmoney)
{
resultsFound++;
}
if (level < usingListBox.Items.Count - 1 && tempmoney != goalmoney) Calculate(level + 1, tempmoney, templist);
}
}
Your problem can be reduced to a well known mathematical problem labeled Frobenius equation which is closely related to the well known Coin problem. Suppose you have N items, where i-th item costs c[i] and you need to spent exactly S$. So you need to find all non negative integer solutions (or decide whether there are no solutions at all) of equation
c[1]*n[1] + c[2]*n[2] + ... + c[N]*n[N] = S
where all n[i] are unknown variables and each n[i] is the number of bought items of i-th type.
This equation can be solved in a various ways. The following function allSolutions (I suppose it can be additionally simplified) finds all solutions of a given equation:
public static List<int[]> allSolutions(int[] system, int total) {
ArrayList<int[]> all = new ArrayList<>();
int[] solution = new int[system.length];//initialized by zeros
int pointer = system.length - 1, temp;
out:
while (true) {
do { //the following loop can be optimized by calculation of remainder
++solution[pointer];
} while ((temp = total(system, solution)) < total);
if (temp == total && pointer != 0)
all.add(solution.clone());
do {
if (pointer == 0) {
if (temp == total) //not lose the last solution!
all.add(solution.clone());
break out;
}
for (int i = pointer; i < system.length; ++i)
solution[i] = 0;
++solution[--pointer];
} while ((temp = total(system, solution)) > total);
pointer = system.length - 1;
if (temp == total)
all.add(solution.clone());
}
return all;
}
public static int total(int[] system, int[] solution) {
int total = 0;
for (int i = 0; i < system.length; ++i)
total += system[i] * solution[i];
return total;
}
In the above code system is array of coefficients c[i] and total is S. There is an obvious restriction: system should have no any zero elements (this lead to infinite number of solutions). A slight modification of the above code avoids this restriction.
Assuming you have class Product which exposes a property called Price, this is a way to do it:
public List<List<Product>> GetAffordableCombinations(double availableMoney, List<Product> availableProducts)
{
List<Product> sortedProducts = availableProducts.OrderByDescending(p => p.Price).ToList();
//we have to cycle through the list multiple times while keeping track of the current
//position in each subsequent cycle. we're using a list of integers to save these positions
List<int> layerPointer = new List<int>();
layerPointer.Add(0);
int currentLayer = 0;
List<List<Product>> affordableCombinations = new List<List<Product>>();
List<Product> tempList = new List<Product>();
//when we went through all product on the top layer, we're done
while (layerPointer[0] < sortedProducts.Count)
{
//take the product in the current position on the current layer
var currentProduct = sortedProducts[layerPointer[currentLayer]];
var currentSum = tempList.Sum(p => p.Price);
if ((currentSum + currentProduct.Price) <= availableMoney)
{
//if the sum doesn't exeed our maximum we add that prod to a temp list
tempList.Add(currentProduct);
//then we advance to the next layer
currentLayer++;
//if it doesn't exist, we create it and set the 'start product' on that layer
//to the current product of the current layer
if (currentLayer >= layerPointer.Count)
layerPointer.Add(layerPointer[currentLayer - 1]);
}
else
{
//if the sum would exeed our maximum we move to the next prod on the current layer
layerPointer[currentLayer]++;
if (layerPointer[currentLayer] >= sortedProducts.Count)
{
//if we've reached the end of the list on the current layer,
//there are no more cheaper products to add, and this cycle is complete
//so we add the list we have so far to the possible combinations
affordableCombinations.Add(tempList);
tempList = new List<Product>();
//move to the next product on the top layer
layerPointer[0]++;
currentLayer = 0;
//set the current products on each subsequent layer to the current of the top layer
for (int i = 1; i < layerPointer.Count; i++)
{
layerPointer[i] = layerPointer[0];
}
}
}
}
return affordableCombinations;
}

Categories