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

25
demandé sur Nas Banov 2010-08-27 16:53:53

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

9
répondu Juan 2010-08-28 23:52:51

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
4
répondu 10 revsuser113292 2010-08-28 21:28:46

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)
4
répondu Gabe 2010-08-30 03:52:25

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 .

4
répondu belisarius 2011-05-17 06:21:45

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);
 }
}
3
répondu BalusC 2011-05-17 02:21:29

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)
2
répondu Josh Leitzel 2010-08-28 23:51:38

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.
2
répondu RRUZ 2010-09-16 13:56:59

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.

2
répondu Donal Fellows 2011-05-17 02:22:16

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

1
répondu Tom Medley 2010-08-28 23:42:04

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)
1
répondu Michael Foukarakis 2010-09-02 10:16:48

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

0
répondu Tom Medley 2010-08-28 04:56:05

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.

0
répondu mjfgates 2010-08-28 20:54:43

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)
0
répondu David Murdoch 2010-09-03 13:34:41
'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)
0
répondu dbasnett 2011-05-17 02:23:17