Programmation superstitieuse

19

Votre défi est extrêmement simple. Étant donné une année en entrée, imprimez tous les mois de cette année qui contiendront un vendredi 13 selon le calendrier grégorien. Notez que même si le calendrier grégorien n'a été introduit qu'en 1582, pour simplifier, nous prétendons qu'il est utilisé depuis 0001 après JC.

Règles

  • Les programmes ou fonctions complets sont autorisés.

  • Vous pouvez prendre l'entrée comme arguments de fonction, depuis STDIN ou comme arguments de ligne de commande.

  • Vous n'êtes pas autorisé à utiliser les fonctions intégrées de date et d'heure.

  • Vous pouvez sans risque supposer que l'entrée sera une année valide. Si l'entrée est inférieure à 1, pas un entier valide ou supérieure au type de numéro natif de votre langue, vous n'avez pas à gérer cela et vous obtenez un comportement non défini.

  • La sortie peut être des nombres, en anglais ou dans tout autre format lisible par l'homme, tant que vous spécifiez la norme.

  • Assurez-vous de tenir compte des années bissextiles. Et rappelez-vous, les années bissextiles ne se produisent pas tous les 4 ans!

Conseils

Puisqu'il y a tellement de façons différentes de procéder, je ne veux pas vous dire comment procéder. Cependant, il peut être difficile de savoir par où commencer, alors voici quelques façons fiables de déterminer le jour de la semaine à partir d'une date.

Exemple d'E / S

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

Comme d'habitude, c'est le code-golf, donc les échappatoires standard s'appliquent et la réponse la plus courte l'emporte.

DJMcMayhem
la source
5
Lorsqu'il est exécuté le vendredi 13, il devrait s'inverser et afficher les mois sans vendredi 13. (Freaky Friday références pour la victoire)
Addison Crump
1
Related
Digital Trauma
Est - ce bon exemple: 0001 --> 5? Selon cette page (et mon code) ce devrait être avril et juillet.
faubi
@faubiguy mon mauvais, tu as raison. C'était sur le calendrier julien. Permettez-moi de résoudre ce problème.
DJMcMayhem
Par "vous n'êtes pas autorisé à utiliser des fonctions intégrées de date ou d'heure", est-ce que je ne peux pas non plus convertir en temps Unix?
busukxuan

Réponses:

1

Pyth, 73 octets

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

Essayez-le en ligne!

Utiliser l'algorithme de Gauss, comme dans ma réponse Python. ~ 55 octets du code sont pour le calcul de la semaine, donc choisir un meilleur algorithme pourrait le faire baisser beaucoup je suppose ... mais bon, au moins ça marche maintenant! :)

Denker
la source
2

Python 2, 157 144 136 136 octets

Ma solution utilise l'algorithme de Gauss. L'entrée est l'année en tant que nombre entier. La sortie est la liste des mois avec un vendredi 13 sous forme de nombres (1-12). Probablement un peu plus de golf possible, mais il se fait tard ... Je vais éditer celui-ci demain et descendre un peu plus. En attendant, les suggestions sont toujours les bienvenues!

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: Je suis descendu à 144 en remplaçant la boucle for par une liste complète et en faisant quelques autres petits ajustements.

edit2: Il est passé à 136 avec les suggestions de Morgan Thrapp et a corrigé le bug qu'il a découvert. Merci beaucoup! :)

Denker
la source
1

Perl - 141 107 103 octets

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

Cela utilise une version modifiée de la formule pour le jour julien pour calculer le jour de la semaine du 13 mars, puis utilise le nombre de jours de la semaine chaque mois est décalé de janvier pour trouver le jour de la semaine pour le reste de la mois, en commençant par les 2 derniers mois de l'année précédente débutant en mars puis les 10 premiers mois de l'année en cours (pour éviter de calculer deux fois les années bissextiles).

faubi
la source
1

C - 164 153 112 octets

J'ai trouvé une jolie petite solution en utilisant une version fortement modifiée de la méthode de Schwerdtfeger. Il code la table nécessaire dans un entier en utilisant la base 7, modifiée pour tenir dans un mot signé de 32 bits. Il affiche le mois sous forme de caractère ASCII, avec janvier codé comme 1, février comme 2et ainsi de suite, avec octobre codé comme :, novembre codé comme ;et décembre codé comme <.

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

Ici, il est légèrement non golfé:

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

Je suis sûr qu'il existe plusieurs façons de le rendre encore plus petit, mais je pense que l'algorithme, ou une légère variation de celui-ci, est presque idéal pour trouver les mois où le vendredi 13 se produit (en ce qui concerne la taille du code). Remarques:

  1. Si un mot de 64 bits avait pu être utilisé, il serait possible de se débarrasser d'un ajout gênant ( +5).
  2. La variable mn'est pas réellement nécessaire, car le mois que nous regardons est déductible t.

Je laisse ma réponse plus ancienne ci-dessous, car elle utilise une méthode complètement différente que l'on ne voit pas dans les autres réponses ici.


Ceci est basé sur une solution à un problème connexe ( /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);}

Il simule essentiellement le calendrier grégorien, avançant un jour à la fois, imprimant le mois alors qu'il s'agit d'un vendredi et du 13. Le voici sous une forme légèrement plus lisible:

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
la source
ecc impressionnant mais introuvable en 123456789 -> janvier, octobre octobre
RosLuP
Hmm, ça le fait pour moi. Pourrais-je une raison dépendante de la plate-forme? Cela fonctionne pour moi sur un Macbook Pro assez moderne lors de la compilation avec Clang. Notez qu'il sort 1:pour 123456789, où :dénote octobre. J'ai clarifié l'encodage ci-dessus.
Fors
Oui 1: ici aussi; Je n'ai pas compris ':' était pour octobre ...
RosLuP
0

Excel, 137 octets

Prend l'année d'entrée dans A1. La sortie est une liste non séparée de Hexidecimal. (Janvier = 0, décembre = B)

Utilise l'algorithme de Gauss pour janvier et août.

=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
la source
Cette réponse utilise actuellement des fonctions intégrées de date et d'heure, ce qui est explicitement indiqué par rapport aux règles du défi.
Fors
@Fors, merci de l'avoir signalé. Mis à jour.
Wernisch
0

C, 276 219 octets

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

entrée depuis la sortie stdin dans stdout, essayez de http://ideone.com/XtuhGj [la fonction de débogage est 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
la source