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))
Algumas idéias
Basicamente, d(x)descomprime um vetor de 3 números inteiros a partir de um único número inteiro de 2 dígitos. d(x)é construída como a função inversa (ao longo dos 26 segundos bissextos às vezes) de c(v), que por sua vez é uma função de compressão que transforma um triplo como (1998,12,31) em um número como 85. Para derivar a lista [20 , 21 ... 28,58] Eu projetei outro algoritmo para verificar se a função de compressão é bijetiva sobre o domínio. Ou seja, assegurei-me de que o programa a seguir não produz duplicatas e usei sua saída como a lista do programa acima.
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))
A função de compactação c(v)foi projetada para ser bijetiva usando um esquema muito simples. Vamos tomar como exemplo (1998, 12, 31).
- A expressão (v [0]% 10) * 10 seleciona as unidades do ano (por exemplo, 1 9 9 8 -> 8) e o torna o décimo dígito da saída (agora x = 80).
- Há apenas uma combinação de dois meses / dia em que o segundo salto ocorre, então eu decidi usar o componente day para distinguir entre o caso 06,30 e o caso 12,31. A expressão v [2]% 30 é 0 se o dia for 30 e é 1 se o dia for 31. No nosso exemplo, adicionamos 1 a x (portanto, agora x = 81).
- Por fim, observei que esse quebra-cabeça envolve apenas 5 décadas; portanto, se eu mapear a primeira década (os anos setenta) para 0 e a última década (os anos 2010) para 4, eu posso fazer coisas legais. Mais especificamente, se em vez de mapear para 0,1,2,3,4 eu mapear para 0,2,4,6,8 eu posso adicionar esse valor às unidades de x, que devido à regra anterior é 0 ou 1. Então, no final, temos que também este último passo não estraga a bijeção, e entendemos que as unidades de uma caixa 06,30 são uma de 0,2,4,6,8 e que as unidades de uma 12,31 são um dos 1,3,5,7,9. Portanto, a bijeção é óbvia. Em nosso exemplo, 1998 está na terceira década (70s-> 0, 80s-> 1, 90s-> 2), então adicionamos 2 * 2 = 4. Então temos x = 85.
Eu escrevi o programa para verificar se isso é verdade e depois defini d(x)como o inverso de c(v). No nosso exemplo, c ((1998, 12, 31)) é 85 ed (85) é impresso corretamente 1998-12-31 23:59:60.