Le dernier lundi


27

Le lundi 31 octobre, c'est Halloween. Et cela m'a fait réfléchir - je me demande quels autres mois le dernier jour du mois est aussi un lundi?

Contribution

  • Un entier positif dans n'importe quel format pratique représentant une année 10000 > y > 0,.
  • L'entrée peut être complétée par des zéros (par exemple, 0025pour l'année 25) si nécessaire.

Sortie

  • Une liste des mois de cette année où le dernier jour du mois est un lundi.
  • Il peut s'agir de noms de mois (par exemple, January, March, October), ou de noms abrégés ( Jan, Mar, Oct), ou de nombres ( 1, 3, 10), de lignes distinctes ou d'une liste ou délimités, etc., tant que cela n'est pas ambigu pour le lecteur.
  • Le format de sortie doit être cohérent:
    • Pour toutes les entrées (ce qui signifie que vous ne pouvez pas générer de noms de mois pour certaines entrées et de numéros de mois pour d'autres entrées)
    • Ainsi que cohérent par sortie (ce qui signifie que vous ne pouvez pas produire 1pour Januarydans la même sortie que Julpour July)
    • Fondamentalement, choisissez un format et respectez-le.

Règles

  • Supposons le calendrier grégorien pour les entrées / sorties, même jusqu'à y = 1.
  • Les années bissextiles doivent être correctement prises en compte (pour rappel: chaque année divisible par 4, sauf les années non divisibles par 100, sauf si elles sont également divisibles par 400 - 1700, 1800, 1900, toutes n'étaient pas des années bissextiles, mais 2000 l'était).
  • Vous pouvez utiliser tous les outils intégrés ou autres outils de calcul de date que vous aimez.
  • Un programme complet ou une fonction sont acceptables. S'il s'agit d'une fonction, vous pouvez renvoyer la sortie plutôt que de l'imprimer.
  • Les failles standard sont interdites.
  • Il s'agit de donc toutes les règles de golf habituelles s'appliquent et le code le plus court (en octets) l'emporte.

Exemples

   1 --> Apr, Dec
 297 --> May
1776 --> Sep
2000 --> Jan, Jul
2016 --> Feb, Oct
3385 --> Jan, Feb, Oct

Classement



1
Associé mais pas en double ou?
ElPedro

@ElPedro Associé mais pas en double. Le premier ne permet aucune intégration et demande un combo date / jour fixe (vendredi 13), tandis que le second demande le dernier dimanche de chaque mois de l'année, limité entre 1900 et 3015.
AdmBorkBork

Désolé @TimmD. Ma mauvaise compréhension de votre commentaire.
ElPedro

1
@ElPedro Aucun problème! Je préférerais avoir une question et être claire, plutôt que de ne pas avoir de question et d'avoir quelque chose de peu clair.
AdmBorkBork

Réponses:


2

Dyalog APL avec le cal de dfns , version 15.0: 22; Version 16.0: 19 octets

La fonction cal est livrée avec une installation par défaut, entrez simplement )copy dfns.

Version 15.0: ∊⎕{⍵/⍨2=≢⍎⊢⌿cal⍺⍵}¨⍳12

enrôler (aplatir)

