Trouvez le dernier dimanche de chaque mois d'une année donnée


21

Solutions F # connues dans 140 caractères , et c'est un problème de code Rosetta .

Résultat requis sur stdout ou dans une variable de chaîne pour l'année d'entrée 2014:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28

Comme demandé, pour 1900:

1900-01-28 1900-02-25 1900-03-25 1900-04-29 1900-05-27 1900-06-24 1900-07-29 1900-08-26 1900-09-30 1900-10-28 1900-11-25 1900-12-30

Et 2000:

2000-01-30 2000-02-27 2000-03-26 2000-04-30 2000-05-28 2000-06-25 2000-07-30 2000-08-27 2000-09-24 2000-10-29 2000-11-26 2000-12-31

Posé parce que les dates semblent faire ressortir la maladresse dans la plupart des langues. Plus que de permettre des bibliothèques de dates, j'espère les voir! Mais s'il est externe au langage de base, déclarez-le au nom du message (par exemple, C # + NodaTime de Jon Skeet).

Précisions:

  • Années 1900 à 3015
  • calendrier Grégorien
  • S'il en est autrement, tout ce qui est conventionnel pour le Royaume-Uni / Londres.
  • Un programme prenant un commutateur de ligne de commande ou stdin est très bien, produisant le résultat à stdout
  • Une fonction prenant une valeur pour l'année et renvoyant une chaîne convient également.

Échappatoires standard exclues . Dans l'attente des solutions APL, J, K et de nouvelles bibliothèques de dates.


@ Sp3000 - 1752 pourrait être particulièrement gênant :-)
squeamish ossifrage

@ MartinBüttner: Veuillez utiliser les bibliothèques de dates, avez édité la question pour demander aux gens de déclarer ceux qu'ils utilisent avec la langue.
Phil H

1
Vous devez spécifier la plage d'années qui sont des entrées valides et des considérations sur l'adoption grégorienne. (C'est-à-dire que si la plage d'années inclut des années antérieures à 1930, vous devez spécifier soit que le calendrier grégorien doit être utilisé pour toute la plage, indépendamment des paramètres régionaux; soit que la sortie peut varier selon les paramètres régionaux; soit vous devez indiquer une date limite avant laquelle le calendrier julien doit être utilisé et les cas de test pour les trois ans autour du passage à l'euro).
Peter Taylor

1
@squeamishossifrage: Je l'ai limité à 1900 et grégorien, car je préfère éviter un projet de recherche pour établir la spécification ...
Phil H

1
@ Adám: Désolé de vous avoir fait attendre si longtemps pour une réponse :) Oui en effet.
Phil H

Réponses:


1

Dyalog APL avec cal de dfns , 19 octets

Mieux vaut tard que jamais!

Invite pour l'année, retourne la liste des dates au format aaaa md .

⎕{⍺⍵,2↑⊢⌿cal⍺⍵}¨⍳12

invite pour la saisie numérique et que ce soit l'argument gauche de la

