Code Golf: calculer la date de Pâques Orthodoxe
Le Défi
Calculer la date de la Pâques orthodoxe grecque ( http://www.timeanddate.com/holidays/us/orthodox-easter-day ) dimanche dans une année donnée (1900-2100) en utilisant le moins de caractères.
Input est juste une année sous la forme '2010'. Ce n'est pas pertinent où vous l'obtenez (Input, CommandLineArgs etc.) mais il doit être dynamique!
Sortie doit être sous la forme jour-mois-année (disons dd/mm/yyyy
ou d/m/yyyy
)
Restrictions Pas de fonctions standard, telles que Mathematica EasterSundayGreekOrthodox
ou PHP easter_date()
, qui renvoient la date (Non applicable Grégorienne) automatique doit être utilisé!
Exemples
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
Le nombre de codes inclut l'entrée / sortie (c'est-à-dire le programme complet).
Modifier: Je veux dire la date de Pâques.
Référence: http://en.wikipedia.org/wiki/Computus
14 réponses
Python (101 140 132 115 caractères)
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
Celui-ci utilise l'algorithme Meeus Julian mais comme celui-ci ne fonctionne qu'entre 1900 et 2099, une implémentation utilisant algorithme grégorien anonyme arrive tout de suite.
Edit: maintenant 2005 est correctement géré. Merci à Mark pour le pointant à l'extérieur.
Edit 2: Meilleure gestion de quelques années, merci pour toute l'entrée!
Edit 3: devrait fonctionner pour toutes les années dans la plage. (Désolé pour le détournement Juan.)
CLI PHP, pas de easter_date()
, 125 caractères
Valide pour les dates du 13 Mars 1900 au 13 Mars 2100, travaille maintenant pour Pâques qui tombent en Mai
Code:
<?=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));
Invocation:
$ php codegolf.php 2010
$ php codegolf.php 2005
Sortie:
04/04/2010
01/05/2005
Avec des espaces:
<?=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));
Cette itération n'est plus lisible grâce à la gestion des affectations par PHP. C'est presque un langage fonctionnel!
Pour être complet, voici la solution de 127 caractères précédente qui ne compter sur les balises courtes:
Code:
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));
Invocation:
$ 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
C#, 155 157 182 209 212 les caractères
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 caractères
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)
Cela utilise également L'algorithme Meeus Julian (et devrait fonctionner pour les dates en mai).
- supprimé ne vérifie plus nécessaire pour les années modernes et zéro-remplissage en sortie
- ne vous attendez plus à Easters en Mars car il n'y en a pas entre 1800-2100
- inclus la version Python 2.3 (la plus courte jusqu'à présent)
Mathematica
<<Calendar`;a=Print[#3,"/",#2,"/",#]&@@EasterSundayGreekOrthodox@#&
Invoquer avec
a[2010]
Sortie
4/4/2010
moi aussi: Je ne vois pas l'intérêt de ne pas utiliser les fonctions intégrées .
Java - 252 196 190 les caractères
Mise à jour 1: le premier algo était pour Pâques Grégorienne occidentale. Fixé à Pâques Julian est maintenant. Sauvé 56 caractères :)
Mise à jour 2: zéro remplissage ne semble pas être nécessaire. Sauvé 4 caractères.
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);}}
Avec des nouvelles lignes
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 caractères)
En utilisant l'algorithme Meeus Julian . Cette mise en œuvre suppose qu'une année valide à quatre chiffres a été donnée.
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)
Delphi 377 335 317 les caractères
Ligne Unique:
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.
Formaté:
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.
Tcl
Pâques Orientales
(116 caractères)
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
Utilise L'algorithme Meeus. Prend l'année comme argument de ligne de commande, produit Eastern easter. Pourrait être un one-liner, mais il est légèrement plus lisible lorsqu'il est divisé...
Pâques Occidentale
(220 caractères avant de diviser sur les lignes)
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
Utilise L'algorithme anonyme.
COBOL, 1262 caractères
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.
Note: Pas le mien, mais je l'aime
EDIT: j'ai ajouté un nombre de caractères avec des espaces mais je ne sais pas comment l'espacement fonctionne dans COBOL donc je n'ai rien changé à l'original. ~ vlad003
Mise à jour: j'ai trouvé où L'OP a obtenu CE code: http://www.tek-tips.com/viewthread.cfm?qid=31746&page=112 . je mets ça ici parce que l'auteur le mérite. ~vlad003
C, 128 121 98 les caractères
Retour à l'algorithme de Meeus. Calcul du jour en Julien, mais Ajustement pour grégorien (cela me semble toujours naïf, mais je ne peux pas trouver une alternative plus courte).
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);}
Je n'ai pas trouvé un cas où floor(d/31)
serait réellement nécessaire. Aussi, pour tenir compte des dates en mai, le m
dans l'algorithme de Meeus doit être au moins 5, donc le DoM est supérieur à 154, d'où la division.
L'année est fournie comme le nombre de arguments d'invocation de programme plus un, ie. pour 1996, vous devez fournir des arguments pour 1995. La gamme D'ARG_MAX sur les systèmes modernes est plus que suffisante pour cela.
PS. Je vois que Gabe est arrivé à la même implémentation en Python 2.3, me dépassant d'un caractère. Aw. :( PPS. Quelqu'un qui regarde une méthode tabulaire pour 1800-2099?
Edit-raccourci la réponse de Gabe à 88 caractères:
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)
BASIC, 973 caractères
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édit: Société Astronomique de l'Australie du Sud
EDIT: j'ai ajouté un nombre de caractères mais je pense que beaucoup d'espaces pourraient être supprimés; Je ne connais pas BASIC donc je n'ai apporté aucune modification au code. ~ vlad003
Je ne vais pas l'implémenter, mais j'aimerais en voir un où le code envoie un e-mail au Pape, scanne toute réponse qui revient pour une date, et renvoie cela.
Certes, le processus appelant peut être bloqué pendant un certain temps.
Javascript 125 caractères
Cela va gérer les années 1900-2199. Certaines des autres implémentations ne peuvent pas gérer l'année 2100
correctement.
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);
Un correctif pour les dates jusqu'à 2399.
Je suis sûr qu'il existe un moyen de calculer algorithmiquement les dates au-delà de cela, mais je ne veux pas le comprendre.
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)
'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)