Calculez la date de Pâques

13

Votre fonction ou programme devrait prendre un an comme entrée et retourner (ou imprimer) la date (dans le calendrier grégorien) de cette année Pâques (pas la Pâques orthodoxe orientale). La date renvoyée doit être formatée selon ISO 8601, mais avec une prise en charge pour les années supérieures à 9999 (comme 312013-04-05 ou 20010130 ), et elle doit uniquement fonctionner avec des années supérieures ou égales à 1583 (l'année de la adoption du calendrier grégorien), et des années inférieures ou égales à 5701583 (car c'est à ce moment que la séquence des dates de Pâques commence à se répéter).

Exemples:

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

L'utilisation de fonctions intégrées pour renvoyer la date de Pâques est ennuyeuse et donc interdite. La réponse la plus courte (en caractères) l'emporte.

Ressources:

Fors
la source
Vous rendez-vous compte que certaines langues ont une fonction intégrée pour ce faire?
Peter Taylor
Tel que? Le seul que je connaisse est PHP, mais les fonctions easter_date et easter_days sont assez limitées, easter_date ne fonctionne que pendant des années après 1970 et easter_days ne renvoie pas le nombre correct de jours pour les années antérieures à 1753. Mais je vais modifier la question pour interdire l'utilisation de ces fonctions.
Fors
1
C'est donc grégorien et NON julien? De plus, je ne suis pas catholique, qu'est-ce que la "Tradition catholique"?
jdstankosky

Réponses:

3

GolfScript (85 caractères)

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

Exemple d'utilisation:

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

Notez que cela utilise un algorithme différent de la plupart des réponses actuelles. Pour être précis, j'ai adapté l'algorithme attribué à Lichtenberg dans la ressource liée par Sean Cheshire dans un commentaire sur la question.

L'algorithme d'origine, en supposant des types sensibles (c.-à-d. Pas les nombres de JavaScript) et avec une adaptation pour donner le mois * 31 + jour (en utilisant un décalage de jour de 0) est

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

J'ai extrait une sous-expression commune et fait quelques autres optimisations pour réduire à

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

Cette approche a des opérations arithmétiques légèrement plus nombreuses que l'autre (algorithme à 20 op d'Al Petrofsky), mais elle a des constantes plus petites; GolfScript n'a pas à se soucier des parenthèses supplémentaires car il est basé sur la pile, et puisque chaque valeur intermédiaire dans ma disposition optimisée est utilisée avec précision deux fois, elle correspond bien à la limitation de GolfScript d'un accès facile aux trois premiers éléments de la pile.

Peter Taylor
la source
Il a un petit problème, lorsque la date de Pâques se situe entre le 1er avril et le 10 avril, il renvoie des dates telles que 1725041, quand il devrait retourner 17250401. Mais voté pour l'approche différente!
Fors
@Fors, oups. Maintenant corrigé.
Peter Taylor
5

Python 2 - 125 120 119 caractères

C'est la réponse de Fors sans vergogne portée sur 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

Modifier : dernière ligne modifiée print"%d-0%d-%02d"%(y,b/31,b%31+1)pour enregistrer 5 caractères. J'aurais aimé représenter 10000as 1e4, mais cela produirait une virgule flottante nécessitant un appel à int.

Edit2 : Merci à Peter Taylor d'avoir montré comment s'en débarrasser 10000et sauver 1 personnage.

Steven Rumbalski
la source
1
Si vous vous séparez 10000, 100*100vous pouvez mettre la dernière ligne sous la forme de Horner en tant que (y*100+b/31)*100+b%31+1. La parenthèse de tête vous permet de supprimer l'espace après print, et vous pouvez extraire les trois instances de 100dans une variable pour une économie globale de 1 caractère.
Peter Taylor
@PeterTaylor: Excellente suggestion. Mis à jour ma réponse.
Steven Rumbalski
Vous pouvez en faire une fonction e(y)et économiser quelques octets
sagiksp
4

PHP 154

150 caractères si je passe à YYYYMMDD au lieu de 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";

Avec les sauts de ligne:

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

Utilisation: php easter.php 1997
Sortie:1997-03-30

Utilisation: php easter.php 2001
Sortie:2001-04-15

jdstankosky
la source
1
Grand algorithme de golf, pas si grand golf de code. J'ai pris la liberté de couper 18 octets:<?=$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
Ne répond pas au format de sortie. Le zéro de tête pour la journée est manquant là où c'est nécessaire. Par exemple, pour l'année 1725, il sort 1725-04-1au lieu de 1725-04-01.
Christoph
4

dc: 106 caractères

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

Usage:

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

Cela devrait pouvoir être raccourci en utilisant «d» et «r» au lieu de toutes les charges et tous les magasins.

Fors
la source
3

C: 151 148 caractères

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

Et le même code, mais mieux formaté:

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

Il existe affreusement de nombreux algorithmes pour calculer la date de Pâques, mais seuls quelques-uns sont bien adaptés au golf par code.

Fors
la source
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))}

Inspiré par la solution PHP de @ jdstankosky ... Fournit le résultat YYYYMMDD ...

Maintenant réduit à:

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

Demande maintenant une entrée ... chaîne littérale réduite de "0" à 0 et laissez le travail de frappe lâche à mon avantage! :)

Encore réduit pour prendre en compte 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
la source
2

APL 132

Cet algorithme calcule le nombre de jours de Pâques par rapport au début de mars. La date est retournée au format AAAAMMJJ comme autorisé dans la question:

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] 

Prendre les cas de test d'origine:

      E 2013
20130331
      E 1583
15830410
      E 3029
30290322
      E 1789
17890412         
Graham
la source
0

Fortran (GFortran) , 179 octets

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

Essayez-le en ligne!

Utilise l'algorithme "Pâques grégorienne modifiée" (Al Petrofsky) du deuxième lien de ressource. Étrangement, il échoue pour l'année 5701583 (et, apparemment, seulement pour cette année), prédisant la Pâques comme une semaine plus tôt. Imprime la date au YYYYYYYMMDDformat, avec quelques espaces en tête si l'année comporte moins de sept chiffres.

rafa11111
la source