Recursive function to calculate time of a hierarchy - c#

I'm having problem with a recursive function for calculating the time of an hierarchy. Every item in the hierarchy have list of its subordinates and what I'll like to do is getting the time sum of all the step below when calling the function. The problem is that I have a time driver that the time should be multiplied by. Say for instance that the last step in the hierarchy have the time driver 2 and the step above it the time driver 4, the third step from the bottom should then get the time for 4 of those steps under which each one contains 2 of the first step. Hope you get the idea.
public double getIdealTime(double sum, bool first)
{
if (first)
{
sum += this.idealTime;
first = false;
}
else
{
sum += this.idealTime * this.timeDriverNumber;
}
foreach (var prodel in this.subordinates)
{
sum = prodel.getIdealTime(sum, first);
}
return sum;
}
The "first" true and false is just a solution to not get the time of all the steps (the time x the time drivers) for the actual step but for only one of that instance.
The problem is that the function doesn't give me the right output value. I'm not sure why, but it feels like the function goes "top to bottom" instead of "bottom to top". That is, since one usually only set the time for the last items and then calculate the times using the subordinates and its subordinates, it doesn't multiplicate with any other timedriver than the last one.
An example:
Step 1
step 2 time driver 8
Step 2.1 = 3s time driver 4
Step 2.2 = 4s time driver 3
Should for step 1 generate (4*3 + 3*4) * 8 = 192 seconds but gives me 24 seconds since it doesn't multiply with step twos timedriver of 8. Step 2 gives me 24 seconds as it should since it should give me the time for one of the step 2 only.
Edit: I've tried to work out a working example but I can't simplify the code to build around it enough to get something I could publish here. I'd still really appreciate some help though!

Related

Are DateTimes passed by reference in C#? If not, why is my object updating as I change a variable?

I have ran into a problem which I simply cannot get my head around. When I debug the program, I can see the program works fine - this is the strange part.
The issue I am facing is when I append to a List with the new object - it seems to completely change. Let me explain better by showing my code.
System.DateTime timeNow = System.DateTime.Now;
List<Train> trainsOnNet = new List<Train>();
for(int i = 1; i <= 3; i++)
{
Train t = new Train();
t.NewCarrige(true, "A"[0]);
t.NewCarrige(false, "B"[0]);
t.addStation(App.Stations.FirstOrDefault(x => x.GetShortCode().Equals("MTG")));
t.addStation(App.Stations.FirstOrDefault(x => x.GetShortCode().Equals("BNS")));
t.addStation(App.Stations.FirstOrDefault(x => x.GetShortCode().Equals("BSH")));
int minsToAdd = 5;
t.GetStations().ForEach(x =>
{
timeNow = timeNow.AddMinutes(minsToAdd);
x.SetArrivalTime(timeNow);
minsToAdd += 10;
});
timeNow = timeNow.AddMinutes(15);
trainsOnNet.Add(t);
}
When I add t to the trainsOnNet List, the time seems to change to the last time that the loop will generate, even before it generates.
If I place a stopper on this line, I can see that the t instance has the correct time variables (ie, 5 minutes from the current execution time and then 10 minutes between each). However, when I then press continue and inspect the trainsOnNet list. This time has been changed to the next trains set of times.
It appears to me that timeNow is being passed by reference, and as the loop increases the time, the stored time updates until I am left with 3 trains all saying the same time.
For example, if I execute the program at 1951 with a stopper on trainsOnNet.Add(t) I can see that t holds 3 stations, in which the first stations Arrival time is 19:56 and the second is 20:11 and 20:26. Perfect. I then hit continue and inspect the newly appended object to my list. On inspection, the t instance arrival time properties have now changed to:
20:56, 21:11, 21:36
Doing the maths of my code, the next train should arrive 20 minutes after the previous train has arrived at the end station. Which brings me to 20:46. Thus deeming it more confusing why the first train is being changed past the second trains expected time let alone being updated without stating to do so.
Any ideas would be greatly appricated.
Stop on the line on the first execution:
Stop on same line, after pressing continue (changed properties):
As you can see, the values are being changed? In this case, by a whole hour?
System.DateTime is a "value type". You can check that by seeing on your intellisense in Visual Studio or in the documentation that it is declared as a struct, not a class (the latter are reference types).
Your problem, however, is not really about this.
It's not clear what you exactly intend to do, and the flaw is probbaly in your logic implementation.
1 - you reuse the same variable timeNow for all iterations, it's hard (at least to me) to keep track on how much it is supposed to be and how much the value is after a few "mental" iterations.
2 - you set minsToAdd to 5, then increase it by 10 in loop. So, after a few iterations of the inner loop, minsToAdd gets these values :
15, 25, 35, 45, etc...
Then, you add this to timeNow, so imagine that timeNow is 00:00 at the beginning, in the inner loop it gets values
00:05,
00:05 + 15min = 00:20
00:20 + 25min = 00:55
00:55 + 35min = 01:30
etc...
and after the inner loop you add 15 min to the last value.
Is that what you expect?
Try to change these two lines:
timeNow = timeNow.AddMinutes(minsToAdd);
x.SetArrivalTime(timeNow);
To just:
x.SetArrivalTime(timeNow.AddMinutes(minsToAdd));
As others explained, you're overriding the timeNow variable with each iteration. This change should give you the expected result.

