부활절 날짜를 계산


13

귀하의 기능이나 프로그램은 1 년 동안 입력해야하며 부활절 (동방 정교회 부활절이 아님) 연도의 날짜 (그레고리력)로 반환 (또는 인쇄)해야합니다. 반환 된 날짜는 ISO 8601에 따라 형식이 지정되어야하지만 9999보다 큰 연도 (예 : 312013-04-05 또는 20010130 )를 지원해야하며 1583 (연도)의 연도 만 작동하면됩니다. 그레고리력을 채택), 5701583 이하의 연도 ( 이스터 데이 날짜 순서가 반복되기 시작하는 시점).

예 :

e(5701583) = 5701583-04-10
e(2013)    = 2013-03-31
e(1583)    = 1583-04-10
e(3029)    = 30290322
e(1789)    = 17890412
e(1725)    = 17250401

부활절 날짜를 반환하기 위해 내장 함수를 사용하는 것은 지루하므로 허용되지 않습니다. 최단 답변 (문자)이 이깁니다.

자원:


일부 언어에는이를위한 기능이 내장되어 있다는 것을 알고 있습니까?
피터 테일러

같은? 내가 아는 유일한 것은 PHP이지만 easter_date 및 easter_days 함수는 상당히 제한되어 있으며 easter_date는 1970 년 이후 몇 년 동안 만 작동하며 easter_days는 1753 년 이전 몇 년 동안 올바른 일수를 반환하지 않습니다. 그러나 질문을 편집하겠습니다. 그러한 기능의 사용을 금지합니다.
Fors


1
그래서 이것은 줄리안이 아니라 그레고리력입니까? 또한 저는 가톨릭이 아닙니다. "가톨릭 전통"이란 무엇입니까?
jdstankosky

답변:


3

GolfScript (85 자)

~:^100/.)3*4/.@8*13+25/-^19%.19*15+@+30%.@11/+29/23--.@-^.4/++7%97--^0@.31/100*\31%)+

샘플 사용법 :

$ golfscript.rb codegolf11132.gs <<<2013
20130331

이것은 대부분의 현재 답변에 다른 알고리즘을 사용합니다. 구체적으로, 나는 질문에 대한 의견에서 Sean Cheshire 와 연결된 리소스에서 Lichtenberg에 기여한 알고리즘을 조정했습니다 .

합리적인 유형 (예 : JavaScript의 숫자가 아님)을 가정하고 달 * 31 + 일 (일 오프셋 0 사용)을 제공하도록 적응 한 것으로 가정 한 원래 알고리즘은 다음과 같습니다.

K = Y/100
M = 15 + (3*K+3)/4 - (8*K+13)/25
S = 2 - (3*K+3)/4
A = Y%19
D = (19*A+M) % 30
R = (D + A/11)/29
OG = 21 + D - R
SZ = 7 - (Y + Y/4 + S) % 7
OE = 7 - (OG-SZ) % 7
return OG + OE + 92

공통 하위 표현식을 추출하고 다른 최적화를 수행하여

K = y/100
k = (3*K+3)/4
A = y%19
D = (19*A+15+k-(8*K+13)/25)%30
G = 23+D-(D+A/11)/29
return 97+G-(G+y+y/4-k)%7

이 방법은 다른 방법 (Al Petrofsky의 20-op 알고리즘)보다 약간 더 많은 산술 연산을 가지지 만 상수는 더 작습니다. GolfScript는 스택 기반이기 때문에 추가 괄호에 대해 걱정할 필요가 없으며 최적화 된 레이아웃의 각 중간 값이 정확하게 두 배로 사용되므로 GolfScript의 스택에서 상위 3 개 항목에 쉽게 액세스 할 수 없다는 제한에 잘 맞습니다.


부활절 날짜가 4 월 1 일과 4 월 10 일 사이에있을 때는 17250401과 같은 날짜를 반환하지만 17250401을 반환해야하는 작은 문제가 있습니다.
Fors

@ 포스, 죄송합니다. 이제 수정되었습니다.
피터 테일러

5

파이썬 2 - (125 개) 120 119 문자

이것은 뻔뻔스럽게 파이썬으로 포팅 된 Fors의 답변 입니다.

y=input()
a=y/100*1483-y/400*2225+2613
b=(y%19*3510+a/25*319)/330%29
b=148-b-(y*5/4+a-b)%7
print(y*100+b/31)*100+b%31+1

편집 : 마지막 줄에서 print"%d-0%d-%02d"%(y,b/31,b%31+1)5자를 저장하도록 변경되었습니다 . 나는로 표현 10000하고 1e4싶었지만 호출을 필요로하는 부동 소수점을 생성 할 것이다 int.

Edit2 : 그것을 제거 10000하고 1 문자를 저장 하는 방법을 보여 준 Peter Taylor에게 감사드립니다 .


1
당신이 분할하는 경우 10000까지 100*100당신과 같은 호너의 형태로 마지막 줄을 넣을 수 있습니다 (y*100+b/31)*100+b%31+1. 선행 괄호를 사용하면 뒤에 공백을 제거 print할 수 있으며 3 개의 인스턴스를 100변수로 가져와 1 자 전체를 절약 할 수 있습니다 .
피터 테일러

@PeterTaylor : 훌륭한 제안. 내 답변을 업데이트했습니다.
Steven Rumbalski

기능을 e(y)만들고 몇 바이트를 절약 할 수 있습니다
sagiksp

4

PHP 154

YYYY-MM-DD 대신 YYYYMMDD로 전환하면 150

<?$y=$argv[1];$a=$y/100|0;$b=$a>>2;$c=($y%19*351-~($b+$a*29.32+13.54)*31.9)/33%29|0;$d=56-$c-~($a-$b+$c-24-$y/.8)%7;echo$d>31?"$y-04-".($d-31):"$y-03-$d";

