How to compare time after and before midnight? - time

I have a problem when I am trying to decide if its possible to transfer from one train to another. Conditions are, that arrival (A1) time of the first train must be at least 5 min. before departure of the second train (D2). AND you cannot wait for more than 180 minutes, since you have arrived to the station, for second train to arrive (A2) (You can wait in the second train to departure arbitrarily)?
Time you have to eneter is in format: HH:MM
I did compare those times after I have converted them to minutes elapsed since midnight.
The problem is, that if you want to compare times before midnight with time after midnight, you has to change "if condition" in this cases: A1 and D2 is after midnight but A2 is before midnight, A1 and A2 are before midnight and D2 is after midnight, A1 is before and A2 and D2 is after, A1 and A2 are before midnight (but A2 is sooner) and D2 is after midnight.
In all of those cases you would have to have different condition. How to solve this?
PS: I think I should use different time format (not minutes since midnight), but how?
Thank you!

I suggest you use 24 hour time. That way if the second time is lower then you know that it rolled over to the next day.
If the second time is lower then all you would have to do is:
A1 - D1 = (D)ifference
A1 - D = time before D1 leaves (so the time between A1 and D1)
(can someone check my math? I think that is right.)

Don't judge the values based on minutes elapsed since midnight. Judge them based on their actual values. Most any programming language you would deal with would have date/time classes/functions that you can use to do simple date subtraction. If you update your question to indicate what language you are using, I am sure you will be able to get practical code examples.
As a generic UNIX/LINUX practice, for example, you might convert the value to UNIX timestamps and just subtract to get the time difference in seconds.

Can you convert to a DateTime and then do DateDiff?
Pseudocode (syntactically wrong):
If DateDiff(minutes, A1, D2) > 5 Then
If DateDiff(minutes, A1, A2) < 180 Then
Go ahead and allow the transfer
else
Look for another train (too long of a wait)
end if 'DateDiff(minutes, A1, A2) < 180
Look for another train (not enough time to transfer)
end if 'DateDiff(minutes, A1, D2) > 5

This is what I am working on for a similar problem with Excel:
( D3 + IF( (C3-D3)>0,5 ; 1 ; 0 ) ) > ( 0,010417 + C3 + IF( (D3-C3)>0,5 ; 1 ; 0 ) )
00:00 = 0 in Excel, 24:00 = 1
I want to know if D3 is more than 15 minutes after C3.
The above formula accomplishes that without having to muck about with dates.
Note the formula depends on C3 and D3 not being more than 12 hours apart, which is always true in my usage scenario so it's no issue.
Laymans terms:
you compare Time1 to (time2 + 15min) but in case there's a midnight switch you check whether the times are more than 12 hours apart and if so add 24h to either Time1 or Time2.
I haven't actually gotten it working yet but that I believe has more to do with Excel being a piece of turd.
In case I overlooked something though be sure to let me know!

Related

Subtract integer from time in Google Speadsheet

Let's say I want to calculate my overtime in Google Spreadsheets. I need the function to either convert an integer (10) to a duration (10:00:00), or vice versa, to be able to perform a calculation.
So,
=A1 - 8
or
=A1 - 8:00:00
should be converted to
10:30:00 - 8:00:00
and return
02:30:00
in order to continue the calculation in another cell.
To convert an integer (or a fraction) representing number of hours to a duration, just divide it by 24. If you put the value 10.5 in A1, then put this formula in B1
=A1/24-"08:00:00"
And format B1 as Duration, you will get 2:30:00 as the cell value. The "real" underlying value, though, will be 0.1041666667 which corresponds to 2.5/24th of a day.

Speeding Monte Carlo in matlab

