Time Algorithms
A time algorithm is an algorithm associated with parsing, manipulating, computing, and more generally working with, time formats. To begin, we'll start by presenting the two principle source of issues for time algorithms: (1) units of time, and (2) linguistic fence post problems.
Units of Time
Here is an overview of the various ways we can measure time:
Name | Length | Remark |
---|---|---|
nanosecond | 1 ns, 0.000 000 001 s | One billionth of a second |
microsecond | 1 Β΅s, 0.000 001 s | One millionth of a second |
millisecond | 1 ms, 0.001 s | One thousandth of a second |
jiffy | 1/60 s or 1/50 s | Used in electronics; also, "I'll be back in a jiffy" |
second | 1 s | SI base unit for time |
minute | 60 s | |
hour | 1 hr, 60 min, 120 s | |
day | 1 d, 24 hr, 1440 min, 86400 s | |
week | 1 w, 7 d, 168 hr, 10080 min, 604800 s | |
month | 1 mo, [28, 31] d | |
semester | 18 w | |
year | 1 yr, [365, 366] d | |
common year | 1 yr, 52 w, 365 d | |
leap year | 1 yr 1 d, 52 w + 2 d, 366 d | |
olympiad | 4 yr | |
lustrum | 5 yr | During the Roman empire, the interval between censuses |
decade | 10 yr | |
indiction | 15 yr | During the Roman empire, the interval between tax assessments |
jubilee | 50 yr | |
century | 100 yr | |
millennium | 1000 yr | |
megaannum | 1 Ma, 1000 millenia | 1 million years |
galactic year | 1 gy | The amount of time it takes the solar system to orbit the Milky Way Galaxy's center. Roughly 230 million years. |
The table above is just a subset of the units of time used by humans. This presents the first difficulty with handling time data: the sheer number of time units to consider. For a time algorithm to be correct, it work with time units correctly.
Linguistic Fence Posts
The second problem presented is th linguistic fence post. This problem stems from the way we use language. For example, when we say:
"π΄ is due within 2 days of ."
There are two possible meanings.
-
If we count as
meaning, π΄ is due on This is the day after
-
If, however, we don't count
meaning, π΄ is due on This is two days after $$
Moreover, depending on the context, we might have additional parameters: Do we count weekends? Do we count holidays? Is the day 24 hours or business days (8 hours)? The same problem exists when we say:
"π΄ is due in 2 days."
Suppose that we're told the above on date
-
If we count
meaning, π΄ is due on This is the day after
-
If we don't count
meaning, π΄ is due on This is two days after $$
Unfortunately, the only way to be absolutely certain of the intended meaning is through specification.
Wrap-around Counting
A common operation in time algorithms is modular arithmetic. Accordingly, it's imperative that we have a strong understanding of the operation.
First, modular arithmetic is a system of arithmetic for the integers. The arithmetic we're taught in elementary school is a system of arithmetic for the reals (or, at least a subset of the reals β it's unlikely that we're having children add gargantuan numbers). In real arithmetic, the result of an operation could be any real number: either 0, negative, or positive.
In modular arithmetic, the result of an operation will "wrap around" a certain value once it reaches a particular integer called the modulus. Let's illustrate with the classic example, the wall clock.
A wall clock displays 12 hours:
Let's say the current time is 8:00am. We'll mark at as x
.
3 hours later, we land at 11:
In another 3 hours, (11+3), we land at 2:
Thus, we have: This is what we mean by modular arithmetic. For the wall clock, the modulus is Moreover, we say that this is mod-12 arithmetic, or arithmetic mod-12: For all arithmetic operations, once a result's value hits its value starts back at the initial value.
Having seen the basic example, let's add a little more detail.
Week Day Determining
Consider the following problem:
problem. Today is Tuesday. What day will it be in 17 days?
Let's start by assigning each day of the week an index, starting at 0:
Here, the modulus is 7. If we viewed the diagram above as an array, this corresponds to the array's length:
To determine the weekday 17 days from Tuesday, we first determine Tuesday's index. Here, it's 2.
Then, we add the 17 days to 2:
Next, we divide this result by the modulus (the array's length) and obtain the remainder:
What does this tell us? It tells us that we've gone through 2 cycles plus 5
positions. That is, we've wrapped around the circulary array 2 timesputting
us at SU
, then 5 extra, which is FRI
.
Here's a simple implementation of a function for answering the problem using TypeScript:
type Weekday =
| 'Sunday' | 'Monday' | 'Tuesday' | 'Wednesday'
| 'Thursday' | 'Friday' | 'Saturday';
function WhichDay(currentDay: Weekday, days: number) {
const weekdays = [
'Sunday' , 'Monday' , 'Tuesday' , 'Wednesday',
'Thursday' , 'Friday' , 'Saturday' ,
];
const L = 7;
let DayIndex = 0;
switch (currentDay) {
case 'Monday' : DayIndex = 1; break;
case 'Tuesday' : DayIndex = 2; break;
case 'Wednesday' : DayIndex = 3; break;
case 'Thursday' : DayIndex = 4; break;
case 'Friday' : DayIndex = 5; break;
case 'Saturday' : DayIndex = 6; break;
default : throw new Error("Unrecognized weekday.");
}
const sum = DayIndex + days;
const index = sum % L;
return weekdays[index];
};
Examining this function, it should be apparent why the %
operator in
programming languages is so useful. The %
operator, in mathematical
terms, is the natural number remainder operation:
definition. Where and are natural numbers, the operation:
returns the remainder of
To truly under what this definition means, we delve briefly into Euclidean division.
Divisibility
Whenever we divide an integer by an integer we have two possible outcomes:
- can be divided into evenly (no remainder exists).
- cannot be divided into evenly (there exists a remainder).
In logic terms:
where is a remainder. For example, 4 can be divided into 2 evenly. 120 can be divided into 40 evenly. 2, however, cannot be divided into 3 evenly, nor can 3 be divided into 2 evenly.
Quotient
Euclidean division is a mathematical operation based on this idea. First, we introduce two operations:
quotient. Let and Then:
The quotient operation works as follows: First, suppose our friend Billy is a track and field star competing in a special circular track race. The track has a special property. It has numbered sections starting at 0 and ending at some natural number , the length of the track:
The race is won by whoever crosses the most times. Unfortunately, Billy has been running in other races and he's pretty tired. He tells us that he only has enough energy to cover total segments. The quotient tells us that, if Billy can run past segments, he can cross a total of times.
For example, suppose the track is segments long. If Billy only has enough energy to cover segments, then we have and Thus, starting at the segument numbered 0:
- Bill passes segment1. He has enough energy for 4 more segments.
- Billy passes segment2. He has enough energy for 3 more segments.
- Billy passes . He's crossed once. Now he only has enough energy for 2 more segments.
- Billy segment0. Only 1 more segment.
- Billy passes segment1. Bill collapses at segment2.
Billy only crossed once. The entire drama is expressed by writing:
Let's be clear that this is not division operation. This is the quotient operation. It is a different operation. In fact, it's so different that the word "quotient" in this context is a verb. When we compute the quotient of two integers and we quotientize and This is standard mathematical terminology in group theory.
To see why this verb is necessary, here is the definition of real number division:
division. Let where Then:
This is a very different definition from the previous. Real number division is an operation that can take real number inputs β that includes fractional numbers like 2.138 and irrational numbers like Quotient, however, is an operation that can only take integer inputs. It does not work for fractional numbers or irrational numbers. For example, compare the outputs for the following functions:
The functions and divide by a constant. The functions and quotientize by a constant.
Importantly, can be negative, but cannot. What does being negative mean? Well, it just means that Billy runs backwards along the track instead of forwards. When we write we're saying, if Billy has enough energy to cover 5 segments running backwards along the track, he completes runs along the track:
- Starts at segment0 (5 remaining).
- Billy runs backwards, and crosses . That's one cross.
- Past segment2. (3 remaining).
- Past segment1. (2 remaining).
- Past segment0. (1 remaining).
- Past Billy's crossed twice. 0 remaining.
- Billy collapses at segment1.
Remainder
The third operation we introduce is the remainder operation:
remainder. Let and Then:
Relying on our friend Billy once more, the remainder operation tells us which segment Billy stops at. Recall that the segments are all labeled with natural numbers. Thus, the remainder can never be negative. It's always either 0 or a positive number β a natural number.
A few words of caution. The remainder operator is also called the modulo operator, with some textbooks opting to use the notation From personal experience, this is a very bad idea. As we'll see later, this notation looks too similar to the modular arithmetic notation, and can very easily lead to confusion. Accordingly, we will not use this notation, nor will we call it the modulo operator. It's the remainder operator, written as
Next, many programming languages provide the operator as %
.
That is, is equivalent to It is not,
however, equivalent. Some programming languages will compute
rather than when
That is, they use the ceiling function for negatives. This is not inline
with the mathematical definition. Some languages even allow
when again, such a definition does not make much sense from a mathematical
standpoint. For the operation, is always positive.
Euclidean Division
At this point, we can now introduction Euclidean division:
euclidean division. Let and Then there exists two unique integers, and such that:
This proposition is also called the division algorithm. What are the numbers and ? Well, if we have an integer and positive integer and are given by:
The Euclidean algorithm introduces us to the notion of divisibility.
Divisibility
Divisibility is defined as follows:
divisibility. Let where If there exists a such that then we say that divides > and write:
Else, we say that does not divide and write:
Casting this definition in Euclidean division terms:
lemma. Let and divides iff:
Note the use of the absolute value. Remember that the remainder operator is defined only for Alternatively, we can also write:
Let and divides iff:
From the definition of divisibility, we have the notion of a multiple:
definition. Let Then is a multiple of iff
As well as the notion of a factor:
definition. Let Then is a factor of iff
There are several useful properties of divisibility to keep in mind:
properties. Let where Then:
- If:
- for any integer
- If:
- and
- If:
- and
Modular Arithmetic
Now that we have the basic constructs of divisibility, we can now examine a more formal treatment of modular arithmetic. First, we begin with a definition:
definition. Let and If:
then is congruent to modulo and we write:
Put differently:
Let and If there exists a such that:
then:
Or, alternatively:
Let and Iff:
then:
For example, from the definition above, we know that . Why? Because:
and is an integer.