double value in settings file giving wrong calculation results

I've inserted a variable of type Double in the application/settings file and I'm using a "while" loop to do a small calculation:
double final=0;
double cost = application.settings.default.cost; // 0.15
while(true)
{
Thread.Sleep(1000); //speeded up version of 60000 (1 minute)
final+=cost;
//code that waits for the user to quit the loop
}
the result after 1 hour should be 9.00 but it's calculating to something like 24.00 :/
however, if I hardcode the value in to the code, I get the desired result of 9.00
double final=0;
double cost = 0.15
while(true)
{
Thread.Sleep(1000); //speeded up version of 60000 (1 minute)
final+=cost;
//code that waits for the user to quit the loop
}
Any ideas?
Thread.Sleep(1000); does not mean that your code is executed exactly every second.
If you run your code this way 10 times for 1 hour you will get 10 different results.
This was discussed here as well:
How accurate is Thread.Sleep(TimeSpan)?
(although there Thread.Sleep is used with a TimeSpan. The main issue stays the same)
Edit:
I don't know what exactly your are calculating. But calculating costs in this way is not a good approach as it is very inaccurate.
Better take a timestamp when you start calculating your costs and take another one when you are finished. Take the difference of both timestamps and you can calculate the costs quite accurately. Your method gets more and more inacurrate the longer your code us running.

Sorting numbers array issue

