Питон, 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))
Некоторые идеи
По сути, d(x)
распаковывает вектор из 3 целых чисел из одного двузначного целого числа. d(x)
построен как обратная функция (в течение 26 секунд високосных секунд) c(v)
, которая, в свою очередь, представляет собой функцию сжатия, которая превращает 3-х ряд, такой как (1998, 12, 31), в число, подобное 85. Для получения списка [20 , 21 ... 28,58] Я разработал другой алгоритм, чтобы убедиться, что функция сжатия является биективной по области. То есть я убедился, что следующая программа не производит дубликаты, и использовал ее вывод в качестве списка программы выше.
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))
Функция сжатия c(v)
была разработана, чтобы быть биективной, используя очень простую схему. Давайте возьмем в качестве примера (1998,12,31).
- Выражение (v [0]% 10) * 10 выбирает единицы года (например, 1 9 9 8 -> 8) и делает его десятой цифрой выходного значения (теперь x = 80).
- Есть только две комбинации месяца и дня, в которых происходит високосная секунда, поэтому я решил использовать компонент дня, чтобы различать случай 06,30 и случай 12,31. Выражение v [2]% 30 равно 0, если день 30, и 1, если день 31. В нашем примере мы добавляем 1 к x (следовательно, теперь x = 81).
- Наконец, я заметил, что эта головоломка включает только 5 десятилетий; следовательно, если я сопоставлю первое десятилетие (семидесятые) с 0, а последнее десятилетие (2010-е) с 4, я смогу делать классные вещи. Более конкретно, если вместо сопоставления с 0,1,2,3,4 я отображаю на 0,2,4,6,8, я могу добавить это значение к единицам x, что в силу предыдущего правила равно либо 0, либо 1. Итак, в конце мы имеем, что и этот последний шаг не нарушает биекцию, и мы получаем, что единицы измерения в случае 06,30 равны 0,2,4,6,8, а единицы измерения 12,31 дела - это одно из 1,3,5,7,9. Следовательно, биекция очевидна. В нашем примере 1998 год находится в третьем десятилетии (70-е годы -> 0, 80-е годы -> 1, 90-е годы -> 2), поэтому мы добавляем 2 * 2 = 4. Таким образом, мы получаем х = 85.
Я написал программу, чтобы убедиться, что это правда, а затем я определил d(x)
как обратное c(v)
. В нашем примере c ((1998,12,31)) равно 85, а d (85) печатается правильно 1998-12-31 23:59:60
.