Alice lives in Russia(GMT+7). Bob lives in Alaska(GMT-8). They are relatively close, and less than 200 miles apart. https://www.google.com/maps/#55.5067319,-173.8489655,3z
Alice and Bob should meet at noon based on an average of their Time Zones so both people are inconvenienced as little as possible. If we average GMT+7 with GMT-8, we come up with GMT-0.5.
This does not work because calculating noon based on GMT-0.5 would be closer to midnight for both, rather than noon because the time zones are calculated linearly instead of circularly.
Does anyone know of a library which can solve Alice, Bob's problem, and also allow Charlie and Dave to join the meeting?
Your GMT-0.5 average is wrong, because to get the time difference we have to take into account the 24 hour cycle and the fact that GMT is half way between both ends of the range.
GMT+0700 is 15 hours ahead of GMT-0800, but as 15 is greater than 12 (more than half way round the Earth) the shortest time difference is actually 9 hours, but on different days.
That maths is pretty easy. In pseudo code:
offset = abs( 7 - -8 )
if offset > 12 then offset = 24 - offset
Gives offset == 9.
So the closest times to local noon for both parties would be 4.5 hours before noon for Alice in Russia (07:30am) and 4.5 hours after noon for Bob in Alaska (16:30pm) but on the previous day because Russia is in the future!
This half way point would be an imaginary time offset we can call GMT+1130, so Bob and Alice would arrange to meet at 00:30 GMT.
For comparison: timeanddate.com has a meeting planner. It rounds to the hour and gives the best overlaps for Krasnoyarsk and Anchorage as 8am/5pm.
See https://www.timeanddate.com/worldclock/meetingtime.html?iso=20180724&p1=372&p2=18
Academic side point: these two timezones are not a mere 200 miles from each other. They are thousands of miles apart. The eastern point of Russia is actually 12 hours ahead of GMT.
Related
I'm a fantasy basketball player and there is a recurring problem that I have not been able to figure out, and I can't find a similar enough example online that I can adapt for my own usage. For those who don't know, streaming (in fantasy basketball) is when you have an open spot on your individual team that you cycle available / free agent players through, in an attempt to maximize points, based on when they play during the week.
For example, Player 1 has games on Monday, Tuesday and Wednesday, and P2 plays on Thursday, Friday and Sunday. You keep P1 rostered through Wednesday, then drop them and pick up P2 for the rest of the week. Both players' points are added to your total; this allows you to essentially benefit from having two players' scoring for the week while only using one roster spot.
M
T
W
Th
F
S
S
Avg Pts / Game
P1
x
x
x
20
P2
x
x
x
25
The optimal strategy yields 135 points, vs 60 or 75 from just playing one player for the whole week.
The complexity comes from three places.
Players you want to play sometimes overlap on the same day, and their schedules often overlap in a way such that it might be worth it to start a worse player early in the week if it means you get access to a slate of their games later in the week. A player may have a lower points per game than another player, but by virtue of playing more games it’s worth it to start the player with a lower average.
Players can’t be re-added for the rest of the week once dropped, due to the nature of the fantasy sports platform. So you can’t toggle back and forth between two good players if they have complementary schedules. Related to this, there are a set number of “adds” you can use per week. Without this you could just add 7 different players, one each day, and figure out who was going to be the best for each day of the week. For the purposes of this league, the number of adds is 4 per week.
There are lots of available players. Figuring this out manually sometimes means starting players who are ranked far outside the top 130 (the total number of players across all of the leagues rosters) in Points Per Game, but due to their scheduling quirks, offer the best value for the remainder of the week. Trying each combination of players against each other involves a huge number of potential options.
I am a CS hobbyist, but the things I build do not require these sorts of optimizations, and I haven’t been able to find an example that would solve all parts of this problem.
Take the below schedule, for example. An “x” indicates the player is playing that day:
M
T
W
Th
F
S
S
Avg Pts / Game
P1
x
x
x
x
20
P2
x
x
x
21
P3
x
x
x
22
The points maximizing solution is to start Player 1 Monday, drop them and switch to Player 2 for the next three days, start no one on Thursday (as P1 would not be available after dropping them), and then switch to Player 3 for the last two days.
Start P1: 20 + 63 + 44 = 127
Constraints:
There are a set number of available days (7)
Only one player can be played per day
Each player can only be added one time (but can play consecutive games after being added with no penalty).
You can only add new players a set number of times: “n”
There are “p” possible players, each of whom has days of the week they can be played and an average points per game (same across all days)
The objective is to return the schedule of players in the proper combination that optimizes the total points in a given week.
My (somewhat brief) look through the existing algorithms led me to considering the knapsack problem, optimal scheduling, and greedy. Greedy doesn’t seem to work because it would immediately decide to start Player 3, which would not ultimately lead to the optimal solution, ending up with 125 total points
The scheduling algorithm would seem to require considering the start and end of a “task” as the first and last day a player plays, which creates problems here; Player 1’s “block” or whole week between first and last day would show that Player 1 offers the best total value at 80 points, and that the optimal strategy would be to just play them, but it doesn’t consider prematurely ending the task if something else was available.
Likewise I can’t figure out how to introduce the “switching” element into solutions to the knapsack problem.
There is a related question here but it doesn't include the scheduling aspect: Algorithm to select Player with max points but with a given cost
I feel like there’s a method that I’m not quite grasping, or a simplification that would allow me to use one of the aforementioned solutions. Any help in solving this completely inconsequential problem is greatly appreciated!
Given a date, is there an algorithm that can convert it to the week of the year?
Absolutely, but it gets very complicated.
In principle you should be able to divide by 60*60*24 = 86400 to get days, then follow the logic of the calendar to figure out days, weeks, years, and calculate the answer from that. There are 365 days in a year, except leap years. Leap years occur on years divisible by 4, except ones divisible by 100, but happen again on years divisible by 400. Since 2000 is divisible by 400, you can ignore the last 2 rules and you will be correct until the year 2100.
You also have to decide what a week is defined as. In the USA it is traditionally defined as Sunday through Saturday. In Europe it is traditionally defined as Monday through Sunday. But you know what day of the week 1970 started on (Thursday), and can therefore figure out the current year, what day of the week it started on, when that week started, and a little modulo 7 arithmetic gives you your answer.
That is...until you notice that actual date boundaries depend on timezone, whether daylight savings time is in effect, and other such things. This opens up a giant can of worms that everyone delegates to the Olson database. (Which itself needs multiple updates a year because some government, somewhere, tweaks their timezone rules.) And then every language and environment wraps their own date-time library around that. You are strongly advised to find and use that.
If time is represented in UTC, this is the end of the story. However in fact we also have leap seconds (27 so far, possibly a negative one coming soon). This is NOT dealt with by Olson or standard date-time libraries. All of whom try to find the most efficient way to ignore that the leap second happened, and pray that they don't crash when the next one comes. (Not a joke. Linux servers around the world crashed on Jul 2, 2012, and large companies have a variety of "time smearing" approaches to avoid it happening again.)
Only specialized tools like Frink deal with the ugliness of leap seconds in their full glory.
Assuming you already have the year, month, and day, here is the solution according to Pandas.
doy = get_day_of_year(year, month, day)
dow = dayofweek(year, month, day)
# estimate
iso_week = (doy - 1) - dow + 3
if iso_week >= 0:
iso_week = iso_week // 7 + 1
# verify
if iso_week < 0:
if (iso_week > -2) or (iso_week == -2 and is_leapyear(year - 1)):
iso_week = 53
else:
iso_week = 52
elif iso_week == 53:
if 31 - day + dow < 3:
iso_week = 1
I need to alternate between 2 tasks every day, and I need a simple algorithm to know which task I need to do.
I need to be able to run this algorithm by head, using simple general knowledge (like day of week, day of month, etc), and it must not rely of which task has been done the previous day (because I have a crappy memory).
I have tried checking for parity in a combination of day of week / day of month / # of month, etc, but couldn't find a suitable system: day of week have 2 consecutive odd numbers, same goes for day of month every so often.
I am afraid that this is impossible: if you can't remember what you did the day before, any other procedure will require more mnemonic effort.
remember what you did on January first (or another date),
remember the parities of the cumulated months: oeoeoeooeoe or ooeoeoeeoeo for a leap year,
add the cumulated parity of the month before* to the parity of the day,
add that to the parity of the first task.
E.g. if A on January 1st 2022, then on March 17, 2022: e + o = o gives B.
*In January, use even.
You can also state the month parity rule as: until August inclusive, use the co-parity of the month number; then use the parity. But for a leap year, change that parity after February (excluded).
I need to be able to run this algorithm by head
So, you don't need to take help of Computer science. You can use cognitive human ability to map a thing to another thing.
Note: This need not make sense to everybody though, if you are thinking out of the box.
Map task 1 as God's day.
Map task 2 as Devil's day in your brain.
This should be simple just like day and night.
Now, remember that devil's evil karma is always burnt by God the next day and that devil never learns his lesson. So this way, alternating would be easy.
Friends Episode snippet on Youtube
Just count the number of days in between your date and a given "zero" one...then use parity.
Take number of seconds (or milli, or whatever) since EPOCH (common zero for date and time), divide (integer division) by 60x60x24 (or 1000x60x60x24, or what is appropriate), you then get the number of days since EPOCH.
----EDIT----
Example: Got 1653910695 seconds since EPOCH (at the time of my experience). Dividing it by 60x60x24 give 19142 days. To morrow it will give 19143, etc.
<?php
$day = Date('j');
$previous_day = date('j', strtotime("-1 days"));
if($day%2==0 OR $previous_day%2!=0)
echo "Task 1";
}else{
echo "Task 2";
}
?>
Given an arbitrary number of seconds, how can I get the number of years, months, days, hours and mins?
The algorithm should first compute the maximum number of years, then the number of months and so on...
What is an efficient way to do this?
It's mostly down to plain division. As you may know...
A minute has 60 seconds:
number_of_minutes := floor(number_of_seconds / 60)
An hour has 60 minutes:
number_of_hours := floor(number_of_minutes / 60) or
number_of_hours := floor(number_of_seconds / (60 * 60))
A day has 24 hours (at least usually... see below.)
A month has anything between 28 to 31 days.
A year has 365 or 366 days, or 365.2425 days on average.
The last two I mentioned may require you to think more about the stated problem. Either you define an "average" month, which then allows you to say "x seconds equal y average months"; or you don't convert your seconds to months at all.
(Thinking about it, if you were talking to an astronomer or alike, they would probably tell you that a day is not always exactly 24 hours, due to the occasional leap second.)
From this online calculator: http://homer.freeshell.org/dd.cgi using its data I've successfully written a working version, however its data is limited to years 1500 to 2600. I want to modify (and make a better one) so that I can calculate for any year > 2600.
Referring to Table X, is there actually a formula to calculate the base doomsday for all base centuries (above 2600)?
I've tried working it out myself by putting centuries higher than this e.g. 2700 gave me a base doomsday of '00', 2800 gave '02;, 2900 back to '00' again...
Help appreciated.
As I understand it, that page's “Base Doomsday” is just an offset to allow for the four-hundred-year cycle of leap day calculations. So, you can extend it indefinitely into the future simply by adding blocks of four centuries.
Are there any other calculators out there that do this?
Two common methods for calculating the day of the week
given a date are Doomsday, which you are using,
and Zeller's Congruence
www.merlyn.demon.co.uk provides
some really interesting information on date/time calculations, various calendar
systems and significant dates as they relate to calendar/date calculations.
The calculator at this link http://homer.freeshell.org/dd.cgi is the best in terms of explaining doomsday algorithm cleanly and clearly for human, with one little caveat.
If you input 2/29/1900, it would say it's a Thursday. Well, there is no 2/29/1900, because it's not a leap year.
Of course if your input 1/35/2016, it would "garbage-in-garbage-out" for you as well.
Imagine there are only 364 days in a year, then the day of week for each date will never change year after year, because mod(364,7)==0.
But we have 365 days a year, so the day steps forward 1 each year, that's where the second term mod(year, 7) comes from.
In addition, every 4 year, there is a leap year, which contributes to the last term mod(year, 4).
But every 100 years, you subtract a leap year, and every 400 years, you add one leap year. That's where the first term "3,2,0,5" comes in.
You see, it's all because of this leap year, and mod(365,7)==1 business.
7/11, 5to9 helps to remember table Z greatly.