Python, 221 217
def d(x):
q=x%10
if x%2==0:
p,r=q/2,"06-30"
else:
p,r=(q-1)/2,"12-31"
return"%d%d-%s 23:59:60"%(p+197,x/10,r)
for x in [20,21,31,41,51,61,71,81,91,12,22,32,52,73,93,5,24,34,44,55,74,85,57,87,28,58]:print(d(x))
Some Insights
Basically, d(x)
decompresses a vector of 3 integers from a single 2-digit integer. d(x)
is constructed as the inverse function (over the 26 leap seconds datetimes) of c(v)
, which in turn is a compression function that turns a 3-uple such as (1998,12,31) into a number like 85. To derive the list [20,21...28,58] I designed another algorithm to verify that the compression function is bijective over the domain. That is, I made sure that the following program doesn't produce duplicates, and I used its output as the list of the program above.
dates = [(1972,06,30),
(1972,12,31),
(1973,12,31),
(1974,12,31),
(1975,12,31),
(1976,12,31),
(1977,12,31),
(1978,12,31),
(1979,12,31),
(1981,06,30),
(1982,06,30),
(1983,06,30),
(1985,06,30),
(1987,12,31),
(1989,12,31),
(1990,12,31),
(1992,06,30),
(1993,06,30),
(1994,06,30),
(1995,12,31),
(1997,06,30),
(1998,12,31),
(2005,12,31),
(2008,12,31),
(2012,06,30),
(2015,06,30)]
def c(v):
x = (v[0] % 10) * 10
x += v[2] % 30
x += 2 * (int(v[0] / 10) - 197)
return x
for v in dates:
print(c(v))
The compression function c(v)
was designed to be bijective by using a very simple scheme. Let's take as an example (1998,12,31).
- The expression (v[0] % 10) * 10 selects the units of the year (e.g. 1 9 9 8 --> 8) and makes it the tenths digit of the output (now x=80).
- There are only two month-day combination in which the leap second thing happens, so I decided to use the day component to distinguish between the 06,30 case and the 12,31 case. The expression v[2] % 30 is 0 if the day is 30, and is 1 if the day is 31. In our example, we add 1 to x (hence, now x=81).
- Finally, I observed that this puzzle involves only 5 decades; hence if I map the first decade (the seventies) to 0 and the last decade (the 2010s) to 4 I can do cool stuff. More specifically, if instead of mapping to 0,1,2,3,4 I map to 0,2,4,6,8 I can add this value to the units of x, which due to the previous rule is either 0 or 1. So in the end we have that also this last step doesn't screw the bijection, and we get that the units of a 06,30 case are one of 0,2,4,6,8 and that the units of a 12,31 case are one of 1,3,5,7,9. Hence the bijection is obvious. In our example, 1998 is in the third decade (70s->0, 80s->1, 90s->2) so we add 2*2=4. So we get x=85.
I wrote the program to verify that this is true, and then I defined d(x)
as the inverse of c(v)
. In our example, c((1998,12,31)) is 85 and d(85) correctly prints 1998-12-31 23:59:60
.