Programación supersticiosa

19

Tu desafío es extremadamente simple. Dado un año como entrada, imprima todos los meses de ese año que contendrán un viernes 13 de acuerdo con el calendario gregoriano. Tenga en cuenta que aunque el calendario gregoriano no se introdujo hasta 1582, por simplicidad, pretendemos que ha estado en uso desde 0001 AD.

Reglas

  • Se permiten programas o funciones completos.

  • Puede tomar la entrada como argumentos de función, desde STDIN o como argumentos de línea de comando.

  • No está permitido usar ninguna fecha y hora incorporadas.

  • Puede asumir con seguridad que la entrada será un año válido. Si la entrada es menor que 1, no es un número entero válido, o mayor que el tipo de número nativo de su idioma, no tiene que manejar esto y obtiene un comportamiento indefinido.

  • La salida puede ser números, en inglés o en cualquier otro formato legible por humanos, siempre que especifique el estándar.

  • Asegúrese de tener en cuenta los años bisiestos. Y recuerde, ¡ los años bisiestos no ocurren cada 4 años!

Consejos

Dado que hay muchas maneras diferentes de hacerlo, no quiero decirte cómo hacerlo. Sin embargo, puede ser confuso dónde comenzar, por lo que aquí hay un par de formas confiables diferentes de determinar el día de la semana a partir de una fecha.

Muestra IO

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

Como de costumbre, este es el código de golf, por lo que se aplican las lagunas estándar y gana la respuesta más corta.

DJMcMayhem
fuente
55
Cuando se ejecuta el viernes 13, debería revertir y generar meses que no tengan un viernes 13. (Freaky Friday referencias para la victoria)
Addison Crump
1
Relacionado
Trauma digital
¿Es este ejemplo correcto 0001 --> 5? De acuerdo con esta página (y mi código) debería ser abril y julio.
faubi
@faubiguy mi mal, tienes razón. Eso estaba en el calendario juliano. Déjame arreglar eso.
DJMcMayhem
Por "no se le permite usar ninguna fecha u hora incorporada", ¿es que tampoco puedo convertir a hora unix?
busukxuan

Respuestas:

1

Pyth, 73 bytes

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

Pruébalo en línea!

Usando el algoritmo de Gauss, como en mi respuesta de Python. ~ 55 bytes del código son para el cálculo del día de la semana, por lo que elegir un mejor algoritmo podría reducir esto mucho, supongo ... pero bueno, ¡al menos está funcionando ahora! :)

Denker
fuente
2

Python 2, 157 144 136 Bytes

Mi solución usa el algoritmo de Gauss. La entrada es el año como entero. La salida es la lista de meses con un viernes 13 como números (1-12). Probablemente un poco más de golf posible, pero se está haciendo tarde ... Voy a editar este mañana y bajarlo un poco más. ¡Las sugerencias siempre son bienvenidas mientras tanto!

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]

editar: Lo bajé a 144 reemplazando el ciclo for con una comprensión de la lista y haciendo algunos otros pequeños ajustes.

edit2: se redujo a 136 con las sugerencias de Morgan Thrapp y solucionó el error que descubrió. ¡Muchas gracias! :)

Denker
fuente
1

Perl - 141 107 103 bytes

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

Esto usa una versión modificada de la fórmula para el día juliano para calcular el día de la semana del 13 de marzo, luego usa la cantidad de días de la semana que cada mes se compensa desde enero para encontrar el día de la semana para el resto de la semana. meses, comenzando con los últimos 2 meses del año anterior a partir de marzo y luego los primeros 10 meses del año actual (para evitar calcular dos años bisiestos).

faubi
fuente
1

C - 164 153 112 bytes

Encontré una pequeña solución con una versión muy modificada del método de Schwerdtfeger. Codifica la tabla necesaria en un número entero usando la base 7, modificada para caber en una palabra de 32 bits con signo. Emite el mes como un carácter ASCII, con enero codificado como 1, febrero como 2y así sucesivamente, con octubre codificado como :, noviembre codificado como ;y diciembre codificado como <.

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

Aquí está un poco ignorado:

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

Estoy seguro de que hay algunas formas de hacerlo aún más pequeño, pero creo que el algoritmo, o una ligera variación del mismo, es casi ideal para encontrar los meses en los que se produce el viernes 13 (con respecto al tamaño del código). Notas:

  1. Si se hubiera podido usar una palabra de 64 bits, sería posible deshacerse de una adición molesta ( +5).
  2. La variable mno es realmente necesaria, ya que el mes que estamos viendo es deducible t.

Dejo mi respuesta anterior a continuación, ya que utiliza un método completamente diferente que no se ve en otras respuestas aquí.


Esto se basa en una solución a un problema relacionado ( /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);}

Básicamente simula el calendario gregoriano, avanzando un día a la vez, imprimiendo el mes cuando es viernes y 13. Aquí está en una forma ligeramente más legible:

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);
}
Fors
fuente
impresionante ecc pero no encontrado en 123456789 -> enero, octubre octubre
RosLuP
Hmm, lo hace por mí. ¿Podría alguna razón dependiente de la plataforma? Funciona para mí en un Macbook Pro bastante moderno al compilar con Clang. Tenga en cuenta que genera 1:para 123456789, donde :denota octubre. Aclaré la codificación anterior.
Fors
Sí 1: aquí también; No entendí ':' fue para octubre ...
RosLuP
0

Excel, 137 bytes

Toma año de entrada en A1. La salida es una lista no separada de Hexidecimal. (Enero = 0, diciembre = B)

Utiliza el algoritmo de Gauss para enero y agosto.

=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)
Wernisch
fuente
Esta respuesta actualmente usa fechas y horas integradas, que se declara explícitamente en contra de las reglas del desafío.
Fors
@ For, gracias por señalarlo. Actualizado.
Wernisch
0

C, 276 219 bytes

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

entrada de salida stdin en stdout intente http://ideone.com/XtuhGj [la función de depuración es 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");
        }

}
RosLuP
fuente