⎕{... entrée numérique comme argument de gauche pour la fonction anonyme suivante, en prenant chacune des valeurs du côté droit comme argument de droite à son tour

⍵/⍨ l'argument if (donne une liste vide sinon)

2= deux (à savoir dimanche et lundi) est égal à

le décompte de

les chiffres

⊢⌿ la rangée la plus basse de

cal le calendrier pour

⍺⍵ année argument de gauche, mois argument de droite, ce dernier étant

⍳12 1 à 12

Version 16.0: ⍸2=⎕{≢⍎⊢⌿cal⍺⍵}¨⍳12

les indices où

2= deux égaux (à savoir dimanche et lundi)

⎕{... entrée numérique comme argument de gauche pour la fonction anonyme suivante, en prenant chacune des valeurs du côté droit comme argument de droite à son tour

le décompte de

les chiffres

⊢⌿ la rangée la plus basse de

cal le calendrier pour

⍺⍵ année argument de gauche, mois argument de droite, ce dernier étant

⍳12 1 à 12


19

JavaScript (Firefox 30+), 112 109 103 95 95 octets

Regardez ma, pas intégré!

y=>[for(m of(i=0,y%4|y%400*!(y%100)&&6)+"63153042641")if((i++,y+(y>>2)-(y/100|0)*3/4|0)%7==m)i]

Voici une version ES6 de 107 octets:

y=>[...(y%4|y%400*!(y%100)&&6)+"63153042641"].map((m,i)=>(y+(y>>2)-(y/100|0)*3/4|0)%7-m?0:i+1).filter(x=>x)

Et voici ma précédente tentative, 123 113 octets d'ES6:

y=>[(l=y%4|y%400*!(y%100))?[7]:[1,7],[4,12],[9],[3,6],[8,11],[5],l?[1,2,10]:[2,10]][(y+(y>>2)-(y/100|0)*3/4|0)%7]

Explication

Le jour de la semaine d'une année particulière est calculé comme suit:

y+(y>>2)-(y/100|0)*3/4|0)%7

En d'autres termes:

  • Prenez y.
  • Ajoutez le nombre de 4e années avant y( y>>2).
  • Soustrayez le nombre de 100 ans avant y( y/100|0).
  • Ajoutez le nombre de 400e années auparavant y; c'est 1/4 de y/100|0, donc nous utilisons *3/4|0.

Ensuite, nous modulons le résultat par 7. Si nous laissons 0le dimanche, 1le lundi, etc., le résultat correspond au jour de la semaine du 31 décembre de cette année. Par conséquent, pour décembre, nous voulons vérifier si le résultat est 1. Cela nous donne le dernier caractère de la chaîne.

Le dernier jour de novembre est 31 jours avant le dernier jour de décembre. Cela signifie que pour que le dernier jour de novembre soit un lundi, le 31 décembre doit être un (1 + 31) % 7 = 4= jeudi.

Cette procédure est répétée jusqu'à ce que nous revenions au mois de mars (a 3). Qu'il y ait ou non un jour bissextile, le dernier jour de février est 31 jours avant le dernier jour de mars, nous pouvons donc le calculer aussi (c'est (3 + 31) % 7 = 6). La partie délicate consiste à trouver la valeur correcte pour janvier:

  • S'il s'agit d'une année bissextile, le dernier jour de janvier est 29 jours avant le dernier jour de février, ce qui entraîne (6 + 29) % 7 = 0.
  • Sinon, c'est 28 jours avant le dernier jour de février, ce qui entraîne (6 + 28) % 7 = 6.

Nous pouvons calculer s'il s'agit ou non d'une année bissextile avec l'extrait de code suivant:

!(y%400)|y%100*!(y%4)

Cela donne 0si yn'est pas une année bissextile et un entier positif sinon. Cela nous amène à

!(y%400)|y%100*!(y%4)?0:6

pour calculer le jour de janvier. Cependant, nous pouvons faire mieux en inversant les conditions:

y%4|y%400*!(y%100)?6:0

Comme le résultat de la fausse est toujours 0 de toute façon, nous pouvons le réduire à

y%4|y%400*!(y%100)&&6

sauver un octet de plus précieux.

En rassemblant le tout, nous parcourons chaque caractère de la chaîne, vérifiant si chacun est égal au jour de la semaine du 31 décembre. Nous gardons les index de ceux qui correspondent, renvoyant ce tableau à la fin. Et c'est ainsi que vous effectuez des calculs d'année bissextile sans fonctions intégrées.


Owww ... Mon cerveau, as-tu expliqué les années bissextiles dans tout ça?
Magic Octopus Urn

2
@carusocomputing C'est pour ça !(y%4)*y%100|!(y%400). chaque année divisible par 4, sauf les années non divisibles par 100, sauf si divisible également par 400
mbomb007

Espérons que y+(y>>2)+(z=y/25>>2)+(z>>2)vous économiserez encore un octet.
Neil

@Neil Merci, mais j'ai trouvé un meilleur moyen :-)
ETHproductions

Agréable; J'ai enregistré 6 octets sur mon port Batch en utilisant (y*5/4-(y/100)*3/4).
Neil

11

JavaScript (Firefox 30-57), 67 65 64 63 61 octets

y=>[for(_ of(m='')+1e11)if(new Date(y+400,++m).getDay()==2)m]

Enregistré 2 4 6 octets grâce à @ETHproductions. Enregistrement d'un autre octet en affichant les mois dans l'ordre inverse.


Je pense que vous pouvez économiser 2 octets en le .keys()y=>[for(_ of(m=0,Array(12)))if(new Date(y+400,++m).getDay()==2)m]
déplaçant

@ETHproductions Je peux enregistrer un octet supplémentaire en inversant la commande!
Neil

L'ordre inverse est très bien. Le formatage de la sortie n'est pas la partie intéressante de ce défi.
AdmBorkBork

Quelle est notre politique sur les compréhensions de baie maintenant qu'elles ont été supprimées de la spécification?
MayorMonty

Vous pouvez économiser encore 2 octets en sautant Array(12)complètement: y=>[for(_ of(m=0,1e11+""))if(new Date(y+400,++m).getDay()==2)m]
ETHproductions

8

MySQL, 183 134 129 106 octets

SET @y=2016;SELECT help_topic_id AS m FROM mysql.help_topic HAVING m BETWEEN 1 AND 12 AND 2=DAYOFWEEK(LAST_DAY(CONCAT(@y,-m,-1)))

Remplacez 2016par l'année souhaitée. Courir.

Rév. 2: utilisé la help_topicstable dans l'installation par défaut au lieu de créer une table temporaire.

Rev.3: J'ai- adopté l' astuce d' aross et j'ai remarqué que je pouvais également omettre les guillemets pour "-1".
Cependant, -1est requis dans MySQL: j'ai besoin d'une date complète.

Rev.4: La restriction m BETWEEN 1 AND 12peut être effectuée en tant que m>0 AND m<13(-6), mais n'est pas nécessaire du tout - les valeurs invalides seront ignorées; les avertissements seront comptés mais non répertoriés.


Vous avez vraiment besoin de la table shema mysql? mariadb.com/kb/en/mariadb/mysqlhelp_topic-table
Jörg Hülsermann

@ JörgHülsermann Je ne comprends pas votre point.
Titus

Devrait FROM help_topicsans mysql.travail? Je n'ai pas essayé
Jörg Hülsermann

@ JörgHülsermann uniquement si vous ajoutez au préalable USE mysql;La base de données correcte doit être sélectionnée d'une manière ou d'une autre.
Titus

5

Perl, 64 octets

Comprend +1 pour -n

Donnez votre avis sur STDIN:

perl -M5.010 mon.pl <<< 2016

mon.pl:

#!/usr/bin/perl -n
map$b.=$/.gmtime$_.e4,-7e6..3e7;say$b=~/on (\S+ )\S.* $_.* 1 /g

5

Lot, 160 152 octets

@set/ay=%1,m=0,j=6*!(!(y%%4)*(y%%100)+(y%%400)),y=(y*5/4-y/100*3/4)%%7
@for %%d in (%j% 6 3 1 5 3 0 4 2 6 4 1)do @set/am+=1&if %%d==%y% call echo %%m%%

Réponse de Port of @ ETHproduction. Avec les abréviations des mois pour 197 189 octets:

@set/ay=%1,j=6*!(!(y%%4)*(y%%100)+(y%%400)),y=(y*5/4-y/100*3/4)%%7
@for %%m in (Jan.%j% Feb.6 Mar.3 Apr.1 May.5 Jun.3 Jul.0 Aug.4 Sep.2 Oct.6 Nov.4 Dec.1)do @if %%~xm==.%y% call echo %%~nm

4

J, 48 34 33 octets

[:I.(2=7|_2#@".@,@{.])&>@calendar

15 octets enregistrés avec l'aide de @ Adám .

Utilise le calendrier intégré pour générer un tableau de chaînes représentant les mois, puis analyse chaque chaîne pour déterminer si le dernier lundi est le dernier jour du mois. Il génère chaque mois comme numéro de mois de chacun. C'est Jan = 0, Feb = 1..., Dec = 11.

La sortie de calendarest

   _3 ]\ calendar 2016
┌─────────────────────┬─────────────────────┬─────────────────────┐
│         Jan         │         Feb         │         Mar         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│     1  2  3  4  5  6│        1  2  3  4  5│
│  3  4  5  6  7  8  9│  7  8  9 10 11 12 13│  6  7  8  9 10 11 12│
│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20│ 13 14 15 16 17 18 19│
│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27│ 20 21 22 23 24 25 26│
│ 24 25 26 27 28 29 30│ 28 29               │ 27 28 29 30 31      │
│ 31                  │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Apr         │         May         │         Jun         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│  1  2  3  4  5  6  7│           1  2  3  4│
│  3  4  5  6  7  8  9│  8  9 10 11 12 13 14│  5  6  7  8  9 10 11│
│ 10 11 12 13 14 15 16│ 15 16 17 18 19 20 21│ 12 13 14 15 16 17 18│
│ 17 18 19 20 21 22 23│ 22 23 24 25 26 27 28│ 19 20 21 22 23 24 25│
│ 24 25 26 27 28 29 30│ 29 30 31            │ 26 27 28 29 30      │
│                     │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Jul         │         Aug         │         Sep         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                 1  2│     1  2  3  4  5  6│              1  2  3│
│  3  4  5  6  7  8  9│  7  8  9 10 11 12 13│  4  5  6  7  8  9 10│
│ 10 11 12 13 14 15 16│ 14 15 16 17 18 19 20│ 11 12 13 14 15 16 17│
│ 17 18 19 20 21 22 23│ 21 22 23 24 25 26 27│ 18 19 20 21 22 23 24│
│ 24 25 26 27 28 29 30│ 28 29 30 31         │ 25 26 27 28 29 30   │
│ 31                  │                     │                     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│         Oct         │         Nov         │         Dec         │
│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│ Su Mo Tu We Th Fr Sa│
│                    1│        1  2  3  4  5│              1  2  3│
│  2  3  4  5  6  7  8│  6  7  8  9 10 11 12│  4  5  6  7  8  9 10│
│  9 10 11 12 13 14 15│ 13 14 15 16 17 18 19│ 11 12 13 14 15 16 17│
│ 16 17 18 19 20 21 22│ 20 21 22 23 24 25 26│ 18 19 20 21 22 23 24│
│ 23 24 25 26 27 28 29│ 27 28 29 30         │ 25 26 27 28 29 30 31│
│ 30 31               │                     │                     │
└─────────────────────┴─────────────────────┴─────────────────────┘

Usage

   f =: [:I.(2=7|_2#@".@,@{.])&>@calendar
   f 1
3 11
   f 297
4
   f 1776
8
   f 2000
0 6
   f 2016
1 9
   f 3385
0 1 9

Explication

[:I.(2=7|_2#@".@,@{.])&>@calendar  Input: year Y
                         calendar  Get 12 boxes each containing a month
    (                )&>@          Operate on each box
                    ]                Identity, get the box
         _2       {.                 Take the last two strings
                ,@                   Flatten it
             ".@                     Parse it into an array of integers
           #@                        Get the length
       7|                            Take it modulo 7
     2=                              Test if it equals 2 - it will either
                                     have two days or 9 days in the last
                                     two lines if the end is on a Monday
[:I.                               Return the indices containing a true value

attendez, le calendrier affiche-t-il réellement de l'art ascii?
Destructible Lemon

@DestructibleWatermelon Pour être exact, le format de sortie de calendarest un tableau de 12 cases où chaque case contient un tableau 2d de caractères
miles

Je ne sais même pas comment faire "chacun" en J, mais c'est déjà beaucoup plus court: I.7=;#&.>".&.>,&.>_2{.&.>calendar 2016si vous combinez tous les "under-open", vous devriez pouvoir le faire assez court.
Adám

@ Adám Merci, il utilise une meilleure méthode mais ce n'est pas un verbe en J. Je pense que ça va quand même aider
miles

Mon intention était seulement d'inspirer. Je sais que ce n'est pas un verbe.
Adám

4

Mathematica, 62 57 octets

DayName@DayRange[{#},{#+1},"EndOfMonth"]~Position~Monday&

Fonction anonyme. Prend un nombre en entrée et renvoie une liste de listes de nombres à élément unique en sortie. Honnêtement, je ne sais plus trop comment ça fonctionne.


4

Perl + cal, 46 octets

say`cal $_ $ARGV[0]`=~/\n.{5}\n/&&$_ for 1..12

Exemple:

$ perl -E 'say`cal $_ $ARGV[0]`=~/\n.{5}\n/&&$_ for 1..12' 2016

2







10


$

1
À proprement parler, c'est perl + cal, pas seulement perl :-p. Par exemple, ma machine Windows a Perl, mais cela ne fonctionnera pas là-bas.
philomory

Bon point, mis à jour cela et ma tentative bash.
steve

4

Java 7,186 182 172 octets

Merci à Kevin d'avoir économisé 4 octets
Merci à @cliffroot d'avoir économisé 10 octets

int[]f(int n){int c=n-1,x=c*365+c/4+c/400-c/100,k=0,b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3},a[]=new int[12];for(int i:b)a[k++]=(x+=i+28)%7==1?1:0;return a;}

non golfé

int[] f(int n) {
 int c=n-1,x=c*365+(c/4)+(c/400)-(c/100),k=0,
   b[] = {3,(n % 4 < 1 & n % 100 > 0) | n % 400 < 1 ? 1 : 0
                                     ,3,2,3,2,3,3,2,3,2,3},a = new int[ 12 ];

 if ( (n % 4 < 1 & n % 100 > 1) | n % 400 < 1 )
     b[ 1 ] = -1;
 for (int i : b)
    a[ k++ ] = (x += i + 28) % 7 == 1 ? 1 : 0;

return a;
     }

Cette version est fournie par @cliffroot ( 168 octets )

 static int[] f(int n) {
 int b = 13561787 | ( (n%4 < 1 & n%100 > 0) | n%400 < 1 ? 1 << 20 : 0 ),
           x = --n*365 + n/4 + n/400 - n/100,a[]=new int[12],k=0;
    while (k < 12)
    a[k++] = (x += (b >> 24 - k*2&3 ) + 28) % 7 == 1 ? 1 : 0;
  return a;   }
    }

échantillon de sortie

1 1 0 0 0 0 0 0 0 1 0 0(for input 3385)

1
Après avoir écrit ma réponse , je savais que tout le calcul vous - même serait plus court .. :) BTW, vous pouvez jouer au golf n%4==0à n%4<1; n%400==0vers n%400<1et int c=...;int[]b=...,a=...vers int c=...,b[]=...,a[]=....
Kevin Cruijssen

1
bet apeut être défini dans la intpartie comme ceci:int ... ,b[]=...,a[]=...
Olivier Grégoire

1
int[]f(int n){int x=--n*365+n/4+n/400-n++/100,k=0,b[]={1,(n%4<1&n%100>0)|n%400<1?-1:-2,1,0,1,0,1,1,0,1,0,1},a[]=new int[12];for(int i:b)a[k++]=(x+=i+30)%7==1?1:0;return a;}quelques octets enregistrés
cliffroot

1
peut également changer bà b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3}et i+30à i+28pour 2 octets
cliffroot

1
et encore 3 octetsint[]f(int n){int b=13561787|((n%4<1&n%100>0)|n%400<1?1<<20:0),x=--n*365+n/4+n/400-n/100,a[]=new int[12],k=0;while(k<12)a[k++]=(x+=(b>>24-k*2&3)+28)%7==1?1:0;return a;}
cliffroot

3

Python 2, 100 octets

Pouah. Les mathématiques avec les dates ne sont pas aussi simples que je le voudrais.

lambda y:[m+1for m in range(12)if(date(y,12,31)if m>10else(date(y,m+2,1)-timedelta(1))).weekday()<1]

Essayez-le en ligne

Même longueur:

lambda y:[m-1for m in range(2,14)if(date(y,12,31)if m>12else(date(y,m,1)-timedelta(1))).weekday()<1]

Je n'allais même pas essayer Python avec celui-ci. Bel effort.
ElPedro

3

MATL , 21 octets

12:"G@QhO6(YO9XO77=?@

Les mois sont affichés sous forme de nombres.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

Cela utilise des fonctions intégrées de conversion de date. Pour l'année donnée, il teste le dernier jour du mois qui est le lundi.

Au lieu de spécifier explicitement le dernier jour du mois k(qui peut être 28, 29, 30 ou 31), nous spécifions le 0-ème jour du mois k+1, qui est équivalent et ne dépend pas du mois ou de l'année.

12:      % Push [1 2 ... 12] (months)
"        % For each month k
  G      %   Push input
  @Q     %   Push k+1
  h      %   Concatenate
  O6(    %   Postpend four zeros. For example, for input 2016 and month k=1 
         %   (first iteration) this gives [2016 2 0 0 0 0] (year, month, day,
         %   hour, min, sec). The 0-th day of month k+1 is the same as the
         %   last day of month k.
  YO     %   Convert the above 6-element date vector to date number
  9XO    %   Convert date number to date string with output format 9, which 
         %   is weekday as a capital letter
  77=    %   Is it an 'M'?
  ?      %   If so
    @    %     Push current month (will be implicitly displayed)

3

Utilitaires Bash + GNU, 56 octets

seq -f1month-1day$1-%g-1 12|date -f- +%B%u|sed -n s/1//p

Semble nécessiter la dateversion 8.25. La version 8.23 ​​dans Ideone ne le coupe pas.


3

Excel, 537 octets

Parce que - vous savez - Excel!

Prend l'année d'entrée dans A1. Renvoie la liste hexadécimale des mois; 1 = janvier, C = décembre. Étant donné que chaque mois est un chiffre unique, aucun séparateur n'est nécessaire.

=IF(2=WEEKDAY(EOMONTH(DATE(A1,1,1),0)),1,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,2,1),0)),2,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,3,1),0)),3,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,4,1),0)),4,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,5,1),0)),5,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,6,1),0)),6,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,7,1),0)),7,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,8,1),0)),8,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,9,1),0)),9,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,10,1),0)),"A","")&IF(2=WEEKDAY(EOMONTH(DATE(A1,11,1),0)),"B","")&IF(2=WEEKDAY(EOMONTH(DATE(A1,12,1),0)),"C","")