줄 바꿈으로 :

<?
$y = $argv[1];
$a = $y / 100 |0;
$b = $a >> 2;
$c = ($y % 19 * 351 - ~($b + $a * 29.32 + 13.54) * 31.9) / 33 % 29 |0;
$d = 56 - $c - ~($a - $b + $c - 24 - $y / .8) % 7;
echo $d > 31 ? "$y-04-".($d - 31) : "$y-03-$d";

사용법 : php easter.php 1997
출력 :1997-03-30

사용법 : php easter.php 2001
출력 :2001-04-15


1
훌륭한 코드 골프는 아니지만 훌륭한 알고리즘 골프. 18 바이트를 자르는 자유를 얻었습니다 :<?=$y=$argv[1],"-0",3+$m=($d=56-($c=($y%19*351-~(($a=$y/100|0)*29.32+($b=$a>>2)+13.54)*31.9)/33%29)-~($a-$b+$c-24-$y/.8)%7)>>5,31*$m-$d;
Titus

출력 형식을 충족하지 못합니다. 필요한 경우 하루의 선행 0이 누락되었습니다. 예를 들어 1725 년 동안이 1725-04-1대신에 출력 됩니다 1725-04-01.
Christoph

4

dc : 106 자

?[0n]smdndsy100/1483*ly400/2225*-2613+dsa25/319*ly19%3510*+330/29%sb148lb-5ly*4/la+lb-7%-d31/0nn31%1+d9>mp

용법:

> dc -e "?[0n]smdndsy100/1483*ly400/2225*-2613+dsa25/319*ly19%3510*+330/29%sb148lb-5ly*4/la+lb-7%-d31/0nn31%1+d9>mp"
1725
17250401
>

모든로드 및 저장 대신 'd'및 'r'을 사용하여 단축 할 수 있습니다.


3

C : 151 개 148 문자

y;a;b;main(){scanf("%d",&y);a=y/100*1483-y/400*2225+2613;b=(y%19*3510+a/25*319)/330%29;b=148-b-(y*5/4+a-b)%7;printf("%d-0%d-%02d\n",y,b/31,b%31+1);}

같은 코드이지만 형식이 더 좋습니다.

#include <stdio.h>

int y, a, b;

int main() {
    scanf("%d", &y);

    a = y/100*1483 - y/400*2225 + 2613;
    b = (y%19*3510 + a/25*319)/330%29;
    b = 148 - b - (y*5/4 + a - b)%7;

    printf("%d-0%d-%02d\n", y, b/31, b%31 + 1);
}

부활절 날짜를 계산하는 데에는 엄청나게 많은 알고리즘이 있지만 그중 몇 가지만이 코드 골프에 적합합니다.


3

자바 162 156 145

function e(y){alert(y+"0"+((d=56-(c=(y%19*351-~((b=(a=y/100|0)>>2)+a*29.32+13.54)*31.9)/33%29|0)-~(a-b+c-24-y/.8)%7)>(f=31)?4:3)+(d-f>0&d-f<10?0:"")+(d>f?d-f:d))}

@jdstankosky의 PHP 솔루션에서 영감을 얻은 ... YYYYMMDD 결과 제공 ...

이제 다음과 같이 좁혀졌습니다.

alert((y=prompt())+0+((d=56-(c=(y%19*351-~((b=(a=y/100|0)>>2)+a*29.32+13.54)*31.9)/33%29|0)-~(a-b+c-24-y/.8)%7)>(f=31)?4:3)+(d-f>0&d-f<10?0:"")+(d>f?d-f:d))

이제 입력을 요청합니다 ... 리터럴 문자열 "0"을 0으로 줄이고 느슨한 타이핑 작업을 유리하게 여깁니다! :)

ES6를 고려하여 추가 축소 ...

e=y=>y+"0"+((d=56-(c=(y%19*351-31.9*~((b=(a=y/100|0)>>2)+29.32*a+13.54))/33%29|0)-~(a-b+c-24-y/.8)%7)>(f=31)?4:3)+(d-f>0&d-f<10?0:"")+(d>f?d-f:d)


2

APL 132

이 알고리즘은 부활절이 3 월 초를 기준으로하는 일 수를 계산합니다. 질문에 허용 된대로 날짜는 YYYYMMDD 형식으로 반환됩니다.

E y                                                   
(a b)←⌊((3 8×⌊y÷100)+¯5 13)÷4 25                           
c←7|y+(⌊y÷4)-a-e←⌊d-((19×d←30|(227-(11×c)-a-b))+c←19|y)÷543
+/(10*4 2 0)×y,(3+i>31),(61⍴⍳31)[i←e+28-c] 

원래 테스트 사례를 수행 :

      E 2013
20130331
      E 1583
15830410
      E 3029
30290322
      E 1789
17890412         

0

포트란 (GFortran) , 179 바이트

READ*,I
J=I/100*2967-I/400*8875+7961
K=MOD(MOD(I,19)*6060+(MOD(MOD(J/25,59),30)+23)*319-1,9570)/330
L=K+28-MOD(I*5/4+J+K,7)
WRITE(*,'(I7,I0.2,I0.2)')I,(L-1)/31+3,MOD(L-1,31)+1
END

온라인으로 사용해보십시오!

두 번째 리소스 링크에서 "Emended Gregorian Easter"알고리즘 (Al Petrofsky)을 사용합니다. 이상하게도 부활절은 5701583 년 (그리고 올해 만)에 실패하여 부활절을 일주일 전으로 예측합니다. YYYYYYYMMDD연도가 7 자리 미만인 경우 일부 선행 공백과 함께 날짜를 형식으로 인쇄합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.