Hitung tanggal Paskah

13

Fungsi atau program Anda harus mengambil satu tahun sebagai input dan mengembalikan (atau mencetak) tanggal (dalam kalender Gregorian) tahun Paskah itu (bukan Paskah Ortodoks Timur). Tanggal yang dikembalikan harus diformat sesuai dengan ISO 8601, tetapi dengan dukungan untuk tahun yang lebih besar dari 9999 (seperti 312013-04-05 atau 20010130 ), dan hanya perlu bekerja dengan tahun yang lebih besar atau sama dengan 1583 (tahun adopsi kalender Gregorian), dan tahun-tahun kurang dari atau sama dengan 5701583 (seperti saat urutan tanggal Paskah mulai terulang).

Contoh:

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

Penggunaan fungsi bawaan untuk mengembalikan tanggal paskah membosankan dan karenanya dilarang. Jawaban terpendek (dalam karakter) menang.

Sumber:

Untuk S
sumber
Apakah Anda menyadari bahwa beberapa bahasa memiliki fungsi bawaan untuk melakukan ini?
Peter Taylor
Seperti? Satu-satunya yang saya ketahui adalah PHP, tetapi fungsi easter_date dan easter_days sangat terbatas, easter_date hanya berfungsi selama bertahun-tahun setelah tahun 1970 dan easter_days tidak mengembalikan jumlah hari yang benar untuk tahun sebelum 1753. Tetapi saya akan mengedit pertanyaan untuk melarang penggunaan fungsi tersebut.
Fors
1
sumber daya: en.wikipedia.org/wiki/Computus#Algorithms
John Dvorak
1
Jadi ini Gregorian dan BUKAN Julian? Juga, saya bukan Katolik, apa "Tradisi Katolik?"
jdstankosky
2
Fungsi lainnya
SeanC

Jawaban:

3

GolfScript (85 karakter)

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

Penggunaan sampel:

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

Perhatikan bahwa ini menggunakan algoritma berbeda untuk sebagian besar jawaban saat ini. Untuk lebih spesifik, saya telah mengadaptasi algoritma yang dikaitkan dengan Lichtenberg di sumber daya yang dihubungkan oleh Sean Cheshire dalam komentar pada pertanyaan.

Algoritma asli, dengan asumsi jenis yang masuk akal (yaitu bukan angka JavaScript) dan dengan adaptasi untuk memberikan bulan * 31 + hari (menggunakan day offset 0) adalah

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

Saya mengekstraksi subekspresi umum dan melakukan beberapa optimasi lain untuk mengurangi

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

Pendekatan ini memiliki operasi aritmatika sedikit lebih dari yang lain (algoritma Al-Petrofsky 20-op), tetapi memiliki konstanta yang lebih kecil; GolfScript tidak perlu khawatir dengan tanda kurung tambahan karena itu berbasis tumpukan, dan karena setiap nilai menengah dalam tata letak yang dioptimalkan digunakan tepat dua kali, ini cocok dengan batasan GolfScript untuk akses mudah ke tiga item teratas di tumpukan.

Peter Taylor
sumber
Ini memiliki masalah kecil, ketika tanggal Paskah terletak antara tanggal 1 April dan 10 April, ia mengembalikan tanggal seperti 1725041, ketika itu harus mengembalikan 17250401. Tetapi dipilih untuk pendekatan yang berbeda!
Fors
@Fors, oops. Sekarang sudah diperbaiki.
Peter Taylor
5

Python 2 - 125 120 119 karakter

Ini adalah jawaban Fors tanpa malu-malu porting ke 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

Sunting : Mengubah baris terakhir dari print"%d-0%d-%02d"%(y,b/31,b%31+1)untuk menyimpan 5 karakter. Aku akan senang untuk mewakili 10000sebagai 1e4, tapi itu akan menghasilkan floating point memerlukan panggilan ke int.

Sunting2 : Terima kasih kepada Peter Taylor untuk menunjukkan cara menyingkirkan itu 10000dan menyimpan 1 karakter.

Steven Rumbalski
sumber
1
Jika Anda memisahkan 10000hingga 100*100Anda dapat menempatkan baris terakhir dalam bentuk Horner sebagai (y*100+b/31)*100+b%31+1. Tanda kurung utama memungkinkan Anda untuk menghapus spasi setelahnya print, dan Anda bisa menarik tiga contoh dari 100ke variabel untuk penghematan keseluruhan 1 char.
Peter Taylor
@PeterTaylor: Saran yang bagus. Memperbarui jawaban saya.
Steven Rumbalski
Anda dapat menjadikannya fungsi e(y)dan menyimpan beberapa byte
sagiksp
4

PHP 154

150 karakter jika saya beralih ke YYYYMMDD bukan 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";

Dengan Line Breaks:

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

Penggunaan: php easter.php 1997
Output:1997-03-30

Penggunaan: php easter.php 2001
Output:2001-04-15

jdstankosky
sumber
1
Golf algoritma hebat, kode golf tidak begitu hebat. Saya mengambil kebebasan untuk memotong 18 byte:<?=$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
Gagal memenuhi format output. Angka nol di awal untuk hari ini tidak ada di tempat yang diperlukan. Misalnya untuk tahun 1725 itu menghasilkan 1725-04-1bukan 1725-04-01.
Christoph
4

dc: 106 karakter

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

Pemakaian:

> 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
>

Ini harus dapat dipersingkat dengan menggunakan 'd' dan 'r' alih-alih semua beban dan toko.

Untuk S
sumber
3

C: 151 148 karakter

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);}

Dan kode yang sama, tetapi lebih baik diformat:

#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);
}

Ada banyak algoritma yang menakutkan untuk menghitung tanggal Paskah, tetapi hanya beberapa yang cocok untuk kode golf.

Untuk S
sumber
3

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

Terinspirasi oleh solusi PHP @ jdstankosky ... Memberikan hasil YYYYMMDD ...

Sekarang dipersempit menjadi:

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))

Sekarang minta input ... string string "0" menjadi berkurang dan biarkan pengetikan yang longgar menguntungkan saya! :)

Dikurangi lebih jauh untuk memperhitungkan 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)

WallyWest
sumber
2

APL 132

Algoritma ini menghitung jumlah hari Paskah terletak relatif terhadap awal Maret. Tanggal dikembalikan dalam format YYYYMMDD sebagaimana diizinkan dalam pertanyaan:

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] 

Mengambil kasus uji asli:

      E 2013
20130331
      E 1583
15830410
      E 3029
30290322
      E 1789
17890412         
Graham
sumber
0

Fortran (GFortran) , 179 byte

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

Cobalah online!

Menggunakan algoritma "Emended Gregorian Easter" (Al Petrofsky) dari tautan sumber daya kedua. Anehnya, itu gagal untuk tahun 5701583 (dan, tampaknya, hanya untuk tahun ini), memprediksi Paskah satu minggu sebelumnya. Mencetak tanggal dalam YYYYYYYMMDDformat, dengan beberapa spasi terkemuka jika tahun memiliki kurang dari tujuh digit.

rafa11111
sumber