Exemple: A1 contient 2016. B1 contient la formule ci-dessus et s'affiche sous la forme de 2Afévrier et octobre.


3

PHP, 109 180 159 octets

for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";
  • Produit l'année fournie, pas tous (... toujours lire la question)
  • Avis ignorés (merci Titus)
  • Changez whileen forcar c'est maintenant une seule année (encore une fois, merci Titus)

Vieux 2

$z=0;while($z++<9999){$o=[];$m=0;while($m++<12)if(date("N",strtotime(sprintf("%04d-$m-","$z").cal_days_in_month(0,$m,$z)))<2)$o[]=$m;echo count($o)>0?"$z:".implode(",",$o)."
":"";}

Prend en charge toutes les années du point à 10000, s'est également débarrassé d'un avertissement var non défini que je ne connaissais pas sur un PC. Oui, elle est plus longue que l'ancienne version, mais elle est plus robuste.

Vieux 1

while($z++<9999){$o=[];$m=0;while($m++<12)if(date("N",strtotime("$z-$m-".cal_days_in_month(0,$m,$z)))<2)$o[]=$m;echo count($o)>0?"$z:".implode(",",$o)."
":"";}

Si vous utilisez Windows ou un système 32 bits, il y aura le redoutable bug 2038, mais sur un système Linux 64 bits, ça va.

J'ai essayé d'utiliser date("t"...ce qui est censé représenter la dernière date du mois donné, mais les résultats ne correspondent pas à ceux mentionnés précédemment dans ce fil.


2
-2: "$ z" n'a pas besoin de guillemets -7: ignore les avis (ils ne sont pas imprimés avec les paramètres par défaut: ne pas initier $z, pas de guillemets pour N) -1: forau lieu de while -43 : prendre l'entrée comme demandé au lieu de parcourir les années -3: joinau lieu de implode-16: sortie directe: for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";+9 si vous insistez pour ne pas avoir de virgule de fin:echo$o=$o?",$m":$m;
Titus

Ahh mal lu la question! Je pensais que c'était pour toutes les années. Oups: B Merci pour les autres suggestions aussi, allez-y
CT14.IT

3

PHP, 92 octets

for($d=new DateTime("$argv[1]-1-1");$i++<12;)$d->modify("1month")->format(w)!=2?:print"$i,";

vérifier 12 fois 1 mois après le premier jour de l'année est un mardi. Si c'est le cas, c'est la veille du dernier jour du mois est un lundi.


Vous pouvez utiliser l'écho au lieu de l'impression et économiser 1
Octopus

1
@Octopus pas à l'intérieur de l'opérateur ternaire
Jörg Hülsermann

3

C, 214 octets

main(int a,char *b[]){for(int x,y,d,m=12;m;m--){y=atoi(b[1]);x=m-1;d=x==1?(y%4==0?(y%100==0?(y%400==0?29:28):29):28):(x==3||x==5||x==10?30:31);if((d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7==1)printf("%d\n",m);}}

Compiler

gcc -std=c99 -o foo foo.c

Non golfé

Avec des crédits aux gourous concernés.

Michael Keith et Tom Craver pour le programme C pour trouver le jour de la semaine en fonction de la date .

Collin Biedenkapp pour Q&A: Comment savoir quel est le dernier jour du mois?

/* credit to Collin Biedenkapp */
short _get_max_day(short x, int z) {
    if(x == 0 || x == 2 || x == 4 || x == 6 || x == 7 || x == 9 || x == 11)
        return 31;
    else if(x == 3 || x == 5 || x == 8 || x == 10)
        return 30;
    else {
        if(z % 4 == 0) {
            if(z % 100 == 0) {
                if(z % 400 == 0)
                    return 29;
                return 28;
            }
            return 29;
        }
        return 28;
    }
}

main(int argc,char *argv[]) {
 for(int y,d,m=12;m;m--) {
  y=atoi(argv[1]);
  d=_get_max_day(m-1,y);
  /* credit to Michael Keith and Tom Craver */
  if ((d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7 == 1)
    printf("%d\n",m);
 }
}

1
Et si vous inversiez votre ifdirection, pour avoir votre elseretour 31, et donc vous pouvez éliminer la grosse ==chaîne?
AdmBorkBork

1
serait mieux si (x == 1) {z part} else if (x == 3 || x == 5 || x == 8 || x == 10) return 30 else return 31
RosLuP

1
qu'en est-il de: renvoyer x == 1? (z% 4 == 0? (z% 100 == 0? (z% 400 == 0? 29: 28): 29): 28) :( x == 3 | | x == 5 || x == 8 || x == 10? 30: 31)
RosLuP

TimmyD + RosLuP: merci pour les points return (), 100 octets maintenant enregistrés.
steve

1
il est possible de continuer à réduire enfin jusqu'à ce que: u (y, m) {return m-1? 30 + ((2773 >> m) & 1): 28+ (y% 4 == 0 && y% 100 || y% 400 == 0);} où y est l'année et m le mois
RosLuP

3

C, 119 octets

t=1248700335,m;main(y){for(scanf("%d",&y),t+=y&3||y%25<1&&y&15;m++,(6+y+y/4-y/100+y/400+t)%7||printf("%d,",m),t;t/=7);}

Celui-ci utilise un tableau qui contient le décalage des jours de la semaine du dernier jour de chaque mois pour une année bissextile, encodé dans un mot signé de 32 bits en utilisant la base 7. Si ce n'est pas une année bissextile, nous ajoutons 1 au décalage de janvier (comme vous pouvez le voir y&3||y%25<1&&y&15est utilisé pour vérifier les années sans jours bissextiles). Ensuite, nous parcourons simplement chaque mois et vérifions si son dernier jour est un lundi. Assez simple en fait, pas de hacks ou de trucs laids. Ici, il est légèrement non golfé:

t=1248700335,m;
main(y){
  for(
    scanf("%d",&y),t+=y&3||y%25<1&&y&15;
    m++,(6+y+y/4-y/100+y/400+t)%7||printf("%d,",m),t;
    t/=7
  );
}

Je pourrais revisiter cela pour le réécrire comme une fonction pour enregistrer quelques caractères. Le printfprend également un peu trop de place ...


Le printf ("% d,", m) imprimerait quelque chose comme 1, ou 2, 3, donc il y en a toujours un ',' plus ... Je préfère utiliser seulement des espaces
RosLuP

En fait, je préfère également les espaces dans la sortie, mais j'écris habituellement mes solutions C golfées afin qu'elles n'aient pas besoin d'espace blanc, donc je peux simplement nuke tous les espaces blancs de ma version semi-golfée quand je veux vérifier le nombre de caractères .
Fors

3

PHP, 96 95 76 71 69 64 61 octets

Remarque: les numéros d'année doivent être remplis à 4 caractères, comme 0070.

for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn))-1||print$i;

Courez comme ceci:

echo 3385 | php -nR 'for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn))-1||print$i;';echo
> -1-2-10

Explication

Itère de -1 à -12. Créez une date en utilisant mktime, day 0(le dernier jour du mois précédent) et month 2..13. Formatez la date en tant que numéro de jour et si le résultat est 1, imprimez le numéro actuel. Le signe négatif -est utilisé comme délimiteur.

Le bogue du millénaire frappe à nouveau!

Notez qu'avec cette version, la plage 0..100est interprétée comme 1970..2069. Ce n'est pas un problème pour la plage 0..69, car les semaines ont un modèle qui se répète tous les 400 ans (146097 jours, exactement 20871 semaines), mais pour la plage 70..99, 1900 est ajouté au numéro de l'année, qui n'est pas un multiple de 400. Pour corriger ce problème JUSTE pour les numéros de 30 ans dans une plage de 10k, le moyen le plus simple est d'ajouter 400 au numéro de l'année pour empêcher l'interprétation à 2 chiffres ( +4 octets ):

for(;13+$i-=1;)date(N,mktime(0,0,0,1-$i,0,$argn+400))-1||print$i;

Tweaks

  • Un octet enregistré en utilisant !~-$ipour comparer $iavec 1( -1binaire nié est 0, logiquement nié est true; chaque autre nombre estfalse ), donc les parenthèses ne sont pas nécessaires
  • 19 octets enregistrés en utilisant la last day ofYYYY-mnotation pour créer la date
  • Enregistré 5 octets en utilisant dateet strtotimeau lieu dedate_create
  • Enregistrement de 2 octets en comptant à partir de nombres négatifs, en utilisant le signe négatif comme délimiteur de sortie (les nombres de mois négatifs n'existent pas) et également comme délimiteur dans la YYYY-mpartie de la date
  • Enregistré 5 octets en utilisant mktimeau lieu de strtotime. Revient à l'utilisation du jour 0( mktimeprend également en charge le mois 13, donc 0-13== 31-12)
  • Enregistré 3 octets en utilisant -Rpour rendre $argndisponible

mktimesupprime la nécessité de garnir l'année, n'est-ce pas?
Titus

@Titus, sharp. Eh bien, je viens de comprendre que mktimec'est contre-intuitif , car les arguments sont considérés comme l' INTal. Cela signifie que vous ne pouvez pas remplir l'année ... donc tout dans la plage 0..100est interprété comme 1970..2070. Ce n'est pas un problème pour la gamme 0..70car 400 ans ont un nombre exact de semaines (donc les calendriers répètent le modèle tous les 400 ans), mais 70..99ajoute 1900 (pas un multiple de 400!). Par conséquent, le nouveau ver. a un bug.
aross

La seule solution que je vois pour le moment est $argv[1]+400... à moins que les jours de semaine juliens et grégoriens diffèrent.
Titus

@Titus, oui. Règles disent utilisation cal grégorien
aross

3

Excel, 428 97 96 octets

Entrée en A1. Afficher des valeurs hexadécimales non séparées (janvier = 0, décembre = B)

=IF(2=WEEKDAY(DATE(A1+2000,1,31)),0,"")&CHOOSE(WEEKDAY(DATE(A1+2000,3,0)),4,19,6,"3B",8,25,"7A")

Ajout de 10 octets ("+2000") pour permettre la gestion des dates antérieures à 1990.

Sauvegardé 11 octets grâce à @ Engineer Toast .


Première tentative (428 octets), empruntant fortement à la solution de @ Adám .

=IF(2=WEEKDAY(DATE(A1,1,31)),1,"")&IF(2=WEEKDAY(EOMONTH(DATE(A1,2,1),0)),2,"")&IF(2=WEEKDAY(DATE(A1,3,31)),3,"")&IF(2=WEEKDAY(DATE(A1,4,30)),4,"")&IF(2=WEEKDAY(DATE(A1,5,31)),5,"")&IF(2=WEEKDAY(DATE(A1,6,30)),6,"")&IF(2=WEEKDAY(DATE(A1,7,31)),7,"")&IF(2=WEEKDAY(DATE(A1,8,31)),8,"")&IF(2=WEEKDAY(DATE(A1,9,30)),9,"")&IF(2=WEEKDAY(DATE(A1,10,31)),"A","")&IF(2=WEEKDAY(DATE(A1,11,30)),"B","")&IF(2=WEEKDAY(DATE(A1,12,31)),"C","")

Comment cela fonctionne-t-il des années avant 1900? Le scénario de test 297 -> Mayrevient 6avec cette formule. Ne devrait-il pas être 4? 1776donne 7Aau lieu de seulement 8pour septembre.
Ingénieur Toast

Si vous le faites fonctionner, vous pouvez probablement utiliser Date(A1,3,0)au lieu deEOMONTH(DATE(A1,2,1),0)
Engineer Toast

2

Bash + cal, 58 octets

$ cat t.sh
for A in {1..12};do cal $A $1|grep -qx .....&&echo $A;done
$ bash t.sh 2016
2
10
$

+1 - fonctionne pour BSD cal(par exemple OSX), mais surveillez les espaces de fin sur GNU cal.
Digital Trauma

2

Python 2, 94 octets

from datetime import*
lambda y:[m for m in range(1,13)if date(y+(m>11),m%12+1,1).weekday()==1]

repl.it

Une fonction sans nom, prend une année entière, affiche une liste des numéros de mois [1-12].

J'ai également essayé de battre le nombre d'octets avec arithmétique sans succès (110 octets). :

lambda y:map(lambda x,v:(23*((x+2)%13or 1)/9+y-2*(0<x<11)+(x>10)+v/4-v/100+v/400)%7==4,range(12),[y-1]+[y]*11)

Une fonction sans nom qui renvoie une liste de valeurs booléennes indiquant si les mois [janvier-décembre] se terminent un lundi


2

Java 7, 200 249 octets

import java.util.*;String c(int y){String r="";GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));c.set(1,y);c.set(2,0);for(int i=0;i++<12;c.add(2,1)){c.set(5,c.getActualMaximum(5));if(c.get(7)==2)r+=i+" ";}return r;}

En Java, GregorianCalendarc'est un mélange entre un calendrier grégorien et julien. Pour cette raison, l'année a 1donné des résultats incorrects. Changer Calendar c=Calendar.getInstance();pour GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));résoudre ce problème en forçant une utilisation du calendrier grégorien uniquement. Merci à @JonSkeet sur stackoverflow.com de m'avoir expliqué cela.

