Programação supersticiosa

19

Seu desafio é extremamente simples. Dado um ano como entrada, imprima todos os meses desse ano que conterão uma sexta - feira 13, de acordo com o calendário gregoriano. Observe que, embora o Calendário Gregoriano não tenha sido introduzido até 1582, por uma questão de simplicidade, fingiremos que ele está em uso desde 0001 DC.

Regras

  • Programas ou funções completos são permitidos.

  • Você pode receber entradas como argumentos de função, de STDIN ou como argumentos de linha de comando.

  • Você não tem permissão para usar nenhuma data e hora incorporadas.

  • Você pode assumir com segurança que a entrada será um ano válido. Se a entrada for menor que 1, não for um número inteiro válido ou maior que o tipo de número nativo do seu idioma, você não precisará lidar com isso e obterá um comportamento indefinido.

  • A saída pode ser números, em inglês ou em qualquer outro formato legível, desde que você especifique o padrão.

  • Certifique-se de ter em conta os anos bissextos. E lembre -se, anos bissextos não acontecem a cada 4 anos!

Dicas

Como existem tantas maneiras diferentes de fazer isso, não quero lhe dizer como fazê-lo. No entanto, pode ser confuso por onde começar; portanto, existem algumas maneiras confiáveis ​​de determinar o dia da semana a partir de uma data.

IO de amostra

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

Como de costume, isso é código-golfe, então as brechas padrão se aplicam e a resposta mais curta vence.

DJMcMayhem
fonte
5
Quando executado na sexta-feira 13, deve reverter e gerar meses que não têm sexta-feira 13. (Referências Freaky Friday para a vitória)
Addison Crump
11
Related
Digital Trauma
Este exemplo está certo 0001 --> 5:? De acordo com esta página (e meu código), deve ser abril e julho.
faubi
@faubiguy meu mal, você está certo. Isso foi no calendário juliano. Deixe-me consertar isso.
DJMcMayhem
Por "você não tem permissão para usar nenhuma data ou hora incorporadas", também não posso converter para hora unix?
precisa saber é

Respostas:

1

Pyth, 73 Bytes

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

Experimente online!

Usando o algoritmo de Gauss, como na minha resposta em Python. ~ 55 bytes do código são para o cálculo durante a semana, portanto, a escolha de um algoritmo melhor pode diminuir bastante isso, suponho ... mas ei, pelo menos está funcionando agora! :)

Denker
fonte
2

Python 2, 157 144 136 bytes

Minha solução usa o algoritmo de Gauss. Entrada é o ano como Inteiro. Saída é a lista de meses com uma sexta-feira 13 como números (1-12). Provavelmente mais golfe possível, mas está ficando tarde ... Vou editar este amanhã e diminuir um pouco mais. Enquanto isso, sugestões são sempre bem-vindas!

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]

edit: reduziu para 144, substituindo o loop for por uma lista de compreensão e fazendo outros pequenos ajustes.

edit2: reduziu para 136 com as sugestões de Morgan Thrapp e corrigiu o bug que ele descobriu. Muito obrigado! :)

Denker
fonte
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

Isso usa uma versão modificada da fórmula para o dia juliano para calcular o dia da semana de 13 de março e, em seguida, usa o número de dias da semana em que cada mês é compensado em janeiro para encontrar o dia da semana para o restante do dia. meses, começando nos últimos 2 meses do ano anterior, começando em março, e nos primeiros 10 meses do ano atual (para evitar o cálculo dos anos bissextos duas vezes).

faubi
fonte
1

C - 164 153 112 bytes

Encontrei uma pequena solução agradável usando uma versão fortemente modificada do método de Schwerdtfeger. Ele codifica a tabela necessária em um número inteiro usando a base 7, modificada para caber em uma palavra de 32 bits assinada. Ele gera o mês como um caractere ASCII, com janeiro codificado como 1fevereiro 2e assim por diante, com outubro codificado como :novembro codificado como novembro ;e dezembro 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++;}

Aqui está um pouco não-destruído:

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

Tenho certeza de que existem algumas maneiras de torná-lo ainda menor, mas acho que o algoritmo, ou uma pequena variação dele, é quase ideal para encontrar os meses em que ocorre a sexta-feira 13 (com relação ao tamanho do código). Notas:

  1. Se uma palavra de 64 bits pudesse ser usada, seria possível livrar-se de uma adição irritante ( +5).
  2. A variável mnão é realmente necessária, pois o mês que estamos vendo é dedutível t.

Deixo minha resposta mais antiga abaixo, pois ele usa um método completamente diferente, não visto em outras respostas aqui.


Isso se baseia em uma solução para um 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);}

Simula basicamente o calendário gregoriano, avançando um dia de cada vez, imprimindo o mês em que é sexta e 13. Aqui está de uma forma um pouco mais legível:

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);
}
Para s
fonte
ECC impressionante, mas não encontrado em 123456789 -> janeiro, outubro outubro
RosLuP 28/16/16
Hmm, faz para mim. Pode me algum motivo dependente da plataforma? Funciona para mim em um Macbook Pro bastante moderno ao compilar com o Clang. Observe que ele gera 1:para 123456789, onde :indica outubro. Esclarei a codificação acima.
Fors
Sim 1: aqui também; Não entendi ':' era para outubro ...
RosLuP
0

Excel, 137 bytes

Recebe o ano de entrada em A1. Saída é uma lista não separada de Hexidecimal. (Janeiro = 0, dezembro = B)

Usa o algoritmo de Gauss para janeiro e 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
fonte
Atualmente, esta resposta usa data e hora incorporadas, que são explicitamente declaradas contrárias às regras do desafio.
Fors
@Fors, obrigado por apontar isso. Atualizada.
Wernisch 28/10
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 da saída stdin no stdout tente http://ideone.com/XtuhGj [a função de depuração é 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
fonte