{... fonction anonyme (trouvée ci-dessous) appliquée à chacun

⍳12 les nombres de 1 à 12 (les mois)

La fonction anonyme ci-dessus est la suivante:

⍺⍵, ajouter les arguments de gauche et de droite (c'est-à-dire l'année et le mois)

2↑ les deux premiers caractères de

⊢⌿ la rangée la plus basse de

cal le calendrier pour

⍺⍵ argument de gauche et argument de droite (année et mois)

TryAPL en ligne:

  1. Revenez à cette page après avoir cliqué ici pour importer calet ses dépendances.

  2. Cliquez ici pour exécuter les cas de test.


Très bien. J'avais espéré une bibliothèque APL qui comprenne ce que signifient les dates, mais cal est raisonnable!
Phil H

@PhilH date et jours ?
11 h 51

1
@PhilH Il y a aussi l'espace de noms Dates de MiServer.
2016 à 11h53

1
@PhilH et Dyalog APL primitives dyadiques + - < = et fonctionnent avec des objets de date .Net .
2016

7

Rubis, 91 + 6 = 97

#!ruby -prdate
$_=(Date.new(y=$_.to_i)...Date.new(y+1)).select(&:sunday?).chunk(&:mon).map{|k,v|v[-1]}*' '

Ça marche assez bien. select(&:sunday?)est joli, et étonnamment, *' 'fait tout le formatage par lui-même.


Belles astuces! Vous pouvez enregistrer trois autres caractères en utilisant chunkau lieu de group_by.
Cristian Lupascu

Donc je peux, bien.
histocrate

6

Bash 4.x + ncal, 57

Si les séparateurs de nouvelle ligne sont OK au lieu d'espaces, nous pouvons supprimer le -ncommutateur et l'espace de fin de l' echoinstruction. Et je suppose que cela fonctionnera toujours sans le shebang, j'ai donc supprimé cela aussi:

for i in {01..12};{ echo "$1-$i-`ncal $i $1|tail -c-3`";}

Script d'origine (73 octets):

#!/bin/bash
for i in {01..12};{ echo -n "$1-$i-`ncal $i $1|tail -c-3` ";}

Usage:

$ bash sundays.sh 2014
2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-31
2014-09-28
2014-10-26
2014-11-30
2014-12-28
$

Remarque: les versions Bash antérieures à 4.0 omettent les zéros non significatifs des mois. Cela peut être corrigé avec l'ajout de 5 caractères en changeant {01..12}en `seq -w 1 12)`. Cela tail -c-3peut également provoquer des problèmes sur certains systèmes où la sortie de ncalinclut des espaces de fin, mais je n'en connais aucun.


1
La différence est-elle vraiment liée à Darwin, pas seulement à la version Bash? A été ajouté dans Bash 4.0 (bien qu'il y ait eu quelques bugs plus tard). Quoi qu'il en soit, 1 personnage peut toujours être épargné en utilisant `…`au lieu d'une bonne habitude $(…).
manatwork

Ah, peut-être. Darwin dit qu'il utilise la version 3.2.53; Debian utilise 4.1.5.
squeamish ossifrage

@manatwork PS Je viens de remarquer votre commentaire sur les back-ticks. Bonne prise, merci!
squeamish ossifrage

Je ne pense pas que vous ayez besoin de compter #!/bin/bashpour le golf.
Digital Trauma

@DigitalTrauma C'est bien. Il semble que je puisse aussi utiliser des sauts de ligne au lieu d'espaces. Jusqu'à 57 octets maintenant :-)
squeamish ossifrage

6

IBM DFSORT, 11 3 lignes de 71, 72 ou 80 caractères

 OPTION COPY 
 OUTFIL REPEAT=12,OVERLAY=(5:SEQNUM,2,ZD,5,2,1,8,Y4T,LASTDAYM,TOJUL=Y4T*
 ,9,7,Y4T,ADDDAYS,+1,TOJUL=Y4T,1:16,7,Y4T,PREVDSUN,TOGREG=Y4T(-),12X) 

Les deux réponses au format de sortie en colonnes ont résisté à l'épreuve du temps. Cela me donne une "boucle", en quelque sorte, dans la mesure où OUTFIL REPEAT = copie autant de fois l'enregistrement courant.

Technique différente pour arriver à la valeur, qui semble plus longue mais plus courte car je ne peux pas trouver de moyen inconditionnel pour gérer le 12e record de l'année suivante, et le rendre conditionnel signifie notamment IFTHEN=(WHEN=, deux fois et d'autres choses. Gagner sur les balançoires (le premier du mois est le moyen le plus simple de le faire) perdre beaucoup sur les ronds-points (exigences de syntaxe particulières).

Cela utilise une fonction intégrée (toutes les fonctions de DFSORT sont intégrées) pour trouver le dernier jour du mois. Ajoute ensuite un jour (fonction) pour accéder au premier du mois suivant et utilise la fonction PREVDSUN pour obtenir le dimanche précédent (qui sera toujours le dernier dimanche du mois précédent, comme précédemment).

Lorsque vous transformez l'année (saisie) en une date valide, un numéro de séquence à deux chiffres est utilisé pour le mois, et cette valeur est également copiée pour le jour, car le point de départ n'a pas d'importance tant qu'il est valide, comme nous le sommes après le dernier jour du mois initialement: 5,2est plus court que C'01'.

Voici le détail:

OPTION COPY - copie le fichier d'entrée dans la sortie

OUTFIL - pour permettre à plusieurs fichiers de sortie, avec une sélection et une mise en forme différentes, de produire des rapports formatés. Utilisé de préférence au plus court en INRECraison de l'utilisation de REPEAT=.

REPEAT = 12 - produit 12 copies de chaque enregistrement. Dans cet exemple, il ne peut y avoir qu'un seul enregistrement d'entrée (contrairement à la version précédente) en raison du SEQNUM.

5: - commencez à la colonne 5 du dossier.

SEQNUM, 2, ZD - numéro de séquence, commence par défaut à un, deux chiffres, "décimale zonée" (pour non signé, ce sera le même que le caractère).

1,8 - copiez les octets 1 de la longueur 8 vers l'emplacement actuel (9). En effet, le Y4T doit voir 8, sinon un format de date différent sera utilisé.

Y4T - date au format ccyymmdd (en raison du 8 immédiatement devant).

LASTDAYM - Dernier jour du mois (également possible de la semaine, du trimestre et de l'année).

TOJUL = - sortie date-conversion pour les fonctions de date (TOJUL est un caractère de moins que TOGREG)

9,7 - maintenant qu'il fait 7 longs, Y4T va être CCYYDDD.

ADDDAYS - ajoute un certain nombre de jours, s'ajustant automatiquement si le mois / l'année suivant (peut également être ADDMONS et ADDYEARS)

PREVDSUN - la date julienne entre en jeu, le dimanche précédent est localisé, TOGREG pour obtenir le format de sortie correct, avec le séparateur "-" (pourrait être tout ce que vous aimez comme séparateur)

12X - des blancs pour nettoyer le gâchis qui nous a permis de le faire en si peu de temps

Les résultats de ce qui précède, pour 2014, sont les suivants:

2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-31
2014-09-28
2014-10-26
2014-11-23
2014-12-28

Quelque chose est nécessaire pour dire au SORT quoi faire. Il n'y a pas de défaut. OPTION COPYest le plus court, SORT FIELDS=COPYest équivalent mais plus long.

Le travail lui-même effectué cette fois-ci OUTFIL(pour permettre l'utilisation de REPEAT). Le code de travail est sans doute l'un de 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) ou 138 (70 + 68) (à l'exclusion des blancs de début, de la poursuite forcée et des blancs de fin).

Étant donné que le récepteur devrait savoir ce qu'ils font, je pense que je peux dire que le code DFSORT pour répertorier le dernier dimanche de chaque mois pour n'importe quelle année à partir de 1900 (se déroulera à partir de l'année 0001, mais j'évite la recherche car bien) jusqu'à 9999 (bien que DFSORT prenne en charge les années jusqu'à 9999, la solution précédente ne fonctionnerait pas dans l'année 9999 puisque la 12e date va dans l'année suivante) peut être tweeté.

Pourquoi le code est-il si long, s'il existe des fonctions intégrées particulièrement adaptées?

Les définitions de champ sont éphémères. Un champ est uniquement défini comme un emplacement particulier dans les données (qui est un enregistrement) pour son utilisation immédiate. En d'autres termes, les champs ne sont pas définis en tant que tels, mais sont définis pour chaque utilisation et uniquement pour une utilisation. Les fonctions de date doivent savoir quels (parmi de nombreux) formats de date sont utilisés pour la source, et la sortie doit être dans un format de date, ce qui doit être spécifié.

Maintenant que nous avons une date julienne ... à confirmer?


 OPTION COPY 
 INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8*
 ,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4,14:C'3',22:C'4',30:C'5',38:C'6',*
 46:C'7',54:C'8',62:C'9',69:C'10',77:C'11',85:C'12',127:X,89,8,Y4T,PREV*
 DSUN,TOGREG=Y4T(-),116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-),105:X,73,8,Y4*
 T,PREVDSUN,TOGREG=Y4T(-),94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-),83:X,57,*
 8,Y4T,PREVDSUN,TOGREG=Y4T(-),72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-),61:X*
 ,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-),50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-),*
 39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-),28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T*
 (-),17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-),1:1,8,Y4T,PREVDSUN,TOGREG=Y4T*
 (-),11:X,18,120,6X) 