Code non testé et testé:

Essayez-le ici.

import java.util.*;
class M{
  static String c(int year){
    String r = "";
    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setGregorianChange(new Date(Long.MIN_VALUE));
    calendar.set(Calendar.YEAR, year);
    calendar.set(Calendar.MONTH, 0);
    for(int i = 0; i++ < 12; calendar.add(Calendar.MONTH, 1)){
      calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
      if(calendar.get(Calendar.DAY_OF_WEEK) == 2){
        r += i+" ";
      }
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c(1));
    System.out.println(c(297));
    System.out.println(c(1776));
    System.out.println(c(2000));
    System.out.println(c(2016));
    System.out.println(c(3385));
  }
}

Sortie:

4 12
5 
9 
1 7 
2 10 
1 2 10 

2

C # 6 C #, 171 167 135 octets

using System;
void d(int n){for(int i=0;++i<13;)if((int)new DateTime(n,i,DateTime.DaysInMonth(n,i)).DayOfWeek==1)Console.Write(i+" ");}

-32 octets grâce à Shebang

Imprimer les mois en chiffres; avec espace délimité; avec espace de fuite. Maintenant, cette réponse fonctionne également pour les versions antérieures de C #.


Ancien, 167 octets

using System;using System.Linq;
c(int n)=>string.Join(",",Enumerable.Range(1,12).Where(i=>new DateTime(n,i,DateTime.DaysInMonth(n,i)).DayOfWeek==(DayOfWeek)1));

