25

挑战

使用最少的字符计算给定年份 (1900-2100) 中的希腊东正教复活节 ( http://www.timeanddate.com/holidays/us/orthodox-easter-day ) 的日期。

输入只是“2010”形式的一年。它与您从哪里获得它(输入、CommandLineArgs 等)无关,但它必须是动态的!

输出应采用日-月-年的形式(比如dd/mm/yyyyor d/m/yyyy

限制必须使用自动返回(不适用公历)日期的标准函数,例如 MathematicaEasterSundayGreekOrthodox或 PHP !easter_date()

例子

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

代码计数包括输入/​​输出(即完整程序)。

编辑: 我的意思是东部复活节日期。

参考: http ://en.wikipedia.org/wiki/Computus

4

14 回答 14

9

Python(101 140 132 115 个字符)

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

这个使用Meeus Julian 算法,但由于这个算法只在 1900 年到 2099 年之间有效,因此使用匿名格里高利算法的实现即将出现。

编辑:现在 2005 年得到妥善处理。感谢马克指出。

编辑 2:更好地处理几年,感谢所有输入!

编辑 3:应该适用于范围内的所有年份。(对不起,胡安劫持了它。)

于 2010-08-28T14:25:20.223 回答
4

数学

<<Calendar`;a=Print[#3,"/",#2,"/",#]&@@EasterSundayGreekOrthodox@#&

调用

a[2010]

输出

4/4/2010

我也是:我看不出不使用内置函数的意义。

于 2010-08-28T04:19:18.907 回答
4

PHP CLI,不easter_date(),125 个字符

适用于 1900 年 3 月 13 日至 2100 年 3 月 13 日的日期,现在适用于 5 月的复活节

代码:

<?=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));

调用:

$ php codegolf.php 2010
$ php codegolf.php 2005

输出:

04/04/2010
01/05/2005

带空格:

<?=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));

由于 PHP 对分配的处理,此迭代不再可读。它几乎是一种函数式语言!


为了完整起见,这里是之前的不依赖短标签的 127 个字符的解决方案:

代码:

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

调用:

$ 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
于 2010-08-28T06:12:09.370 回答
4

C#,155 157 182 209 212 个字符

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 个字符

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)

这也使用了 Meeus Julian 算法(并且应该适用于 5 月的日期)。

  • 删除了现代不再需要的检查和输出中的零填充
  • 不要再期待三月的复活节了,因为 1800-2100 之间没有复活节
  • 包括 Python 2.3 版本(目前最短)
于 2010-08-28T07:02:02.730 回答
3

Java - 252 196 190 个字符


  • 更新 1:第一个算法是针对西方格里高利复活节的。现在固定为东朱利安复活节。保存了 56 个字符 :)

  • 更新 2:似乎不需要零填充。节省了 4 个字符。


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

带有换行符

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);
 }
}
于 2010-08-28T05:04:24.883 回答
2

德尔福377 335 317 个字符

单线:

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.

格式化:

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.
于 2010-08-28T00:40:52.170 回答
2

JavaScript(196 个字符)

使用Meeus Julian 算法。此实现假定给出了一个有效的四位数年份。

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)
于 2010-08-28T06:01:47.570 回答
2

Tcl

东部复活节

(116 个字符)

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

使用 Meeus 算法。将年份作为命令行参数,生成东部复活节。可能是单行的,但拆分时它的可读性略高...

西方复活节

(分割线之前的 220 个字符)

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

使用匿名算法。

于 2010-08-28T15:00:19.993 回答
1

COBOL,1262 个字符

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.

注:不是我的,但我喜欢

编辑:我添加了一个带空格的字符数,但我不知道 COBOL 中的空格是如何工作的,所以我没有改变原始的任何内容。~vlad003

更新:我发现 OP 从哪里得到了这个代码:http ://www.tek-tips.com/viewthread.cfm?qid=31746&page=112 。我只是把它放在这里,因为作者应得的。~vlad003

于 2010-08-27T13:03:30.110 回答
1

C, 128 121 98 个字符

回到 Meeus 的算法。计算朱利安的一天,但调整为格里高利(这对我来说仍然很幼稚,但我找不到更短的替代方案)。

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

我还没有找到floor(d/31)实际需要的案例。此外,要考虑 5 月的日期,min Meeus 的算法必须至少为 5,因此 DoM 大于 154,因此是除法。

年份以程序调用参数的数量加一的形式提供,即。对于 1996 年,您必须提供 1995 年的参数。现代系统上的 ARG_MAX 范围足以满足此要求。

PS。我看到 Gabe 在 Python 2.3 中实现了相同的实现,超过了我一个字符。哦。:( PPS。有人在看 1800-2099 的表格方法吗?

编辑 - 缩短 Gabe 对 88 个字符的回答:

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)
于 2010-08-29T09:16:06.847 回答
0

基本,973 个字符

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

图片来源:南澳大利亚天文学会

编辑:我添加了一个字符数,但我认为可以删除很多空格;我不了解 BASIC,所以我没有对代码进行任何更改。~vlad003

于 2010-08-27T13:08:04.323 回答
0
'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)
于 2010-08-28T11:42:05.420 回答
0

我不打算实现它,但我希望看到一个代码通过电子邮件向教皇发送电子邮件,扫描任何返回的日期的答案,然后返回。

诚然,调用进程可能会被阻塞一段时间。

于 2010-08-28T20:54:43.663 回答
0

Javascript 125 个字符

这将处理 1900 - 2199 年。其他一些实现无法2100正确处理年份。

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)

不打高尔夫球..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);

最多可修复 2399 的日期。
我确信有一种方法可以通过算法计算超出此范围的日期,但我不想弄清楚。

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)
于 2010-09-02T17:23:35.723 回答