Calcule la fecha de Pascua

13

Su función o programa debe tomar un año como entrada y devolver (o imprimir) la fecha (en el calendario gregoriano) de la Pascua de ese año (no la Pascua ortodoxa oriental). La fecha de devolución debe estar formateada de acuerdo con ISO 8601, pero con soporte para años superiores a 9999 (como 312013-04-05 o 20010130 ), y solo necesita trabajar con años mayores o iguales a 1583 (el año del adopción del calendario gregoriano), y años menores o iguales a 5701583 (ya que es cuando la secuencia de fechas de Pascua comienza a repetirse).

Ejemplos:

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

El uso de funciones integradas para devolver la fecha de pascua es aburrido y, por lo tanto, no está permitido. La respuesta más corta (en caracteres) gana.

Recursos:

Fors
fuente
¿Te das cuenta de que algunos idiomas tienen una función incorporada para hacer esto?
Peter Taylor
¿Como? El único que conozco es PHP, pero las funciones easter_date y easter_days son bastante limitadas, easter_date solo funciona durante años después de 1970 y easter_days no devuelve la cantidad correcta de días durante años anteriores a 1753. Pero editaré la pregunta para no permitir el uso de tales funciones.
Fors
1
Entonces, ¿este es gregoriano y NO juliano? Además, no soy católica, ¿cuál es la "tradición católica"?
jdstankosky
2
Más funciones
SeanC

Respuestas:

3

GolfScript (85 caracteres)

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

Uso de la muestra:

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

Tenga en cuenta que esto utiliza un algoritmo diferente a la mayoría de las respuestas actuales. Para ser específicos, he adaptado el algoritmo atribuido a Lichtenberg en el recurso vinculado por Sean Cheshire en un comentario sobre la pregunta.

El algoritmo original, suponiendo tipos sensibles (es decir, no los números de JavaScript) y con una adaptación para dar mes * 31 + día (usando el desplazamiento de día de 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

Extraje una subexpresión común e hice algunas otras optimizaciones para reducir a

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

Este enfoque tiene un poco más de operaciones aritméticas que el otro (algoritmo de 20 operaciones de Al Petrofsky), pero tiene constantes más pequeñas; GolfScript no necesita preocuparse por los paréntesis adicionales porque está basado en la pila, y dado que cada valor intermedio en mi diseño optimizado se usa con precisión dos veces, encaja perfectamente con la limitación de GolfScript de acceso fácil a los tres elementos principales de la pila.

Peter Taylor
fuente
Tiene un pequeño problema, cuando la fecha de Pascua es entre el 1 de abril y el 10 de abril, devuelve fechas como 1725041, cuando debería devolver 17250401. ¡Pero votó por el enfoque diferente!
Fors
@ For, Uy. Ahora arreglado.
Peter Taylor
5

Python 2 - 125 120 119 caracteres

Esta es la respuesta de Fors descaradamente portada a 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

Editar : se modificó la última línea print"%d-0%d-%02d"%(y,b/31,b%31+1)para guardar 5 caracteres. Me hubiera encantado representar 10000como 1e4, pero eso produciría un punto flotante que requeriría una llamada int.

Edit2 : Gracias a Peter Taylor por mostrar cómo deshacerse de eso 10000y guardar 1 personaje.

Steven Rumbalski
fuente
1
Si se divide 10000hasta 100*100que puede poner la última línea en forma de Horner como (y*100+b/31)*100+b%31+1. El paréntesis inicial le permite eliminar el espacio después print, y puede extraer las tres instancias de 100una variable para un ahorro general de 1 carácter.
Peter Taylor
@PeterTaylor: Excelente sugerencia. Actualicé mi respuesta.
Steven Rumbalski
Puede convertirlo en una función e(y)y guardar algunos bytes
sagiksp
4

PHP 154

150 caracteres si cambio a AAAAMMDD en lugar de AAAA-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";

Con saltos de línea:

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

Uso: php easter.php 1997
Salida:1997-03-30

Uso: php easter.php 2001
Salida:2001-04-15

jdstankosky
fuente
1
Gran algoritmo de golf, no tan buen código de golf. Me tomé la libertad de cortar 18 bytes:<?=$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
No cumple con el formato de salida. Falta el cero inicial del día donde sea necesario. Por ejemplo, para el año 1725 sale en 1725-04-1lugar de 1725-04-01.
Christoph
4

dc: 106 caracteres

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

Uso:

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

Esto debería poder acortarse usando 'd' y 'r' en lugar de todas las cargas y almacenes.

Fors
fuente
3

C: 151148 caracteres

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

Y el mismo código, pero mejor formateado:

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

Hay terriblemente muchos algoritmos para calcular la fecha de Pascua, pero solo unos pocos son adecuados para el golf de código.

Fors
fuente
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))}

Inspirado en la solución PHP de @ jdstankosky ... Proporciona el resultado AAAAMMDD ...

Ahora reducido a:

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

Ahora pide entradas ... ¡redujo la cadena literal de "0" a 0 y dejé que la escritura suelta funcione a mi favor! :)

Reducido aún más para tener en cuenta 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
fuente
2

APL 132

Este algoritmo calcula el número de días de Pascua en relación con el comienzo de marzo. La fecha se devuelve en el formato AAAAMMDD según lo permitido en la pregunta:

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] 

Tomando los casos de prueba originales:

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

Fortran (GFortran) , 179 bytes

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

Pruébalo en línea!

Utiliza el algoritmo de "Pascua Gregoriana Enmendada" (Al Petrofsky) del segundo enlace de recursos. Curiosamente, falla para el año 5701583 (y, aparentemente, solo para este año), prediciendo la Pascua como una semana antes. Imprime la fecha en YYYYYYYMMDDformato, con algunos espacios iniciales si el año tiene menos de siete dígitos.

rafa11111
fuente