-4 octets grâce à TimmyD

Les mois en sortie sont des nombres dans la chaîne de retour, séparés par des virgules

Non golfé

string c(int n)=>
    string.Join(",",                                        // Join them with commas
        Enumerable.Range(1,12)                              // For 1-12 inclusive
        .Where(                                             // Select only
            i=>new DateTime(n,i,DateTime.DaysInMonth(n,i)   // Get last day of that year-month
            ).DayOfWeek                                     // Get its day of week
            ==(DayOfWeek)1                              // Is Monday
        )
    )
;

@TimmyD Oui mais nécessite une distribution explicite. Réponse mise à jour
Lien Ng

LINQ est amusant mais c'est 126 octets:; void q(int y){for(int m=1;m<13;m++){if((int)new DateTime(y,m,DateTime.DaysInMonth(y,m)).DayOfWeek==1){Console.WriteLine(m);}}}) De plus, il serait plus court de lancer le DayOfWeekto intque de le intfaireDayOfWeek
Kade

@Shebang Merci. Je ne devrais vraiment pas jouer au golf sur une seule ligne --- Seul Jon Skeet peut le faire. Voyez si j'ai le temps de mettre à jour demain. Fatigué maintenant.
Link Ng

Vous pouvez le convertir en un Action<int>pour économiser quelques octets
TheLethalCoder

