迷信程序设计


19

您的挑战非常简单。给定年份作为输入,请根据公历打印该年中包含13号星期五的所有月份。请注意,尽管公历直到1582年才引入,但为简单起见,我们将其自0001 AD开始使用。

规则

  • 允许使用完整的程序或功能。

  • 您可以将输入用作STDIN的函数参数,也可以用作命令行参数。

  • 不允许您使用任何日期和时间内置函数。

  • 您可以放心地假设输入将是有效年份。如果输入小于1,不是有效的整数,或者大于您的语言本机数字类型,则不必处理此操作,并且会得到不确定的行为。

  • 只要指定标准,输出就可以是数字,英文或其他任何人类可读的格式。

  • 确保您考虑了leap年。请记住,leap年并不是每4年发生一次!

提示

由于有很多不同的方法可以解决此问题,因此我不想告诉您如何执行此操作。但是,从何处开始可能会造成混乱,因此这里有几种可靠的方法来确定从日期开始的星期几。

样品IO

2016 --> May
0001 --> 4, 7
1997 --> Jun
1337 --> 09, 12
123456789 --> January, October

像往常一样,这是代码高尔夫球,因此存在标准漏洞,并且最短的答案会获胜。


5
当在13号星期五运行时,它应该反转并输出没有13号星期五的月份。(胜利的怪诞星期五参考)
艾迪生·克伦普


这个例子正确0001 --> 5吗?根据此页面(和我的代码),应该是4月和7月。
faubi

@faubiguy我不好,你是对的。那是在朱利安日历上。我来解决这个问题。
DJMcMayhem

通过“不允许使用任何日期或时间内置函数”,我也不能转换为Unix时间吗?
busukxuan

Answers:


1

Pyth,73个字节

L?>b2QtQfq%+++13+/-*2.6?qT2 12%-T2 12 .2 1*5%yT4*4%yT100*6%yT400 7 5r1 13

在线尝试!

使用高斯算法,就像在我的Python答案中一样。大约55个字节的代码用于工作日的计算,因此我认为选择更好的算法可能会使此问题大为减少……但是,至少它现在可以正常工作了!:)


2

Python 2中,157 144个 136字节

我的解决方案使用高斯算法。输入的年份为整数。输出是月份列表,第13个星期五为数字(1-12)。可能还会打更多的高尔夫球,但是它来晚了...明天再编辑一次,然后再打一点。在此期间,随时欢迎提出建议!

def f(i):y=lambda m:(i-1,i)[m>2];print[m for m in range(1,13)if(13+int(2.6*((m-2)%12,12)[m==2]-.2)+y(m)%4*5+y(m)%100*4+y(m)%400*6)%7==5]

编辑:通过使用列表组合替换for循环将其降至144,然后进行其他一些小的调整。

edit2:根据Morgan Thrapp的建议,将其降低到136,并修复了他发现的错误。非常感谢!:)


1

的Perl - 141个 107 103字节

$y=<>-1;map{$y++if++$i==3;print"$i "if($y+int($y/4)-int($y/100)+int($y/400))%7==$_}'634163152042'=~/./g