I'm trying to speed up the following Monte Carlo simulation in matlab:
http://pastebin.com/nS0K7XXa
and this is the full result of the matlab profiler
http://i.imgur.com/bGFY5e7.png
I am pretty new at using matlab, but I spent a good deal of time already on this and I think I'm missing something somewhere, because I have the feeling that this should run much faster.
I'm concerned about the lines the profiler show in red of course... lets start with these ones:
time calls line code
37.59 19932184 54 radselec = fix(rand(1)*nr) + 1;
4.54 19932184 55 nm = nm - 1;
45.35 19932184 56 Rad2(radselec) = Rad2(radselec) + 1;
I have a very large vector (Rad2) which holds positive integer values, initially they are all zero but as the simulation progresses it fills up.
line 54 picks a random element of that vector, everytime I add a value to that vector I also add a value to the variable nr, so basically nr is numel(nr) and fix(rand(1)*nr)+1 will pick a random number between 1 and nr.
Question 1: Is there a better way of doing this? rand(1) alone seems to take a long time, as you can see from line 26:
31.50 20540616 26 r = rand(1);
Question 2: line 56 also called my attention... once I have a value for radselec, I need to add +1 to the value of Rad2(radselec).
Now I thought that doing Rad2(radselec) = Rad2(radselec) + 1; was just as fast as doing nm = nm - 1 or +1 for that matter... but the profiler shows that adding +1 to an element of a vector is 10 times slower.
Question 3:
31.50 20540616 26 r = rand(1);
27
22.72 20540616 28 if r > R1/Rt
3.39 20220062 29 reacselec = 2;
10.80 20220062 30 if r > (R1+R2)/Rt
rand(1) seems to be slow as it is... by definition I need that random number between 0 and 1. So I can't think of another way of speeding that line up.
Now... How come line 28 is 2 times slower than line 30 ??? I mean... they are practically the same line with the same calculation... if anything line 30 should be slightle slower for having R1+R2 in the numerator, instead of just R1.
What's happening there?
And finally,
24.26 20540616 79 end
why is that end statement chugging so many time? How can fix that?
Thank you for your time, and sorry if this questions are too basic. I just started programming a few months ago, and I do not have a computer science background. I'm thinking on taking some courses, but that's not a priority.
Any help will be very appreciated.

Compute arrival date given departure date and duration

I am trying to make a program to calculate when train comes for a to b.
I have time when train leaves and the time it takes to travel to distance from a to b.
I need help a algorithm to find if that train bypasses 24 hours.
Like I got these times: Train leaves at 20:55, train ride time - 11:40.
The result should be 8:35, but how could I get it?
program troleibusai;
var xxx:integer ;
f,g:text ;
a:real;
Begin
Assign(F,'train_times');
Reset(F);
Assign(G,'results.txt');
Rewrite(G);
Read(F,left_hour);
Read(F,left_minute);
Read(F,ride_hour);
Read(F,ride_minute);
Heres the code.
Have a look at the between functions in unit dateutils,
e.g. http://www.freepascal.org/docs-html/rtl/dateutils/minutesbetween.html
Calculate left_hour * 60 + left_minute + ride_hour * 60 + ride_minute
and get it div 60 and mod 60

Algorithm to smooth numbers with variable input time