2

Ruby, 54 + 6 = 60 octets

λ cat monday.rb
p (1..12).select{|m|Date.new($*[0].to_i,m,-1).monday?}
λ ruby -rdate monday.rb 2016
[2, 10]

6 octets pour -rdatesur la ligne de commande pour obtenir la classe Date de la bibliothèque standard.

Explication: assez simple grâce à la grande Dateclasse du Ruby stdlib . Non seulement at - il des méthodes telles que monday?, tuesday?, etc, le constructeur prendra des nombres négatifs pour tout champ passé l' année signifie «compter ce champ arrière à partir de la fin de la période représentée par le champ précédent. $*est un raccourci pour ARGV, $*[0]est donc un moyen rapide pour obtenir le premier argument de ligne de commande.


2

PHP, 84 octets

for($m=1;$m++<14;){if(strftime('%w',strtotime($argv[1]."-$m-1"))==2)echo($m-1)." ";}

Mon premier Code Golf. C'est le PHP le plus court à ce jour sur cette question.

EDIT: ne semble pas fonctionner pour la première année. Je vais devoir comprendre pourquoi, mais pour l'instant je dois y aller.


1
Je dirais "Bienvenue chez PPCG!" mais vous êtes inscrit ici depuis plus longtemps que moi! : D Joli premier golf.
AdmBorkBork