Yesterday at work I set out to figure out how to sort numbers without using the library method Array.Sort. I worked on and off when time permitted and finally was able to come up with a basic working algorithm at the end of today. It might be rather stupid and the slowest way, but I am content that I have a working code.
But there is something wrong or missing in the logic, that is causing the output to hang before printing the line: Numbers Sorted. (12/17/2011 2:11:42 AM)
This delay is directly proportionate to the number of elements in the array. To be specific, the output just hangs at the position where I put the tilde in the results section below. The content after tilde is getting printed after that noticeable delay.
Here is the code that does the sort:
while(pass != unsortedNumLen)
{
for(int i=0,j=1; i < unsortedNumLen-1 && j < unsortedNumLen; i++,j++)
{
if (unsorted[i] > unsorted[j])
{
pass = 0;
swaps++;
Console.Write("Swapping {0} and {1}:\t", unsorted[i], unsorted[j]);
tmp = unsorted[i];
unsorted[i] = unsorted[j];
unsorted[j] = tmp;
printArray(unsorted);
}
else pass++;
}
}
The results:
Numbers unsorted. (12/17/2011 2:11:19 AM)
4 3 2 1
Swapping 4 and 3: 3 4 2 1
Swapping 4 and 2: 3 2 4 1
Swapping 4 and 1: 3 2 1 4
Swapping 3 and 2: 2 3 1 4
Swapping 3 and 1: 2 1 3 4
Swapping 2 and 1: 1 2 3 4
~
Numbers sorted. (12/17/2011 2:11:42 AM)
1 2 3 4
Number of swaps: 6
Can you help identify the issue with my attempt?
Link to full code
This is not homework, just me working out.
Change the condition in your while to this:
while (pass < unsortedNumLen)
Logically pass never equals unsortedNumLen so your while won't terminate.
pass does eventually equal unsortedNumLen when it goes over the max value of an int and loops around to it.
In order to see what's happening yourself while it's in the hung state, just hit the pause button in Visual Studio and hover your mouse over pass to see that it contains a huge value.
You could also set a breakpoint on the while line and add a watch for pass. That would show you that the first time the list is sorted, pass equals 5.
It sounds like you want a hint to help you work through it and learn, so I am not posting a complete solution.
Change your else block to the below and see if it puts you on the right track.
else {
Console.WriteLine("Nothing to do for {0} and {1}", unsorted[i], unsorted[j]);
pass++;
}
Here is the fix:
while(pass < unsortedNumLen)
And here is why the delay occurred.
After the end of the for loop in which the array was eventually sorted, pass contains at most unsortedNumLen - 2 (if the last change was between first and second members). But it does not equal the unsorted array length, so another iteration of while and inner for starts. Since the array is sorted unsorted[i] > unsorted[j] is always false, so pass always gets incremented - exactly the number of times j got incremented, and that is the unsortedNumLen - 1. Which is not equal to unsortedNumLen, and so another iteration of while begins. Nothing essentially changed, and after this iteration pass contains 2 * (unsortedNumLen - 1), which is still not equal to unsortedNumLen. And so on.
When pass reaches value int.MaxValue, it the overflow happens, and next value the variable pass will get is int.MinValue. And the process goes on, until pass finally gets the value unsortedNumLen at the moment the while condition is checked. If you are particularly unlucky, this might never happen at all.
P.S. You might want to check out this link.
This is just a characteristic of the algorithm you're using to sort. Once it's completed sorting the elements it has no way of knowing the sort is complete, so it does one final pass checking every element again. You can fix this by adding --unsortedNumLen; at the end of your for loop as follows:
for(int i=0,j=1; i < unsortedNumLen-1 && j < unsortedNumLen; i++,j++)
{
/// existing sorting code
}
--unsortedNumLen;
Reason? Because you algorithm is bubbling the biggest value to the end of the array, there is no need to check this element again since it's already been determined to be larger the all other elements.

algorithms for tournament brackets (NCAA, etc.)