En a besoin JCL

//LASTSUNG EXEC PGM=SORT 
//SYSOUT   DD SYSOUT=* 
//SORTOUT  DD SYSOUT=* 
//SYSIN    DD * 

Et un fichier d'entrée (une autre ligne de JCL et trois éléments de données instream):

//SORTIN DD *
2014 
1900 
2000 

Produit:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28
1900-01-28 1900-02-25 1900-03-25 1900-04-29 1900-05-27 1900-06-24 1900-07-29 1900-08-26 1900-09-30 1900-10-28 1900-11-25 1900-12-30
2000-01-30 2000-02-27 2000-03-26 2000-04-30 2000-05-28 2000-06-25 2000-07-30 2000-08-27 2000-09-24 2000-10-29 2000-11-26 2000-12-31

Fonctionnera réellement jusqu'à l'année 9999.

DFSORT est le produit de tri IBM Mainframe. Les données peuvent être manipulées, mais comme le tri est essentiel et que les tris sont souvent volumineux et de longue durée, les cartes de contrôle DFSORT n'ont pas de constructions en boucle, donc nous ne pouvons pas mettre un SORT dans une boucle. Rend les choses un peu longues pour des tâches comme le golf.

Pourquoi publier la réponse, c'est parce que DFSORT a une PREVDdayfonction. Donc, dimanche dernier d'un mois est facile. C'est le dimanche précédent (PREVDSUN) jusqu'au premier jour du mois suivant.