Votre erreur est que vous créez 1-13-1 et 1-14-1 pour l'année 1 <13 est suffisant. Si vous résolvez cela, vous pouvez supprimer les parenthèses inutiles pour le moment et penser à utiliser l'opérateur ternaire
Jörg Hülsermann

Cela devrait résoudre vos problèmesfor(;$m++<12;)strftime("%w",strtotime($argv[1]+($m/12^0)."-".($m%12+1)."-1"))!=2?:print"$m ";
Jörg Hülsermann

2

R, 106 99 95 83 78 77 74 octets

g=function(x)which(format(seq(as.Date(paste0(x,-2,-1)),,'m',12)-1,"%u")<2)

La séquence des derniers jours de chaque mois est donnée par seq(as.Date(paste0(x,-2,-1)),,'m',12)-1:

  • paste0contraint -2 et -1 aux caractères. Si xc'était 2016 par exemple, paste0(x,-2,-1)donne "2016-2-1"qui est ensuite converti au 1er février 2016 par as.Date.

  • seqappliqué à un objet POSIXct ou Date est seq(from, to , by, length.out): ici ton'est pas donné, byest donné comme 'm'qui est mis en correspondance 'month'grâce à la mise en correspondance partielle, et length.outest bien sûr 12.

  • La séquence résultante est le premier jour des 12 mois commençant par février de l'année en question. -1nous donne alors le dernier jour des 12 mois commençant par janvier de l'année en question.

