イースターの日付を計算する


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年以降のみ機能し、1753年より前のeaster_daysは正しい日数を返しません。しかし、質問を編集しますそのような機能の使用を禁止します。
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

これは、現在の回答のほとんどとは異なるアルゴリズムを使用していることに注意してください。具体的には、質問に対するコメントでショーン・チェシャーがリンクしているリソースの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はスタックベースであるため、余分なかっこを心配する必要はありません。最適化されたレイアウトの各中間値は正確に2回使用されるため、スタックの上位3つのアイテムへの簡単なアクセスというGolfScriptの制限にうまく適合します。


イースターの日付が4月1日から4月10日の間にある場合、小さな問題があり、17250401を返すはずの1725041などの日付を返します。しかし、別のアプローチに賛成です!
Fors

@Fors、おっと。修正されました。
ピーターテイラー

5

パイソン2 - 125の 120 119文字

これは、Pythonに恥知らずに移植された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:ピーターテイラーにそれを取り除き、100001キャラクターを保存する方法を示してくれてありがとう。


1
分割10000する場合100*100、最後の行をとしてホーナーの形式に入れることができます(y*100+b/31)*100+b%31+1。先頭の括弧を使用すると、の後のスペースを削除できます。また、変数にprint3つのインスタンスを引き出して、100全体で1文字節約できます。
ピーターテイラー

@PeterTaylor:素晴らしい提案。私の答えを更新しました。
スティーブンランバルスキー

あなたはそれ機能することができます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;
タイタス

出力形式に適合しません。必要に応じて、その日の先頭のゼロが欠落しています。たとえば、1725年の場合はの1725-04-1代わりに出力されます1725-04-01
クリストフ

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

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

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

オンラインでお試しください!

2番目のリソースリンクの「Emended Gregorian Easter」アルゴリズム(Al Petrofsky)を使用します。奇妙なことに、5701583年(および、明らかに今年のみ)に失敗し、イースターが1週間前であると予測しています。YYYYYYYMMDD年が7桁未満の場合、先頭にスペースを付けて形式で日付を出力します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.