这使用儒略日的公式的修改版本来计算3月13日的星期几,然后使用每月从1月起偏移的星期几来查找其余日期的星期几。从3月开始的上一年的最后2个月开始,然后是本年的前10个月(以避免两次计算(年)。


1

Ç - 164个 153 112字节

我找到了使用Schwerdtfeger方法的大量修改版本的不错的解决方案。它使用基数7将必需的表编码为整数,并修改为适合带符号的32位字。它以ASCII字符形式输出月份,一月编码为1,二月编码为2依此类推,十月编码为:,十一月编码为;,十二月编码为<

t=1496603958,m;main(y){for(scanf("%d",&y),y--;(y%100+y%100/4+y/100%4*5+t+5)%7||putchar(m+49),t;t/=7)2-++m||y++;}

在这里,它有点松散:

t=1496603958,m;
main(y){
  for(
    scanf("%d",&y),y--;
    (y%100+y%100/4+y/100%4*5+t+5)%7||putchar(m+49),t;
    t/=7
  )
    2-++m||y++;
}

我敢肯定有几种方法可以使它变得更小,但是我认为该算法或其稍有变化对于寻找第13个星期五发生的月份(相对于代码大小)而言几乎是理想的。笔记:

  1. 如果可以使用64位字,则可以消除烦人的加法(+5)。
  2. m实际上,该变量不是必需的,因为可以从中推导出要查看的月份t

我将下面的较旧答案留在下面,因为它使用的是完全不同于此处其他答案中所见的方法。


这是基于对相关问题的解决方案(/codegolf//a/22531/7682)。

Y,M,D,d;main(y){for(scanf("%d",&y);Y<=y;++D>28+(M^2?M+(M>7)&1^2:!(Y&3)&&(Y%25||!(Y&15)))&&(D=1,M=M%12+1)<2&&Y++)(d=++d%7)^1||D^13||y^Y||printf("%d,",M);}

它基本上模拟公历,一次前进一天,在星期五和13号打印月份。在这里,它的可读性略高:

Y,M,D,d;
main(y){
  for(
    scanf("%d",&y);
    Y<=y;
    ++D>28+(
      M^2
        ?M+(M>7)&1^2
        :!(Y&3)&&(Y%25||!(Y&15))
    )&&(
      D=1,
      M=M%12+1
    )<2&&Y++
  )
    (d=++d%7)^1||D^13||y^Y||
      printf("%d,",M);
}

令人印象深刻的ecc但在123456789中找不到-> 10月1月,10月
RosLuP

嗯,对我有用。可能会因平台而异吗?使用Clang编译时,它可以在相当现代的Macbook Pro上为我工作。请注意,它输出1:123456789,其中:表示月。我澄清了上面的编码。
Fors

是的1:也是。我不明白':'是10月...
RosLuP

0

Excel,137个字节

在A1中输入年份。输出是十六进制的非分隔列表。(一月= 0,十二月= B)

在一月和八月使用高斯算法。

=CHOOSE(MOD(6+5*MOD(A1-1,4)+4*MOD(A1-1,400),7)+1,"","",1,"","",0,"")&CHOOSE(MOD(5*MOD(A1-1,4)+4*MOD(A1-1,400),7)+1,9,35,"8B",5,"2A",7,4)

此答案当前使用日期和时间内置函数,这与挑战中的规则明确指出。
Fors

@Fors,感谢您指出这一点。更新。
维尔尼施(Wernisch)

0

C,276219字节

#define R return
#define L(i) for(;i-->0;) 
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}s(y,m,g){g+=4;L(m)g+=u(y,m),g%=7;L(y)g+=1+u(y,1),g%=7;R g;}z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}

从stdout中的stdin输出输入到http://ideone.com/XtuhGj [调试功能为z]

w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}
/*    
// ritorna il numero dei giorni di anno=y mese=m con mese in 0..11
// m==1 significa febbraio   y%4?0:y%100?1:!(y%400) non funziona
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}

// argomenti anno:y[0..0xFFFFFFF]  mese:m[0..11]  giorno:g[1..u(y,m)]
// ritorna il numero del giorno[0..6]
s(y,m,g)
{g+=4; // correzione per il giorno di partenza anno mese giorno = 0,1,1
 L(m)g+=  u(y,m),g%=7; // m:0..m-1  somma mod 7 i giorni del mese dell'anno y
 L(y)g+=1+u(y,1),g%=7; // y:0..y-1  somma mod 7 gli anni da 0..y-1
                       // g+=1+u(y,1) poiche' (365-28)%7=1 e 1 e' febbraio
 R g;
}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
// calcola tutti gli ultimi giorni del mese dell'anno y che cadono di lunedi'
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
//ritorna in r il numero dei mesi che ha giorno 13 di venerdi[==4]
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}
*/

#define P printf
#define W while 
#define M main 
#define F for
#define U unsigned
#define N int
#define B break
#define I if
#define J(a,b)  if(a)goto b
#define G goto
#define P printf
#define D double
#define C unsigned char
#define A getchar()
#define O putchar
#define Y malloc
#define Z free
#define S sizeof
#define T struct
#define E else
#define Q static
#define X continue
M()
{N y,m,g,r,arr[]={1,297,1776,2000,2016,3385}, arr1[]={2016,1,1997,1337,123456789};
 C*mese[]={"gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"};
 C*giorno[]={"Lun","Mar","Mer","Gio","Ven","Sab","Dom"};
 P("Inserisci Anno mese giorno>");r=scanf("%d %d %d", &y, &m, &g);
 P("Inseriti> %d %d %d r=%d\n", y, m, g, r);
 I(r!=3||m>12||m<=0||g>u(y,m-1))R 0;
 r=s(y,m-1,g);// 12-> 11 -> 0..10
 P("Risultato=%d giorno=%s\n", r, giorno[r]);
 r=w(y,0,0);P(" r=%d ", r);P("\n");
 F(m=0;m<6;++m)
        {P("N anno=%d -->",arr[m]); 
         r=w(arr[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }
 F(m=0;m<4;++m)
        {P("N anno=%d -->",arr1[m]); 
         r=z(arr1[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.