Cas de test:

> g(1)
[1]  4 12
> g(25)
[1] 3 6
> g(297)
[1] 5
> g(2000)
[1] 1 7
> g(2016)
[1]  2 10
> g(3385)
[1]  1  2 10
> g(9999)
[1] 5

Ancienne version à 95 octets, affichant les noms des mois au lieu de leurs seuls numéros:

g=function(x)format(S<-seq(as.Date(sprintf("%04i-02-01",x)),,'m',12)-1,"%B")[format(S,"%u")==1]

Cette réponse est tout simplement géniale. Je n'avais aucune idée d' seqavoir une méthode pour Date-objects et cela résout le problème de as.Datene pas gérer les années ci-dessus 10000dans ma réponse supprimée.
Billywob

@Billywob oui seq.Dateet seq.POSIXtsont assez impressionnants: ils peuvent même traiter des commandes telles que seq(time1, time2, by="10 min")ou seq(date1, date2, by="quarter"). Très utile pour tracer une série chronologique.
plannapus

2

Japt, 24 octets

Do1 £Ov"Ð400+U"+X e ¥2©X

Testez-le en ligne! Produit un tableau de nombres, avecfalseà la place des mois qui ne se terminent pas un lundi.

Il y avait un bug dans l'interpréteur qui ne me permettait pas d'utiliser Ðdans le corps de la fonction £. Après la correction du bogue et un autre ajout de fonctionnalité, cela fait 18 octets dans le commit actuel:

Do1@Ð400+UX e ¥2©X

1

Java, 143 129 octets

Cela utilise la nouvelle API temporelle de Java 8.

y->{String s="";for(int m=0;++m<13;)if(java.time.YearMonth.of(y,m).atEndOfMonth().getDayOfWeek().ordinal()==0)s+=m+" ";return s;}

Sortie

Notez que chaque ligne a un espace supplémentaire à la fin.

4 12 
5 
9 
1 7 
2 10 
1 2 10 

Non golfé et test

import java.time.*;
import java.util.function.*;

public class Main {
    public static void main (String[] args) {
        IntFunction<String> func = year -> {
          String result = "";
          for (int month=1; month <= 12; month++) {
            if (YearMonth.of(year, month).atEndOfMonth().getDayOfWeek().ordinal() == 0) {
              result += month + " ";
            }
          }
          return result;
        };
        System.out.println(func.apply(1));
        System.out.println(func.apply(297));
        System.out.println(func.apply(1776));
        System.out.println(func.apply(2000));
        System.out.println(func.apply(2016));
        System.out.println(func.apply(3385));
    }
}

Rasage

  1. 143 à 129 octets: utilisez DayOfWeek::ordinalpour comparer avec une constante numérique au lieu de la constante enum.
    Merci @TimmyD pour l'idée générale sinon la solution exacte! ;-)

@TimmyD malheureusement, c'est une énumération. Il a cependant une getValue()méthode qui permettrait d'économiser quelques octets.
Celos

@Celos ordinal()enregistre 1 octet de plus par rapport à getValue(), même s'il est suggéré de ne jamais l'utiliser.
Olivier Grégoire

oui, bonne réflexion. J'ai posté mon commentaire sans rafraîchir d'abord, donc je n'ai pas vu votre réponse et modifié.
Celos

1

GNU awk, 80 octets

{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}

Exemple

$ gawk '{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}' <<<2016
2
10
$
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.