I have an app that accepts integers at a variable rate every .25 to 2 seconds.
I'd like to output the data in a smoothed format for 3, 5 or 7 seconds depending on user input.
If the data always came in at the same rate, let's say every .25 seconds, then this would be easy. The variable rate is what confuses me.
Data might come in like this:
Time - Data
0.25 - 100
0.50 - 102
1.00 - 110
1.25 - 108
2.25 - 107
2.50 - 102
ect...
I'd like to display a 3 second rolling average every .25 seconds on my display.
The simplest form of doing this is to put each item into an array with a time stamp.
array.push([0.25, 100])
array.push([0.50, 102])
array.push([1.00, 110])
array.push([1.25, 108])
ect...
Then every .25 seconds I would read through the array, back to front, until I got to a time that was less than now() - rollingAverageTime. I would sum that and display it. I would then .Shift() the beginning of the array.
That seems not very efficient though. I was wondering if someone had a better way to do this.
Why don't you save the timestamp of the starting value and then accumulate the values and the number of samples until you get a timestamp that is >= startingTime + rollingAverageTime and then divide the accumulator by the number of samples taken?
EDIT:
If you want to preserve the number of samples, you can do this way:
Take the accumulator, and for each input value sum it and store the value and the timestamp in a shift register; at every cycle, you have to compare the latest sample's timestamp with the oldest timestamp in the shift register plus the smoothing time; if it's equal or more, subtract the oldest saved value from the accumulator, delete that entry from the shift register and output the accumulator, divided by the smoothing time. If you iterate you obtain a rolling average with (i think) the least amount of computation for each cycle:
a sum (to increment the accumulator)
a sum and a subtraction (to compare the timestamp)
a subtraction (from the accumulator)
a division (to calculate the average, done in a smart way can be a shift right)
For a total of about 4 algebric sums and a division (or shift)
EDIT:
For taking into account the time from the last sample as a weighting factor, you can divide the value for the ratio between this time and the averaging time, and you obtain an already weighted average, without having to divide the accumulator.
I added this part because it doesn't add computational load, so you can implement quite easy if you want to.
The answer from clabacchio has the basics right, but perhaps you need a bit more sophisticated answer.
Calculating the average:
0.25 - 100
0.50 - 102
1.00 - 110
In the above subset of the data what is the answer you want? You could use the mean of these numbers or you could do it in a weighted fashion. You could convert the data into:
0.50 - 0.25 = 0.25 ---- (100+102)/2 = 101
1.00 - 0.50 = 0.50 ---- (102+110)/2 = 106
Then you can take the weighted average of these values, weight being the time difference, and value being the average value.
The final answer = (0.25*101 + 0.5*106)/(0.25+0.5) = whatever the value is.
Now coming to "moving" averages:
You can either use previous k values or previous k seconds worth of data. In both cases you can keep two sums: weighted sum and sum of weights.
So... the worst case scenario is 4 readings per second over 7 seconds = 28 values in your array to process. That will be done in nanoseconds anyway, so not worth optimizing IMHO.

Weighting Different Outcomes when Pseudorandomly Choosing from an Arbitrarily Large Sample

So, I was sitting in my backyard thinking about Pokemon, as we're all wont to do, and it got me thinking: When you encounter a 'random' Pokemon, some specimen appear a lot more often than others, which means that they're weighted differently than the ones that appear less.
Now, were I to approach the problem of getting the different Pokemon to appear with a certain probability, I would most likely do so by simply increasing the number of entries that certain Pokemon have in the pool of choices (like so),
Pool:
C1 C1 C1 C1
C2 C2
C3 C3 C3 C3 C3
C4
so C1 has a 1/3 chance of being pulled, C2 has a 1/6th chance, etc, but I understand that this may be a very simple and naive approach, and is unlikely to scale well with a large number of choices.
So, my question is this, S/O: Given an arbitrarily large sample size, how would you go about weighting the chance of one outcome as greater than another? And, as a follow up question, assume that you want the probability of certain options to occur in a ratio with floating-point precision as opposed to whole number ratios?
If you know the probability of each event happening you need to map these probabilities to the range 0-100 (or 0 to 1 if you want to use real numbers and probabilities.)
So in the example above there are 12 Cs. C1 is 4/12 or ~33%,
C2 is 2/12 of ~17%, C3 is 5/12 or ~42%, and C4 is 1/12 or ~8%.
Notice that these all add up to 100%. So if we choose a random number between 0 and 100 we can map C1 to 0-33, C2 to 33-50 (17 more than C1's value) , C3 to 50-92, and C4 to 92-100.
An if statement could make the choice:
r = rand() # between 0-100
if (r <33)
return "C1"
elsif (r < 50)
return "C2"
elsif (r < 92)
return "C3"
elsif (r < 100)
return "C4"
If you wanted more accuracy than 1 in 100 just go from 1-1000 or whatever range you want. It's probably better form to use integers and scale them rather than use floating point numbers as floating point can have odd behavior if the spread between values gets large.
If you wanted to go the binning route like you show above you could try something like so (in ruby though the idea is more general):
a = ["C1"]*4 + ["C2"]*2 + ["C3"]*5 + ["C4"]
# ["C1", "C1", "C1", "C1", "C2", "C2",
# "C3", "C3", "C3", "C3", "C3", "C4"]
a[rand(a.length)] # => "C1' w/ probability 4/12
Binning would be slower as you need to create the array, but easier to add alternatives as you wouldn't need to recalculate the probabilities each time.
You could also generate the above if code from the array representation so you'd just take the pre-processing hit once when the code was generated and then get a fast answer from the created code.

Resources