I'm trying implement a bracket in my program (using C#/.NET MVC) and I am stuck trying to figure out some algorithm.
For example, I have a bracket like this with 8 entries (A,B,C,D,E,F,G,H)
I'm trying to figure out if there's an algorithmic way to
depending on # of entries, find # of
games per round
depending on # of entries, for a
specific game #, what is the
corresponding game # in the next
round?
For example, in this case, for 8 entries, the example are:
for round 1, there are 4 games. Round 2, 2 games. Round 3, 1 game
game 2 in round 1 corresponds to game 5 in round 2.
I also thought about storing this info in a table, but it seems overkill since it never changes, but here it is anyway:
Any help will be greatly appreciated!
Cheers,
Dean
C# code for the first part of your question:
// N = Initial Team Count
// R = Zero-Based Round #
// Games = (N / (2 ^ R)) / 2
public double GamesPerRound(int totalTeams, int currentRound) {
var result = (totalTeams / Math.Pow(2, currentRound)) / 2;
// Happens if you exceed the maximum possible rounds given number of teams
if (result < 1.0F) throw new InvalidOperationException();
return result;
}
The next step in solving part (2) is to know the minimum game number for a given round. An intuitive way to do that would be through a for loop, but there's probably a better method:
var totalTeams = 8;
var selectedRound = 2;
var firstGame = 1;
// If we start with round 1, this doesn't execute and firstGame remains at 1
for (var currentRound = 1; currentRound < selectedRound; currentRound++) {
var gamesPerRound = GamesPerRound(totalTeams, currentRound);
firstGame += gamesPerRound;
}
Quoting #Yuck who answered the first question perfectly.
C# code for the first part of your question:
// N = Initial Team Count
// R = Zero-Based Round #
// Games = (N / (2 ^ R)) / 2
public double GamesPerRound(int totalTeams, int currentRound) {
var result = (totalTeams / Math.Pow(2, currentRound)) / 2;
// Happens if you exceed the maximum possible rounds given number of teams
if (result < 1.0F) throw new InvalidOperationException();
return result;
}
Moving on to the second question:
//G = current game.
//T = total teams
//Next round game = (T / 2) + RoundedUp(G / 2)
//i. e.: G = 2, T = 8
//Next round game = (8 / 2) + RoundedUp(2 / 2) = 5
public int NextGame(int totalTeams, int currentGame) {
return (totalTeams / 2) + (int)Math.Ceiling((double)currentGame / 2);
}
I actually worked this out myself fairly recently and stumbled on (that is, I worked it out, but it has probably been discovered before) a neat recursive solution.
You start with your list of players, in a list that is sorted in seed order. This will be important later.
The overall algorithm consists of splitting the list of players into two and then creating two sub-tournaments. The winners of the two sub-tournaments will end up the grand final of the overall tournament.
Required Objects
Player
Name
Seed
Match
Home Player
Away Player
Next Match (pointer to the Match the winner goes to)
Splitting the Lists
Most tournaments put the top seeded player against the bottom seeded player in round one. In order to do this I used the following algorithm, but you could just put the first n / 2 players in one list and the rest in the other list to create a tournament where seeds 1 and 2 play off in round one (and seed 3 plays 4, 5 plays 6 etc).
I'll note here that the neat thing about having top seed play bottom seed is that with this algorithm if you don't have a power of two number of players, the top seed(s) will get a bye in the early rounds.
Take the first player and put them in the "left" list
Take the next two players (or the last player) and put them in the "right" list
Take the next two player and put them in the "left" list
Repeat from step 2 until there are no more players.
Of course, if there are only two players in the list you simply create a match between them and return.
Building the Tournament
So you start out with a list of say, 64 players. You split it into two lists of 32 players and recursively create two sub tournaments. The methods that you call recursively should return the Matches that represent the sub-tournament's grand final match (the semi-final of your overall tournament). You can then create a match to be the grand final of your overall tournament and set the nextMatch of the semi final matches to be this grand final.
Things to Consider
You'll need to break out of recursing if there are only two players in the list that's passed in.
If your split gives you a list of one, shouldn't recurse with it. Just create a sub-tournament with the other list (it should only have two players so will return with a match immediately), set the home team to be the single player and the nextMatch of the sub-tournament.
If you want to be able to keep track of rounds, you'll need to pass a recursion depth integer - increment it when you create a sub-tournament.
Hope this helps, let me know if you need any clarification :)
So basically its a elimination contest.
So just have List.
The algorithm will always put the first and second teams together if the number of teams is even. You then increase the counter by two and repeat.
If the number of teams is odd do pretty much the samething except you randomly select a winner of the "first around" and put it against the odd team.
After the first round you repeat the algorithm the same way.
A+1
C+1
...
For example, I have a bracket like
this with 8 entries (A,B,C,D,E,F,G,H)
You should be able to figure out how to parse this. This seems like a homework question.
Consider renumbering the games (you can always renumber them back afterwards)
if the final is 1
semis are 2,3
the problem is then has well-published solutions: ahnentafel (German for ancestor table) has been used for a long time by genealogists - http://en.wikipedia.org/wiki/Ahnentafel
one interesting part of this is the binary notation of the game # gives a lot of information as to the structure of the tournament and where in the tree the match is.
Also note that as every match knocks out 1 competitor, for n competitors there will be n-1 matches

Increase value over time using mathematical algorithm