C'était aussi amusant de le faire dans un "opérande" (OVERLAY), un peu comme tout faire dans sprintfou similaire.

Ici, il n'est pas golfé:

 OPTION COPY 

 INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8, 
         1,8,1,8,1,8,1,8, 
         1,8,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4, 
         14:C'3',22:C'4',30:C'5',38:C'6',46:C'7',54:C'8',
         62:C'9',69:C'10',77:C'11',85:C'12', 
        127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
        116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
        105:X,73,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         83:X,57,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         61:X,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
          1:1,8,Y4T,PREVDSUN,TOGREG=Y4T(-), 
         11:X,18,120,6X) 

Bien qu'il ne soit pas tout à fait abusif, il ne serait pas habituel de tenter de regrouper tout cela en un seul OVERLAY, et il y a des choses apparemment inutiles qui sont nécessaires pour que tout puisse aller dans un OVERLAY. Il y a de la place pour le golf, mais comme cela ne supprimerait qu'une seule ligne au maximum, je ne suis pas tenté.

L'INREC est traité pour chaque enregistrement.

OVERLAY permet de modifier le contenu d'un enregistrement existant. Si l'enregistrement est étendu au-delà de sa longueur dans le processus, ce n'est pas un problème.

1,4 est l'année qui vient. Il a un littéral de 0201, puis les 1,8 successifs le répètent 11 fois pour donner un long mandrin de 96 octets,

La douzième année du record actuel étendu est ajoutée à 1 et son mois est passé à 1 (janvier).

Les 10 mois restants sont passés de 3 à 11.

Ensuite, il y a 12, dans l'ordre inverse (en raison de la superposition) de ce type de chose:

127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-),

Le n: est un numéro de colonne sur l'enregistrement. Le X insère un blanc. 89,8 prend les données de cette colonne / longueur, Y4T les traite comme une date CCYYMMDD, PREVDSUM fonctionne le dimanche précédent, TOGREG = Y4T (-) les affiche comme une date grégorienne CCYY-MM-DD.

Parce que vous obtenez des ordures si la source et la cible d'une partie particulière d'un OVERLAY se chevauchent de manière destructrice, la dernière 11:X,18,120,6X)réorganisation et masque un peu le désordre.

Les manuels et les documents peuvent être consultés à l' adresse : http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 et incluent le guide de programmation d'application DFSORT de 900+ pages.

