คำนวณวันอีสเตอร์


13

ฟังก์ชั่นหรือโปรแกรมของคุณควรใช้เวลาเป็นปีในการป้อนและส่งคืน (หรือพิมพ์) วันที่ (ในปฏิทินเกรโกเรียน) ของปีที่ผ่านมาอีสเตอร์ (ไม่ใช่อีสเตอร์ออร์โธดอกซ์ตะวันออก) วันที่ที่ส่งคืนควรจัดรูปแบบตามมาตรฐาน ISO 8601 แต่ด้วยการรองรับปีที่มากกว่า 9999 (เช่น312013-04-05หรือ20010130 ) และต้องทำงานกับปีที่มากกว่าหรือเท่ากับ1583 เท่านั้น (ปี การยอมรับปฏิทิน Gregorian) และปีน้อยกว่าหรือเท่ากับ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

การใช้ฟังก์ชั่นในตัวสำหรับคืนวันอีสเตอร์นั้นน่าเบื่อและไม่อนุญาต คำตอบที่สั้นที่สุด (เป็นตัวอักษร) ชนะ

แหล่งข้อมูล:


คุณรู้ไหมว่าบางภาษามีฟังก์ชั่นในตัวเพื่อทำสิ่งนี้?
Peter Taylor

เช่น? สิ่งเดียวที่ฉันรู้คือ PHP แต่ฟังก์ชั่น easter_date และ easter_days ค่อนข้าง จำกัด easter_date ใช้งานได้หลายปีหลังจากปี 1970 และ easter_days ไม่คืนจำนวนวันที่ถูกต้องสำหรับปีก่อนปี 1753 แต่ฉันจะแก้ไขคำถาม เพื่อไม่อนุญาตให้ใช้งานฟังก์ชั่นดังกล่าว
Fors

1
แหล่งข้อมูล: en.wikipedia.org/wiki/Computus#Algorithms
John Dvorak

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

โปรดทราบว่านี่ใช้อัลกอริทึมที่แตกต่างกับคำตอบปัจจุบันส่วนใหญ่ โดยเฉพาะอย่างยิ่งฉันได้ปรับอัลกอริทึมที่มาจาก Lichtenberg ในทรัพยากรที่เชื่อมโยงโดยSean Cheshireในความคิดเห็นเกี่ยวกับคำถาม

อัลกอริธึมดั้งเดิมสมมติประเภทที่เหมาะสม (เช่นไม่ใช่ตัวเลขของ 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

วิธีนี้มีการคำนวณทางคณิตศาสตร์เล็กน้อยกว่าวิธีอื่น ๆ (อัลกอริทึม 20-op ของ Al Petrofsky) แต่มีค่าคงที่ขนาดเล็กกว่า GolfScript ไม่จำเป็นต้องกังวลเกี่ยวกับวงเล็บพิเศษเนื่องจากเป็นแบบสแต็กและเนื่องจากค่ากลางแต่ละค่าในเลย์เอาต์ที่ดีที่สุดของฉันถูกใช้อย่างแม่นยำสองครั้งจึงเหมาะอย่างยิ่งกับข้อ จำกัด ของ GolfScript ในการเข้าถึงรายการสามอันดับแรกบนสแต็ค


มันมีปัญหาเล็กน้อยเมื่อวันที่อีสเตอร์ตั้งอยู่ระหว่างวันที่ 1 เมษายนและวันที่ 10 เมษายนมันจะส่งคืนวันที่เช่น 1725041 เมื่อมันควรกลับ 17250401 แต่ upvoted สำหรับแนวทางที่แตกต่างกัน!
Fors

@ สำหรับโอ๊ะโอ แก้ไขแล้ว
Peter Taylor

5

Python 2 - 125 120 119 ตัวอักษร

นี่คือคำตอบของ Fors ที่ส่งต่อไปยัง Python อย่างไร้ยางอาย

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เป็นแต่ที่จะผลิตลอยจุดทั้งนี้การเรียกไปยัง1e4int

แก้ไข 2 : ขอบคุณ Peter Taylor ที่แสดงวิธีกำจัด10000และบันทึก 1 ตัวอักษร


1
ถ้าคุณแยก10000ขึ้นไปคุณสามารถใส่บรรทัดสุดท้ายในรูปแบบฮอร์เนอร์เป็น100*100 (y*100+b/31)*100+b%31+1วงเล็บนำหน้าช่วยให้คุณสามารถลบช่องว่างหลังจากprintนั้นและคุณสามารถดึงอินสแตนซ์ทั้งสามของ100ไปยังตัวแปรเพื่อการประหยัดโดยรวมของ 1 อักขระ
Peter Taylor

@PeterTaylor: คำแนะนำที่ดีเยี่ยม อัปเดตคำตอบของฉัน
Steven Rumbalski

คุณสามารถทำให้มันเป็นฟังก์ชั่นe(y)และบันทึกไม่กี่ไบต์
sagiksp

4

PHP 154

150ตัวอักษรถ้าฉันเปลี่ยนเป็น YYYYMMDD แทน YYYY-MM-DD

<?$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";

Useage: php easter.php 1997
เอาท์พุท:1997-03-30

Useage: 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;
ติตัส

ไม่สามารถจัดรูปแบบผลลัพธ์ได้ ศูนย์นำหน้าสำหรับวันนั้นหายไปเมื่อจำเป็น เช่นในปี 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

Javascript 162 156 145 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))}

แรงบันดาลใจจากโซลูชัน PHP ของ @ jdstankosky ... ให้ผลลัพธ์ 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

อัลกอริทึมนี้คำนวณจำนวนวันที่อีสเตอร์อยู่เมื่อเทียบกับต้นเดือนมีนาคม วันที่ส่งคืนในรูปแบบ 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

Fortran (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รูปแบบโดยมีช่องว่างนำหน้าถ้าปีนั้นมีตัวเลขน้อยกว่าเจ็ดหลัก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.