I am writing a test tool which places a large amount of load on a network service. I would like this tool to start with little load and gradually increase over time. I am sure that there is some triganometry which can do this sort of calculation in one line of code but I am not a math guru (yet). Is there some sort of library (or simple algorithm) which can help with this calculation?
The code would ideally take a few arguments:
algorithm to use (determine how quickly the value increases
starting value
ending value (maximum)
time (amount of time between starting and ending value)
step (granularity in milliseconds)
So every [step] an event would be raised indicating what the value is at that point in time.
This is an ideal implementation though, so I am open to suggestion.
Any input would be greatly appreciated, thank you :)
EDIT:
Let me be more clear ... the amount which the value increases is not linear, it is a curve.
If you desire some form of saturation (see Sigmoid function), have a look at my answer here. Another common function shape would be linear or exponential growth. Just let me know if you need one of the later.
I think what you need is some easing function.
There is a set of famous easing functions created by Robert Penner. You may try to look at:
Tweener transition cheat sheets which visualize Robert Penner's equations.
Robert Penner's original code should be at his webpage.
value = (endValue - StartValue) / (time / stepSize) * currentStep;
heck just add one each time the timer goes off
If I understood correctly, why not do this (using the "variables" you defined):
You need to progress overall ending value - starting value values.
Using the time variable, you can figure out how much of an increase you want every millisecond (let's call this increase-amount).
Step just tells you how much time to "sleep" between each value you raise. Every time a new value is raised, you just do last-value + (milliseconds-since-last_step * increase-amount).
Note: I'm not sure why you need the first variable (algorithm to use), since it seems to me that its role is defined by the other variables.
Are you looking for something like this ? (in python, sorry, my C# is rusted at best)
Given you have a curve f that takes values from 0 to 1:
def my_stepper(f, start, end, time, step_size, current_step):
x = current_step * step_size / time
f_1 = f(1)
f_0 = f(0)
y = start + (end - start) * (f(x)- f_0) / (f_1 - f_0)
return y
for i in xrange(11):
# increment increases over time
print 'exp', my_stepper(math.exp, 100., 200., 10., 1., i)
# increment decreases over time
print 'log', my_stepper(lambda x: math.log(1+x), 100., 200., 10., 1., i)
Pseduo logic to your problem:
let the function be F(a+b*x) for given step x,
let the starting value is start,
let the ending value is end
let the starting time is 0 and final time is time
and InverseF is the inverse function of F.
when x=0, F(a)=start Hence a= InverseF(start)
when x=time, F(a+b*time)=end, Hence b=(InverseF(end)-a)/time which reduces to b= (inverseF(end)-inverseF(start))/time
Finaly for any x=step,
value is F(a+b*step) which is
nothing but
F( inverseF(start)+ (inverseF(end)-inverseF(start))/time * step )
is the answer.
For example if
F(x) is liner ie) f(x)=x
value = start+(end-start)/time*step
if F(x) is x*x, then
value = ( sqrt(start) + (sqrt(end)-sqrt(start))/time * step) * ( sqrt(start) + (sqrt(end)-sqrt(start))/time * step)
if F(x) is exp(x) then
value = Exp ( log(start) + (log(end)-log(start))/time*step )
if F(x) is log(x) then
value = Log( (exp(start) + (exp(end)-exp(start))/time*step )
and so on..
another approach without using inverse function is explained below.
let the function be a+b*F(x) for given step x,
let the starting value is start,
let the ending value is end
let the starting time is 0 and final time is time
then a+ b * F(0) = start and a + b * F(time) = end, on solving a & b,
you will get
value = start + (end-start) / (F(time)-F(0) ) * (F(x)-F(0) )
and for a step x,
value = start + (end-start) / (F(time)-F(0) ) * (F(step)-F(0) )
and I hope, any one of the above will solve your problem..
I'll reuse my answer to another question. The functions given for that answer will not spend much time doing low load, but quickly go to medium-heavy load and then increase load slower to reach maximum. If you need more values on the in the middle of the possible loads, or more values in the low load - just pass appropriate distribution function.
Given your input parameters I would call it like this:
Spread(startingValue, endingValue, time/step, x => 1-(1-x)*(1-x))
Sample algorithm functions:
FocusOnHighLoad = x => 1-(1-x)*(1-x)
FocusOnLowLoad = x => x * x
FocusOnMediumLoad = x => (1 + Math.Pow(x * 2 - 1, 3)) / 2
Sample output:
foreach (double load in Spread(50, 1000, 9, FocusOnHighLoad))
Console.WriteLine("Working with {0} load", load);
Working with 50 load
Working with 272.65625 load
Working with 465.625 load
Working with 628.90625 load
Working with 762.5 load
Working with 866.40625 load
Working with 940.625 load
Working with 985.15625 load
Working with 1000 load

Categories

Resources