language agnostic - Código de golf: Calcular la fecha de Pascua ortodoxa
language-agnostic code-golf (14)
C, 128 121 98 caracteres
De vuelta al algoritmo de Meeus. Cálculo del día en Julian, pero ajuste para Gregorian (esto todavía me parece ingenuo, pero no puedo encontrar una alternativa más corta).
main(y,v){int d=(y%19*19+15)%30;d+=(y%4*2+y%7*4-d+34)%7+128;printf("%d/%d/%d",d%31+d/155,d/31,y);}
No he encontrado un caso en el que realmente se necesitara floor(d/31)
. Además, para tener en cuenta las fechas de mayo, la m
en el algoritmo de Meeus debe ser al menos 5, por lo tanto, el DoM es mayor que 154, por lo tanto, la división.
El año se proporciona como el número de argumentos de invocación del programa más uno, es decir. Para 1996 debes aportar los argumentos de 1995. La gama de ARG_MAX en los sistemas modernos es más que suficiente para esto.
PD. Veo que Gabe ha llegado a la misma implementación en Python 2.3, superándome por un personaje. Ah :( PPS. ¿Alguien está mirando un método tabular para 1800-2099?
Editar - Acortó la respuesta de Gabe a 88 caracteres:
y=input()
d=(y%19*19+15)%30
d+=(y%4*2+y%7*4-d+34)%7+128
print"%d/%d/%d"%(d%31+d/155,d/31,y)
El reto
Calcule la fecha de la Pascua ortodoxa griega ( http://www.timeanddate.com/holidays/us/orthodox-easter-day ) el domingo de un año determinado (1900-2100) utilizando la menor cantidad de caracteres.
La entrada es solo un año en el formulario ''2010''. No es relevante donde lo obtengas (Input, CommandLineArgs, etc.) ¡pero debe ser dinámico!
La salida debe estar en la forma día-mes-año (por ejemplo, dd/mm/yyyy
o d/m/yyyy
)
Restricciones ¡ No se deben usar funciones estándar, como easter_date()
Mathematica o easter_date()
PHP, que devuelven la fecha (no aplicable gregorian) automática!
Ejemplos
2005 returns 1/5/2005
2006 returns 23/4/2006
2007 returns 8/4/2007
2008 returns 27/4/2008
2009 returns 19/4/2009
2010 returns 4/4/2010
2011 returns 24/4/2011
2012 returns 15/4/2012
2013 returns 5/5/2013
2014 returns 20/4/2014
2015 returns 12/4/2015
El conteo de códigos incluye entrada / salida (es decir, programa completo).
Edit: me refiero a la fecha de Pascua del este .
Referencia: http://en.wikipedia.org/wiki/Computus
COBOL, 1262 caracteres
WORKING-STORAGE SECTION.
01 V-YEAR PIC S9(04) VALUE 2010.
01 V-DAY PIC S9(02) VALUE ZERO.
01 V-EASTERDAY PIC S9(04) VALUE ZERO.
01 V-CENTURY PIC S9(02) VALUE ZERO.
01 V-GOLDEN PIC S9(04) VALUE ZERO.
01 V-GREGORIAN PIC S9(04) VALUE ZERO.
01 V-CLAVIAN PIC S9(04) VALUE ZERO.
01 V-FACTOR PIC S9(06) VALUE ZERO.
01 V-EPACT PIC S9(06) VALUE ZERO.
PROCEDURE DIVISION
XX-CALCULATE EASTERDAY.
COMPUTE V-CENTURY = (V-YEAR / 100) + 1
COMPUTE V-GOLDEN= FUNCTION MOD(V-YEAR, 19) + 1
COMPUTE V-GREGORIAN = (V-CENTURY * 3) / 4 - 12
COMPUTE V-CLAVIAN
= (V-CENTURY * 8 + 5) / 25 - 5 - V-GREGORIAN
COMPUTE V-FACTOR
= (V-YEAR * 5) / 4 - V-GREGORIAN - 10
COMPUTE V-EPACT
= FUNCTION MOD((V-GOLDEN * 11 + 20 + V-CLAVIAN), 30)
IF V-EPACT = 24
ADD 1 TO V-EPACT
ELSE
IF V-EPACT = 25
IF V-GOLDEN > 11
ADD 1 TO V-EPACT
END-IF
END-IF
END-IF
COMPUTE V-DAY = 44 - V-EPACT
IF V-DAY < 21
ADD 30 TO V-DAY
END-IF
COMPUTE V-DAY
= V-DAY + 7 - (FUNCTION MOD((V-DAY + V-FACTOR), 7))
IF V-DAY <= 31
ADD 300 TO V-DAY GIVING V-EASTERDAY
ELSE
SUBTRACT 31 FROM V-DAY
ADD 400 TO V-DAY GIVING V-EASTERDAY
END-IF
.
XX-EXIT.
EXIT.
Nota: No es mía, pero me gusta.
EDIT: Agregué un recuento de caracteres con espacios, pero no sé cómo funciona el espaciado en COBOL, así que no cambié nada del original. ~ vlad003
ACTUALIZACIÓN: he encontrado dónde el OP obtuvo este código: http://www.tek-tips.com/viewthread.cfm?qid=31746&page=112 . Solo estoy poniendo esto aquí porque el autor lo merece. ~ vlad003
Tcl
Pascua oriental
(116 caracteres)
puts [expr 1+[incr d [expr ([set y $argv]%4*2+$y%7*4-[
set d [expr ($y%19*19+15)%30]]+34)%7+123]]%30]/[expr $d/30]/$y
Utiliza el algoritmo de Meeus. Toma el año como argumento de línea de comando, produce Eastern easter. Podría ser de una sola línea, pero es un poco más legible cuando se divide ...
Pascua occidental
(220 caracteres antes de dividir sobre líneas)
interp alias {} tcl::mathfunc::s {} set;puts [expr [incr 3 [expr {
s(2,(s(4,$argv)%100/4*2-s(3,(19*s(0,$4%19)+s(1,$4/100)-$1/4-($1-($1+8)/25+46)
/3)%30)+$1%4*2-$4%4+4)%7)-($0+11*$3+22*$2)/451*7+114}]]%31+1]/[expr $3/31]/$4
Utiliza el algoritmo anónimo.
BASIC, 973 caracteres
Sub EasterDate (d, m, y)
Dim FirstDig, Remain19, temp ''intermediate results
Dim tA, tB, tC, tD, tE ''table A to E results
FirstDig = y / 100 ''first 2 digits of year
Remain19 = y Mod 19 ''remainder of year / 19
'' calculate PFM date
temp = (FirstDig - 15) / 2 + 202 - 11 * Remain19
Select Case FirstDig
Case 21, 24, 25, 27 To 32, 34, 35, 38
temp = temp - 1
Case 33, 36, 37, 39, 40
temp = temp - 2
End Select
temp = temp Mod 30
tA = temp + 21
If temp = 29 Then tA = tA - 1
If (temp = 28 And Remain19 > 10) Then tA = tA - 1
''find the next Sunday
tB = (tA - 19) Mod 7
tC = (40 - FirstDig) Mod 4
If tC = 3 Then tC = tC + 1
If tC > 1 Then tC = tC + 1
temp = y Mod 100
tD = (temp + temp / 4) Mod 7
tE = ((20 - tB - tC - tD) Mod 7) + 1
d = tA + tE
''return the date
If d > 31 Then
d = d - 31
m = 4
Else
m = 3
End If
End Sub
Crédito: Sociedad Astronómica de Australia del Sur
EDITAR: Agregué un recuento de caracteres pero creo que se podrían eliminar muchos espacios; No sé BASIC, así que no hice ningún cambio en el código. ~ vlad003
C #, 155 157 182 209 212 caracteres
class P{static void Main(string[]i){int y=int.Parse(i[0]),c=(y%19*19+15)%30,d=c+(y%4*2+y%7*4-c+34)%7+128;System.Console.Write(d%31+d/155+"/"+d/31+"/"+y);}}
Python 2.3, 97 caracteres
y=int(input())
c=(y%19*19+15)%30
d=c+(y%4*2+y%7*4-c+34)%7+128
print"%d/%d/%d"%(d%31+d/155,d/31,y)
Esto también usa el algoritmo Meeus Julian (y debería funcionar para las fechas de mayo).
- eliminado ya no es necesario comprobar para los años modernos y cero relleno en la salida
- No esperes más a los Easters en marzo porque no hay ninguno entre 1800-2100
- Incluye la versión de Python 2.3 (la más corta hasta ahora)
Delphi 377 335 317 caracteres
Linea sola:
var y,c,n,i,j,m:integer;begin Val(ParamStr(1),y,n);c:=y div 100;n:=y-19*(y div 19);i:=c-c div 4-(c-((c-17)div 25))div 3+19*n+15;i:=i-30*(i div 30);i:=i-(i div 28 )*(1-(i div 28)*(29 div(i+1))*((21 -n)div 11));j:=y+y div 4 +i+2-c+c div 4;j:=j-7*(j div 7);m:=3+(i-j+40 )div 44;Write(i-j+28-31*(m div 4),''/'',m,''/'',y)end.
Formateado:
var
y,c,n,i,j,m:integer;
begin
Val(ParamStr(1),y,n);
c:=y div 100;
n:=y-19*(y div 19);
i:=c-c div 4-(c-((c-17)div 25))div 3+19*n+15;
i:=i-30*(i div 30);
i:=i-(i div 28 )*(1-(i div 28)*(29 div(i+1))*((21 -n)div 11));
j:=y+y div 4 +i+2-c+c div 4;j:=j-7*(j div 7);
m:=3+(i-j+40 )div 44;
Write(i-j+28-31*(m div 4),''/'',m,''/'',y)
end.
Java - 252 196 190 caracteres
Actualización 1: El primer algo fue para Western Gregorian Easter. Arreglado a Eastern Julian Easter ahora. Guarda 56 caracteres :)
Actualización 2: Parece que no se requiere relleno de cero. Guarda 4 caracteres.
class E{public static void main(String[]a){long y=new Long(a[0]),b=(y%19*19+15)%30,c=b+(y%4*2+y%7*4-b+34)%7+(y>1899&y<2100?128:115),m=c/31;System.out.printf("%d/%d/%d",c%31+(m<5?0:1),m,y);}}
Con nuevas líneas
class E{
public static void main(String[]a){
long y=new Long(a[0]),
b=(y%19*19+15)%30,
c=b+(y%4*2+y%7*4-b+34)%7+(y>1899&y<2100?128:115),
m=c/31;
System.out.printf("%d/%d/%d",c%31+(m<5?0:1),m,y);
}
}
JavaScript (196 caracteres)
Utilizando el algoritmo Meeus Julian . Esta implementación asume que se dio un año válido de cuatro dígitos.
y=~~prompt();d=(19*(y%19)+15)%30;x=d+(2*(y%4)+4*(y%7)-d+34)%7+114;m=~~(x/31);d=x%31+1;if(y>1899&&y<2100){d+=13;if(m==3&&d>31){d-=31;m++}if(m==4&&d>30){d-=30;m++}}alert((d<10?"0"+d:d)+"/0"+m+"/"+y)
Javascript 125 caracteres
Esto manejará los años 1900 - 2199. Algunas de las otras implementaciones no pueden manejar el año 2100
correctamente.
y=prompt();k=(y%19*19+15)%30;e=(y%4*2+y%7*4-k+34)%7+k+127;m=~~(e/31);d=e%31+m-4+(y>2099);alert((d+=d<30||++m-34)+"/"+m+"/"+y)
Ungolfed..ish
// get the year to check.
y=prompt();
// do something crazy.
k=(y%19*19+15)%30;
// do some more crazy...
e=(y%4*2+y%7*4-k+34)%7+k+127;
// estimate the month. p.s. The "~~" is like Math.floor
m=~~(e/31);
// e % 31 => get the day
d=e%31;
if(m>4){
d += 1;
}
if(y > 2099){
d += 1;
}
// if d is less than 30 days add 1
if(d<30){
d += 1;
}
// otherwise, change month to May
// and adjusts the days to match up with May.
// e.g., 32nd of April is 2nd of May
else{
m += 1;
d = m - 34 + d;
}
// alert the result!
alert(d + "/" + m + "/" + y);
Una solución para las fechas hasta 2399.
Estoy seguro de que hay una manera de calcular fechas de forma algorítmica más allá de esto, pero no quiero averiguarlo.
y=prompt();k=(y%19*19+15)%30;e=(y%4*2+y%7*4-k+34)%7+k+127;m=~~(e/31);d=e%31+m-4+(y<2200?0:~~((y-2000)/100));alert((d+=d<30||++m-34)+"/"+m+"/"+y)
Matemática
<<Calendar`;a=Print[#3,"/",#2,"/",#]&@@EasterSundayGreekOrthodox@#&
Invocar con
a[2010]
Salida
4/4/2010
Yo también: no veo el punto de no usar funciones integradas .
PHP CLI, no easter_date()
, 125 caracteres
Válido para las fechas del 13 de marzo de 1900 al 13 de marzo de 2100, ahora funciona para Easters que caen en mayo
Código:
<?=date("d/m/Y",mktime(0,0,0,floor(($b=($a=(19*(($y=$argv[1])%19)+15)%30)+(2*($y%4)+4*$y%7-$a+34)%7+114)/31),($b%31)+14,$y));
Invocación:
$ php codegolf.php 2010
$ php codegolf.php 2005
Salida:
04/04/2010
01/05/2005
Con espacios en blanco:
<?=date("d/m/Y", mktime(0, 0, 0, floor(($b = ($a = (19 * (($y = $argv[1]) % 19) + 15) % 30) + (2 * ($y % 4) + 4 * $y % 7 - $a + 34) % 7 + 114) / 31), ($b % 31) + 14, $y));
Esta iteración ya no es legible gracias al manejo de tareas por parte de PHP. ¡Es casi un lenguaje funcional!
Para completar, aquí está la solución anterior de 127 caracteres que no se basa en etiquetas cortas:
Código:
echo date("d/m/Y",mktime(0,0,0,floor(($b=($a=(19*(($y=$argv[1])%19)+15)%30)+(2*($y%4)+4*$y%7-$a+34)%7+114)/31),($b%31)+14,$y));
Invocación:
$ php -r ''echo date("d/m/Y",mktime(0,0,0,floor(($b=($a=(19*(($y=$argv[1])%19)+15)%30)+(2*($y%4)+4*$y%7-$a+34)%7+114)/31),($b%31)+14,$y));'' 2010
$ php -r ''echo date("d/m/Y",mktime(0,0,0,floor(($b=($a=(19*(($y=$argv[1])%19)+15)%30)+(2*($y%4)+4*$y%7-$a+34)%7+114)/31),($b%31)+14,$y));'' 2005
Python ( 101 140 132 115 caracteres)
y=input()
d=(y%19*19+15)%30
e=(y%4*2+y%7*4-d+34)%7+d+127
m=e/31
a=e%31+1+(m>4)
if a>30:a,m=1,5
print a,''/'',m,''/'',y
Este utiliza el algoritmo Meeus Julian, pero como este solo funciona entre 1900 y 2099, una implementación que usa el algoritmo gregoriano anónimo se está implementando.
Edición: Ahora 2005 se maneja adecuadamente. Gracias a Mark por señalarlo.
Edición 2: Mejor manejo de algunos años, ¡gracias por todos los comentarios!
Edit 3: Debería funcionar para todos los años en rango. (Perdón por haberlo secuestrado Juan.)
No lo voy a implementar, pero me gustaría ver uno en el que el código envíe un correo electrónico al Papa, escanee cualquier respuesta que regrese para una fecha y la devuelva.
Es cierto que el proceso de llamada puede estar bloqueado por un tiempo.
''VB .Net implementation of:
''http://aa.usno.navy.mil/faq/docs/easter.php
Dim y As Integer = 2010
Dim c, d, i, j, k, l, m, n As Integer
c = y / 100
n = y - 19 * (y / 19)
k = (c - 17) / 25
i = c - c / 4 - (c - k) / 3 + 19 * n + 15
i = i - 30 * (i / 30)
i = i - (i / 28) * (1 - (i / 28) * (29 / (i + 1)) * ((21 - n) / 11))
j = y + y / 4 + i + 2 - c + c / 4
j = j - 7 * (j / 7)
l = i - j
m = 3 + (l + 40) / 44
d = l + 28 - 31 * (m / 4)
Easter = DateSerial(y, m, d)