파이썬, 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)
단일 2 자리 정수에서 3 개의 정수로 구성된 벡터를 압축 해제합니다. d(x)
의 역함수 (26 윤초 날짜 시간 이상)로 구성되며 c(v)
, 이는 (1998,12,31)과 같은 3 상을 85와 같은 숫자로 바꾸는 압축 함수입니다. , 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)
은 매우 간단한 체계를 사용하여 bijective하도록 설계되었습니다. 예를 들어 보자 (1998,12,31).
- 식 (v [0] % 10) * 10은 연도의 단위 (예 : 1 9 9 8- > 8)를 선택하여 출력의 10 번째 자릿수 (현재 x = 80)로 만듭니다.
- 윤초의 두 번째 일이 발생하는 두 달의 일 조합 만 있으므로 06,30 사례와 12,31 사례를 구별하기 위해 day 구성 요소를 사용하기로 결정했습니다. 일이 30이면 표현식 v [2] % 30은 0이고, 날이 31이면 1입니다.이 예에서는 1을 x에 추가합니다 (따라서 x = 81).
- 마지막으로이 퍼즐은 50 년에 불과하다는 것을 알았습니다. 따라서 처음 10 년 (70 년대)을 0으로, 마지막 10 년 (2010 년대)을 4로 매핑하면 멋진 일을 할 수 있습니다. 보다 구체적으로, 0,1,2,3,4에 매핑하는 대신 0,2,4,6,8에 매핑하는 경우이 값을 x의 단위에 추가 할 수 있습니다. 이전 규칙으로 인해 0 또는 1. 결국 우리는이 마지막 단계로도 bijection을 망칠 수 없으며, 06,30 케이스의 단위는 0,2,4,6,8 중 하나이고 a의 단위는 12,31 건은 1,3,5,7,9 건 중 하나입니다. 그러므로 그 회귀는 분명하다. 이 예에서 1998 년은 30 년 (70 년대-> 0, 80 년대-> 1, 90 년대-> 2)이므로 2 * 2 = 4를 더합니다. 따라서 우리는 x = 85를 얻습니다.
이것이 사실인지 확인하기 위해 프로그램을 작성한 다음 d(x)
의 역으로 정의 했습니다 c(v)
. 이 예에서 c ((1998,12,31))은 85이고 d (85)는 올바르게 인쇄합니다 1998-12-31 23:59:60
.