Обчисліть дату Великодня


13

Ваша функція або програма повинна зайняти рік, як введення та повернення (або надрукування) дати (за григоріанським календарем) великодніх років цих років (а не східної православної Пасхи). Повернуту дату слід відформатувати відповідно до 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 року. Але я відредагую питання заборонити використання таких функцій.
Форс


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

Зауважте, що для більшості поточних відповідей використовується інший алгоритм. Для конкретності я адаптував алгоритм, приписаний Ліхтенбергу, в ресурсі, пов'язаному Шоном Чеширом, у коментарі до питання.

Оригінальний алгоритм, припускаючи розумні типи (тобто не номери 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-оп), але він має менші константи; GolfScript не повинен турбуватися про додаткові дужки, оскільки він базується на стеках, і оскільки кожне проміжне значення в моєму оптимізованому макеті використовується точно вдвічі, воно добре відповідає обмеженню GolfScript у легкому доступі до перших трьох елементів на стеку.


У цьому є невелике питання, коли дата Великодня лежить між 1 квітня та 10 квітня, вона повертає такі дати, як 1725041, коли вона повинна повернути 17250401. Але прихильна до іншого підходу!
Форс

@ Форс, ой. Тепер виправлено.
Пітер Тейлор

5

Пітон 2 - 125 120 119 символів

Це відповідь Форса безсоромно перенесла на 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як 1e4, але це призвело б до плаваючої точки, яка потребує дзвінка int.

Edit2 : Дякую Пітеру Тейлору за те, що він показав, як позбутися цього 10000і зберегти 1 персонажа.


1
Якщо ви розлучитеся 10000, 100*100ви можете помістити останній рядок у форму Горнера як (y*100+b/31)*100+b%31+1. Провідні дужки дозволяють видалити пробіл після print, і ви можете витягнути три екземпляри 100змінної для загальної економії 1 знака.
Пітер Тейлор

@PeterTaylor: Відмінна пропозиція. Оновлено мою відповідь.
Стівен Румбальський

Ви можете зробити його функцією 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";

Використання: 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

С: 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))}

Натхненний 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

132 APL

Цей алгоритм обчислює кількість днів, що лежить на Великдень відносно початку березня. Дата повертається у форматі 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

Спробуйте в Інтернеті!

Використовує алгоритм "Рекомендований григоріанський Великдень" (Аль Петрофський) з другого ресурсного посилання. Як не дивно, він провалюється на 5701583 рік (і, мабуть, лише на цей рік), прогнозуючи Великдень як тиждень раніше. Друкує дату у YYYYYYYMMDDформаті з деякими провідними пробілами, якщо рік має менше семи цифр.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.