Programmazione superstiziosa


19

La tua sfida è estremamente semplice. Dato un anno come input, stampa tutti i mesi di quell'anno che conterranno un venerdì 13 secondo il calendario gregoriano. Si noti che anche se il calendario gregoriano non fu introdotto fino al 1582, per semplicità fingeremo che sia in uso dal 0001 d.C.

Regole

  • Sono ammessi programmi o funzioni completi.

  • È possibile accettare input come argomenti di funzione, da STDIN o come argomenti della riga di comando.

  • Non è consentito utilizzare alcun data e ora incorporati.

  • Puoi tranquillamente presumere che l'input sarà un anno valido. Se l'input è inferiore a 1, non un numero intero valido o maggiore del tipo di numero nativo delle lingue, non è necessario gestirlo e si ottiene un comportamento indefinito.

  • L'output può essere un numero, in inglese o in qualsiasi altro formato leggibile dall'uomo, purché si specifichi lo standard.

  • Assicurati di tenere conto degli anni bisestili. E ricorda, gli anni bisestili non accadono ogni 4 anni!

Suggerimenti

Dal momento che ci sono molti modi diversi per farlo, non voglio dirti come farlo. Tuttavia, potrebbe essere fonte di confusione da dove iniziare, quindi ecco un paio di modi diversi affidabili per determinare il giorno della settimana da una data.

IO di esempio

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

Come al solito, si tratta di code-golf, quindi si applicano scappatoie standard e vince la risposta più breve.


5
Se eseguito venerdì 13, dovrebbe invertire e generare mesi che non hanno venerdì 13. (Riferimenti per la vittoria di Freaky Friday)
Addison Crump,


Questo esempio è giusto 0001 --> 5:? Secondo questa pagina (e il mio codice) dovrebbe essere aprile e luglio.
Faubi,

@faubiguy mia cattiva, hai ragione. Era sul calendario giuliano. Lascia che lo risolva.
DJMcMayhem

Con "non ti è permesso usare alcun builtin di data o ora", non posso neanche convertirmi in unix time?
Busukxuan,

Risposte:


1

Pyth, 73 byte

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

Provalo online!

Usando l'algoritmo di Gauss, come nella mia risposta Python. ~ 55 byte del codice sono per il calcolo del giorno della settimana, quindi la scelta di un algoritmo migliore potrebbe ridurlo di molto suppongo ... ma ehi, almeno ora funziona! :)


2

Python 2, 157 144 136 byte

La mia soluzione utilizza l'algoritmo di Gauss. L'input è l'anno come numero intero. L'output è l'elenco dei mesi con un venerdì 13 come numeri (1-12). Probabilmente un po 'più di golf possibile, ma si sta facendo tardi ... Lo modificherò domani e lo abbasserò un po' di più. I suggerimenti sono sempre benvenuti nel frattempo!

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]

modificare: ridotto a 144 sostituendo il for-loop con una lista lista e apportando alcune altre piccole regolazioni.

edit2: golfato fino a 136 con i suggerimenti di Morgan Thrapp e risolto il bug che aveva scoperto. Molte grazie! :)


1

Perl - 141 107 103 byte

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

Questo utilizza una versione modificata della formula per il giorno giuliano per calcolare il giorno della settimana del 13 marzo, quindi utilizza il numero di giorni della settimana che ogni mese viene compensato da gennaio per trovare il giorno della settimana per il resto del mesi, a partire dagli ultimi 2 mesi dell'anno precedente a partire da marzo, quindi i primi 10 mesi dell'anno in corso (per evitare di calcolare due anni bisestili).


1

C - 164 153 112 byte

Ho trovato una bella soluzione usando una versione fortemente modificata del metodo di Schwerdtfeger. Codifica la tabella necessaria in un numero intero usando base 7, modificata per adattarsi a una parola con segno a 32 bit. Emette il mese come carattere ASCII, con gennaio codificato come 1, febbraio come 2e così via, con ottobre codificato come :, novembre codificato come ;e dicembre codificato come <.

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

Qui è leggermente non golfato:

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

Sono sicuro che ci sono alcuni modi per renderlo ancora più piccolo, ma penso che l'algoritmo, o una sua leggera variazione, sia quasi ideale per trovare i mesi in cui si verifica Venerdì 13 (rispetto alla dimensione del codice). Appunti:

  1. Se fosse stata utilizzata una parola a 64 bit, sarebbe possibile eliminare un'aggiunta fastidiosa ( +5).
  2. La variabile mnon è effettivamente necessaria, poiché il mese che stiamo guardando è deducibilet .

Lascio qui di seguito la mia risposta più vecchia, visto che utilizza un metodo completamente diverso non visto in altre risposte qui.


Questo si basa su una soluzione a un problema correlato ( /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 sostanzialmente il calendario gregoriano, avanzando di un giorno alla volta, stampando il mese in cui è un venerdì e il 13. Eccolo in una forma leggermente più leggibile:

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

impressionante ecc. ma non trovato in 123456789 -> gennaio, ottobre ottobre
RosLuP

Hmm, lo fa per me. Potrei un motivo dipendente dalla piattaforma? Funziona per me su un Macbook Pro abbastanza moderno durante la compilazione con Clang. Si noti che esce 1:per 123456789, dove :indica ottobre. Ho chiarito la codifica sopra.
Fors,

Sì 1: anche qui; Non ho capito ":" era per ottobre ...
RosLuP,

0

Excel, 137 byte

Prende input anno in A1. L'output è un elenco non separato di esadecimale. (Gennaio = 0, dicembre = B)

Utilizza l'algoritmo di Gauss per gennaio 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)

Questa risposta utilizza attualmente la data e l'ora incorporate, che viene esplicitamente dichiarata contraria alle regole della sfida.
Fors,

@Fors, grazie per averlo sottolineato. Aggiornato.
Wernisch,

0

C, 276 219 byte

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

input dall'output stdin in stdout provare a http://ideone.com/XtuhGj [la funzione di debug è 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");
        }

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.