Comme avec tous les produits IBM, tous les manuels sont disponibles gratuitement (à l'exception d'une quantité atrocement petite de très chers que seul un très petit nombre de personnes dans le monde prétendraient même comprendre).

Toutes les cartes de contrôle DFSORT doivent commencer par un blanc. La colonne 72 est uniquement utilisée pour la continuation (tout élément non vide fera l'affaire, mais * est conventionnel). La colonne 72 est suivie d'une zone de numéro de séquence qui est ignorée, ce qui fait que chaque enregistrement 80 octets.

Un autre couple de solutions à venir, peut-être.


5

Bash, 63 octets

for i in {01..12};{  date -v30d -v${i}m  -v2014y  -vsun +%Y-%m-%d;}

Production:

2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-24
2014-09-28
2014-10-26 
2014-11-30
2014-12-28

for i in {1..12};{ date -v30d -v${i}m -v$1y -v0w +%Y-%m-%d;}- 60 octets
Digital Trauma

-vparam to dateest spécifique à la date BSD. Cela fonctionne donc sur OSX, mais pas sur la plupart des Linux - cela devrait peut-être être indiqué dans la réponse.
Digital Trauma

@DigitalTrauma, fonctionne sur mac et mon Linux.
michael501

4

Python 2 - 189 octets

y=input()
for m in range(12):
 d=[31-(1322>>m&1),28+(y%400<1or 1>y%4<y%100)][m==1];Y=y-(m<2);Z=Y%100;C=Y/100
 while(d+13*((m-2)%12+4)/5+Z+Z/4+C/4-2*C)%7-1:d-=1
 print"%d-%02d-%d"%(y,m+1,d),

Entrez la date via STDIN.

Encore beaucoup de golf qui peut être fait. Le programme va un peu à la mer, juste pour le plaisir:

  • Aucune importation, en particulier n'utilisant aucune fonction de date intégrée
  • Utilise la congruence de Zeller pour calculer les jours de la semaine

Remarques

  • 1322 est une table de recherche magique pour déterminer si un mois non février a 30 ou 31 jours
  • Aucun zfilln'est nécessaire pendant des années en raison de la plage d'entrée, ni de jours car ils seront toujours supérieurs à 20

Python 2 - 106 octets

La solution pas aussi amusante:

from calendar import*
y=input();m=1
while m<13:w,n=monthrange(y,m);print"%d-%02d-%d"%(y,m,n-(n+w)%7),;m+=1

calendar.monthrangerenvoie deux nombres: le jour de la semaine où le mois commence le ( w) et le nombre de jours du mois ( n). La solution est un peu contre-intuitive en raison d'une capture - le jour de la semaine retourné commence à 0 pour lundi , pas dimanche! Cependant, cela est compensé par le fait qu'il nest basé sur 1.


1
Une réponse Pyth très stupide:$from calendar import monthrange as gt$V12AGH>QhN%"%d-%02d-%d"(QhN-H%+GH7
FryAmTheEggman

3

JavaScript (ES6) 155 145

Modifier les problèmes de fuseau horaire fixe Peut être plus court s'il est récursif. Peut être.

F=y=>{
  for(n=i=o=[];!o[11];)
    d=new Date(Date.UTC(y,0,++i)),m=d.getMonth(),
    d.getDay()||(m!=n&&o.push(p.toISOString().slice(0,10)),p=d,n=m);
  return o.join(' ')
}

Vous pouvez utiliser new Date(y,0,++i,9). En outre, cela échoue pour les années bissextiles 2100 et supérieures, car JS ne dispose pas d'informations sur ces années bissextiles et n'a donc pas Feb 29du tout les années bissextiles pour 2100 et supérieures.
Optimizer

@Optimizer ce n'est pas JS: 2100,2200,2300 ne sont pas des années bissextiles. 2014 est une année bissextile et JS le sait. Quant à l'utilisation de l'heure 9, je ne peux pas vérifier mais je pense que cela ne fonctionne pas si vous êtes par exemple à Melbourne ...
edc65

Ah .. Je ne savais pas que nous perdions 3 jours par 400 ans. À propos du 9 - J'ai changé mon fuseau horaire de -1000 (Hawaï) à +1100 (Melbourne) et j'étais new Date(2014,0,26,9)un dimanche donnant une ISOchaîne correcte ainsi getDay()que 0.
Optimizer

3

JavaScript, ES6, 222 219 199 octets

Je n'ai vu aucune réponse JavaScript dans le wiki rosetta.

Et c'est parti:

S=Y=>{for(l=[],p=new Date(Y,i=0);i<365+!(Y%4);)if(!(d=new Date(Y,0,++i,9)).getDay()){p.getMonth()-d.getMonth()&&l.push(p);p=new Date(d)}return[...l,p].map(x=>x.toISOString().split("T")[0]).join(" ")}

Cela crée une fonction Squi renvoie une chaîne avec la sortie souhaitée. la fonction s'occupe également des années bissextiles.

En raison d'ES6, cela ne fonctionne que dans un dernier Firefox.

Merci à apsillers pour la pointe qui l'a réduit à 200 octets

Trouvez la version non golfée ci-dessous sous forme d'extrait de pile que vous pouvez exécuter ici même:

S=Y=>{
  for(l=[],p=new Date(Y,i=0);i<365+!(Y%4);)
    if(!(d=new Date(Y,0,++i,9)).getDay()){
      p.getMonth()-d.getMonth()&&l.push(p);
      p=new Date(d)
    }
  return[...l,p].map(x=>x.toISOString().split("T")[0]).join(" ")
}

alert(S(parseInt(prompt())))


Vous pouvez utiliser + prompt () plutôt que parseInt et raser certains octets
Jacob

@Jacob Cette invite n'est pas ajoutée au nombre d'octets.
Optimizer

OCI. J'aurais dû lire la question ...
Jacob

@apsillers Merci une tonne! Correction du problème et réduction importante en fonction de votre conseil.
Optimizer

La 2100sortie d' entrée 2100-01-31 2100-02-28 2100-03-28 2100-04-25 2100-05-30 2100-06-27 2100-07-25 2100-08-29 2100-09-26 2100-10-31 2100-11-28 2100-12-26 2101-01-02est incorrecte.
Qwertiy

3

Rebol - 120116 80 79 76

d: do join"1-1-"input print collect[for m 2 13 1[d/2: m keep d - d/weekday]]


Non golfé + quelques annotations:

d: do join "1-1-" input         ;; golfy way to create Rebol date! datatype 1-Jan-(year)

print collect [
    for m 2 13 1 [              ;; loop thru months 2 to 13!
        d/2: m                  ;; move to (1st of) next month
        keep d - d/weekday      ;; collect/keep last sunday of month
    ]
]

Exemple de calcul du dimanche dans la console Rebol:

>> ; get last sunday of Jan 2014

>> d: 1-1-2014
== 1-Jan-2014

>> d/month: d/month + 1
== 2

>> d
== 1-Feb-2014

>> d/weekday
== 6

>> d - d/weekday
== 26-Jan-2014

>> ; above is last sunday of Jan 2014
>> ; and when pass end of year (ie. month 13!)

>> d/month: 13
== 13

>> d
== 1-Jan-2015

Potentiel 87: d: 1-1-1 j / an: la collecte des impressions saisies [répéter m 12 [j / mois: m + 1 garder j - j / jour de la semaine]]
rgchris

@rgchris Merci Chris. A pu en raser 7 autres caractères.
draegtun

Agréable!! C'est mauvais, mais ne pensez jamais vraiment à FOR comme étant un raccourci.
rgchris

2

CJam, 122 102 octets

30li:X400%){[1387Yb30f+~28I!I4%!I100%e&|g+\]W%{\_2$>7*-\7%7\m1$+}/}fI;]12/W=12,{101+s1>}%]z{X+W%'-*S}/

Cela n'utilise aucune forme de bibliothèque de dates. On peut aussi encore beaucoup jouer au golf, je pense.

Testez-le ici.


3
Je suis tellement spectaculaire que la réponse CJam n'est pas la meilleure réponse dans un défi de code-golf pour une fois. Je peux mourir heureux .. Aujourd'hui est une bonne journée (jusqu'à ce qu'il soit joué à 6 octets, évidemment)
Brandon

@Brandon: C'est le genre de raison pour laquelle je pensais que ce serait intéressant. Espérant vraiment voir une merveilleuse bibliothèque qui rend cela facile, mais déçu jusqu'à présent.
Phil H

1

R, 128 caractères

P=paste;f=format;a=strptime(P(1:366,scan()),"%j %Y");cat(sort(sapply(split(a,f(a,"%B")),function(x)P(tail(x[f(x,"%u")==7],1)))))

Avec des sauts de ligne:

P=paste
f=format
a=strptime(P(1:366,scan()),"%j %Y")
cat(sort(sapply(split(a,f(a,"%B")),function(x)P(tail(x[f(x,"%u")==7],1)))))

1

C # 255

Non golfé

static void Main(string[] a)
    {
        int y = Int32.Parse(Console.ReadLine());
        DateTime d = new DateTime(y, 1, 1);
        while (d.Year == y)
        {
            if (d.DayOfWeek == DayOfWeek.Sunday && d.Day>(DateTime.DaysInMonth(y,d.Month)-7))
                Console.WriteLine(d.ToShortDateString());
            d = d.AddDays(1);
        }
        Console.ReadKey();
    }

Edit: modifié pour n'imprimer que le dernier dimanche :)


Pas le format de sortie requis. + C'est le code golf
edc65

1

q, 67

{({{1<>x mod 7}-[;1]/x}')14h$1_til[13]+13h$"D"$(($)x),".01.01"}

N'y a-t-il pas de bibliothèques de dates utilisables pour cela dans q?
Phil H

1

"Oh, non, encore lui!"

Java - 259 246 octets

void g(int y){for(int i=;i<12;i++){GregorianCalendar c=new GregorianCalendar(y,i,0);c.set(c.DAY_OF_WEEK,c.SUNDAY);c.set(c.DAY_OF_WEEK_IN_MONTH,-1);System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");}}

Version non golfée:

void g(int y){
    for (int i = 0; i < 12;i++) {
        GregorianCalendar c = new GregorianCalendar(y, i, 0);
        c.set(c.DAY_OF_WEEK, c.SUNDAY);
        c.set(c.DAY_OF_WEEK_IN_MONTH, -1);
        System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");
    }
}

Usage:

import java.util.GregorianCalendar;
import java.util.Scanner;

public class LastSundayInYear {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Year?");
        int year = scanner.nextInt();
        LastSundayInYear sunday = new LastSundayInYear();
        sunday.g(year); 
    }

    void g(int y){
        for (int i = -1; ++i < 12;) {
            GregorianCalendar c = new GregorianCalendar(y, i, 0);
            c.set(c.DAY_OF_WEEK, c.SUNDAY);
            c.set(c.DAY_OF_WEEK_IN_MONTH, -1);
            System.out.print(y+"-"+String.format("%02d",(c.get(c.MONTH)+1))+"-"+(c.get(c.DAY_OF_MONTH))+" ");
        }
    }
}

Production:

2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28

Encore une autre réponse "mettons une réponse Java juste pour les coups de pied". Tant pis. Mais, au moins, puisque vous avez pris la peine d'arriver à ce point de ma réponse, je vais essayer de vous ennuyer un peu plus et d'expliquer mon raisonnement.

La méthode greçoit l'année souhaitée et crée pour chaque mois un GregorianCalendarobjet (les mois vont de 0 à 11). Ensuite, le premier c.setdéfinit le jour de la semaine comme un dimanche et le second déclare que nous voulons la dernière semaine du mois - comme indiqué sur la documentation officielle . Les System.out.printlnimpressions de la date de ce dimanche (si nous faisions cela correctement, l'année serait imprimée comme c.get(c.YEAR), mais en utilisant à ynouveau rase 13 caractères), le mois doit être formaté pour ajouter un zéro de tête de janvier à septembre (et le la valeur est incrémentée car, eh bien, les mois ici sont représentés 0-11) et le jour du dernier dimanche est imprimé. Et cette procédure est répétée pour les onze autres mois.


0

C #, 212 , 237

string x(int y){var s="";var t="";var d=new DateTime(y,1,1);for(;;){if(d.Year!=y){return s;}t=(d.DayOfWeek==DayOfWeek.Sunday)?t=string.Format("{0}-{1}-{2} ",d.Year,d.Month,d.Day):t;s=(d.AddDays(1).Month!=d.Month)?s+=t:s;d=d.AddDays(1);}}

Avec des sauts de ligne

string x(int y)
    {
        var s = "";
        var t = "";
        var d = new DateTime(y,1,1);
        for (;;)
        {
            if (d.Year != y) {
                return s;
            }
            t = (d.DayOfWeek == DayOfWeek.Sunday) ? t = string.Format("{0}-{1}-{2} ", d.Year, d.Month, d.Day) : t;
            s=(d.AddDays(1).Month!=d.Month)?s+=t:s;
            d=d.AddDays(1);
        }
    }

Sortie pour 2014

"2015-1-25 2015-2-22 2015-3-29 2015-4-26 2015-5-31 2015-6-28 2015-7-26 2015-8-30 2015-9-27 2015-10-25 2015-11-29 2015-12-27"

Pas le format de sortie requis
edc65

Là, fixe. Mieux?
Darren Breen

0

C # 171

Fonction renvoyant une chaîne.

string S(int y){var r="";for(int m=1;m<13;++m){var d=new System.DateTime(y,1,1).AddMonths(m).AddDays(-1);r+=y+string.Format("-{0:00}-{1} ",m,d.Day-d.DayOfWeek);}return r;}

Non golfé

string S(int y)
{
    var r="";
    for (int m=1;m<13;++m)
    {
        var d = new System.DateTime(y, 1, 1).AddMonths(m).AddDays(-1);
        r += y + string.Format("-{0:00}-{1} ", m, d.Day - d.DayOfWeek);
    }
    return r;
}

0

C # 194

en utilisant Linq:

string d(int y){return string.Join(" ",Enumerable.Range(1,12).Select(m=>new DateTime(y,m,DateTime.DaysInMonth(y,m))).Select(d=>d.AddDays(-(int)d.DayOfWeek)).Select(d=>d.ToString("yyy-MM-dd")));}

Non golfé

string d(int y)
{
    return string.Join(" ",Enumerable.Range(1,12)
        .Select(m => new DateTime(y, m, DateTime.DaysInMonth(y, m)))
        .Select(d => d.AddDays(-(int)d.DayOfWeek))
        .Select(d => d.ToString("yyy-MM-dd")));
}

Production

2013-01-27 2013-02-24 2013-03-31 2013-04-28 2013-05-26 2013-06-30 2013-07-28 2013-08-25 2013-09-29 2013-10-27 2013-11-24 2013-12-29

0

Mathematica - 171

Enveloppé dans une fonction anonyme, retourne la chaîne

StringJoin[Last@#~DateString~{"Year","-","Month","-","Day"," "}&/@GatherBy[Select[DateRange[DateObject[{#}],DateObject[{#+1}]],DayName@#==Sunday&],DateValue[#,"Month"]&]]&

Premier golf mathématique. J'ai l'impression que cela pourrait être considérablement réduit.


0

VB-192

Function z(y)
For i = 1 To 11
a = 0
s = IIf(i <> 11, DateSerial(y, i + 1, 1), DateSerial(y + 1, 1, 1))
While Weekday(s - a) <> 1
a = a + 1
Wend
r = r + Str(s - a) + " "
Next
z = r
End Function

Ça pourrait être pire ^^

Ma deuxième et dernière entrée (je ne pense pas que je puisse la réduire)

142

Function z(y)
Dim m(12)
For i = 1 To 366
s = DateSerial(y, 1, 1) + i
If Weekday(s) = 1 Then m(Month(s)) = s
Next
z = Join(m, " ")
End Function

0

Rubis 76

Utilise un paramètre de ligne de commande ruby sundays.rb 1900. Utilise la bibliothèque de dates.

require'date';puts (1..12).map{|m|d=Date.new($*[0].to_i,m,-1);d-d.wday}*" "
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.