Finden Sie den letzten Sonntag in jedem Monat eines bestimmten Jahres

21

In 140 Zeichen bekannte F # -Lösungen , und dies ist ein Rosetta-Code- Problem.

Erforderliches Ergebnis für stdout oder in einer Zeichenfolgenvariablen für das Eingabejahr 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

Wie es für 1900 gefordert wurde:

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

Und 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

Aufgestellt, weil Datumsangaben in den meisten Sprachen Unbeholfenheit hervorrufen. Ich hoffe, sie sehen zu können, da sie keine Date-Bibliotheken zulassen! Wenn Sie sich jedoch außerhalb der Basissprache befinden, geben Sie den Namen des Posts an (z. B. C # + Jon Skeets NodaTime).

Klarstellungen:

  • Jahresbereich 1900 bis 3015
  • Gregorianischer Kalender
  • Wenn es anders ist, was auch immer für UK / London üblich ist.
  • Ein Programm, das eine Befehlszeilenoption oder stdin verwendet, ist in Ordnung und liefert das Ergebnis stdout
  • Eine Funktion, die einen Wert für das Jahr annimmt und eine Zeichenfolge zurückgibt, ist ebenfalls in Ordnung.

Standardlücken ausgeschlossen . Wir freuen uns auf die APL-, J- und K-Lösungen und auf einige neue Date-Bibliotheken.

Phil H
quelle
@ Sp3000 - 1752 könnte besonders umständlich sein :-)
squeamish ossifrage
@ MartinBüttner: Bitte benutze Datumsbibliotheken, habe die Frage bearbeitet, um Leute zu bitten, diejenigen zu deklarieren, die sie mit der Sprache verwenden.
Phil H
1
Sie sollten den Bereich der Jahre angeben, die als Eingabe gültig sind, und Überlegungen zur Übernahme durch Gregorianiker anstellen. (Wenn der Zeitraum von Jahren einen Zeitraum vor 1930 umfasst, sollten Sie entweder angeben, dass der Gregorianische Kalender für den gesamten Zeitraum verwendet werden soll, unabhängig vom Gebietsschema, oder dass die Ausgabe je nach Gebietsschema variieren kann, oder Sie sollten ein Stichtag angeben, vor dem Der julianische Kalender sollte verwendet werden und Testfälle für die drei Jahre um die Umstellung).
Peter Taylor
1
@squeamishossifrage: Ich habe es auf 1900 und Gregorian beschränkt, weil ich lieber ein Forschungsprojekt vermeiden möchte, um die Spezifikation zu etablieren ...
Phil H
1
@Adam: Tut mir leid, dass du so lange auf eine Antwort wartest :) Ja, in der Tat.
Phil H

Antworten:

1

Dyalog APL mit cal von dfns , 19 Bytes

Besser spät als nie!

Fordert zur Eingabe des Jahres auf und gibt eine Datumsliste im Format JJJJ TT zurück .

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

Eingabeaufforderung für die numerische Eingabe und lassen Sie das das linke Argument für die

{... anonyme Funktion (siehe unten), die auf jeden von angewendet wird

⍳12 die Zahlen von 1 bis 12 (die Monate)

Die obige anonyme Funktion lautet wie folgt:

⍺⍵, Stellen Sie die linken und rechten Argumente (dh Jahr und Monat) voran

2↑ die ersten beiden Zeichen von

⊢⌿ die unterste Reihe von

cal der Kalender für

⍺⍵ linkes Argument und rechtes Argument (Jahr und Monat)

TryAPL online:

  1. Kehren Sie zu dieser Seite zurück, nachdem Sie hier zum Importieren calund den Abhängigkeiten geklickt haben .

  2. Klicken Sie hier , um die Testfälle auszuführen.

Adam
quelle
Sehr gut. Hatte auf eine APL-Bibliothek gehofft, die verstand, was die Daten bedeuten, aber cal ist vernünftig!
Phil H
@ PHILH Datum und Tage ?
Adám
1
@PhilH Es gibt auch den Datums- Namespace von MiServer.
Adám
1
@PhilH und Dyalog APLs dyadische Primitive + - < = und arbeiten mit .Net- Datumsobjekten .
Adám
7

Rubin, 91 + 6 = 97

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

Funktioniert ziemlich gut. select(&:sunday?)ist hübsch und *' 'erledigt überraschenderweise die gesamte Formatierung von selbst.

Histokrat
quelle
Schöne Tricks! Sie können drei weitere Zeichen speichern, indem Sie chunkanstelle von verwenden group_by.
Cristian Lupascu
Also kann ich, nett.
Histokrat
6

Bash 4.x + ncal, 57

Wenn Zeilenumbrüche anstelle von Leerzeichen in Ordnung sind, können wir den -nSchalter und das nachfolgende Leerzeichen aus der echoAnweisung entfernen . Und ich denke, dass es auch ohne den Shebang funktionieren wird, also habe ich das auch entfernt:

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

Ursprüngliches Skript (73 Byte):

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

Verwendung:

$ 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
$

Hinweis: Bash-Versionen vor 4.0 lassen die führenden Nullen aus den Monaten weg. Dies kann mit dem Zusatz von 5 Zeichen festgelegt werden , indem {01..12}an `seq -w 1 12)`. Außerdem kann dies tail -c-3auf einigen Systemen zu Problemen führen, bei denen die Ausgabe von ncalnachgestellte Leerzeichen enthält, mir ist dies jedoch nicht bekannt.

zimperliches Ossifrage
quelle
1
Hängt der Unterschied wirklich mit Darwin zusammen, nicht nur mit der Bash-Version? Wurde in Bash 4.0 hinzugefügt (obwohl es später einige Bugs gab). Wie auch immer, 1 Charakter kann immer noch geschont werden, wenn `…`anstelle einer guten Angewohnheit eine verwendet wird $(…).
Handarbeit
Ah, könnte sein. Darwin sagt, dass es Version 3.2.53 verwendet; Debian verwendet 4.1.5.
Squeamish Ossifrage
@manatwork PS Habe gerade deinen Kommentar zu den Back-Ticks gesehen. Guter Fang, danke!
Squeamish Ossifrage
Ich glaube nicht, dass Sie das #!/bin/bashfür das Golfen zählen müssen.
Digital Trauma
@DigitalTrauma Das ist gut. Es sieht so aus, als könnte ich auch Zeilenumbrüche anstelle von Leerzeichen verwenden. Jetzt auf 57 Bytes runter :-)
zimperliches Ossifrage
6

IBM DFSORT, 11 3 Zeilen mit 71, 72 oder 80 Zeichen

 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) 

Die beiden Antworten mit kolumnarem Ausgabeformat haben sich bewährt. Das gibt mir eine Art "Schleife", in der bei OUTFIL REPEAT = der aktuelle Datensatz so oft kopiert wird.

Eine andere Technik, um zum Wert zu gelangen, die länger zu sein scheint, aber kürzer ist, da ich keinen unbedingten Weg finden kann, um mit der 12. Platte des folgenden Jahres umzugehen IFTHEN=(WHEN=. Gewinne auf den Schaukeln (der erste Monat ist der einfachste Weg, dies zu tun) verlieren stark an den Kreisverkehren (besondere Syntaxanforderungen).

Dies verwendet eine eingebaute Funktion (alle Funktionen in DFSORT sind eingebaut), um den letzten Tag des Monats zu finden. Fügt dann einen Tag (Funktion) hinzu, um zum ersten des folgenden Monats zu gelangen, und verwendet die PREVDSUN-Funktion, um den vorherigen Sonntag zu erhalten (der wie zuvor immer der letzte Sonntag im vorherigen Monat sein wird).

Wenn das Jahr (Eingabe) in ein gültiges Datum umgewandelt wird, wird eine zweistellige laufende Nummer für den Monat verwendet, und dieser Wert wird auch für den Tag kopiert, da der Startpunkt keine Rolle spielt, solange er gültig ist, wie wir es sind nach dem letzten tag des monats anfänglich: 5,2ist kürzer als C'01'.

Hier ist das Detail:

OPTION COPY - Kopiert die Eingabedatei in die Ausgabe

OUTFIL - Damit mehrere Ausgabedateien mit unterschiedlicher Auswahl und Formatierung formatierte Berichte erstellen können. Wird INRECwegen der Verwendung von bevorzugt dem kürzeren vorgezogen REPEAT=.

REPEAT = 12 - 12 Kopien jedes Datensatzes erstellen. In diesem Beispiel kann es aufgrund der SEQNUM (im Gegensatz zur vorherigen Version) nur einen Eingabedatensatz geben.

5: - Beginnen Sie in Spalte 5 des Datensatzes.

SEQNUM, 2, ZD - Sequenznummer, beginnt standardmäßig mit einer, zwei Ziffern, "Zonendezimal" (für vorzeichenlose Zeichen, die mit dem Zeichen identisch sind).

1,8 - Byte 1 für Länge 8 zum aktuellen Speicherort kopieren (9). Dies liegt daran, dass der Y4T diese 8 sehen muss, ansonsten wird ein anderes Datumsformat verwendet.

Y4T - Datum im ccyymmdd-Format (aufgrund der 8 direkt davor).

LASTDAYM - Letzter Tag des Monats (auch möglich für Woche, Quartal und Jahr).

TOJUL = - Datumsumwandlung für Datumsfunktionen ausgeben (TOJUL ist ein Zeichen weniger als TOGREG)

9,7 - jetzt, da es 7 ist, wird Y4T CCYYDDD sein.

ADDDAYS - Fügt eine Anzahl von Tagen hinzu und passt sich automatisch an, wenn in den folgenden Monat / das folgende Jahr übergegangen wird (dies können auch ADDMONS und ADDYEARS sein).

PREVDSUN - das julianische Datum kommt herein, der vorherige Sonntag ist lokalisiert, TOGREG, um das richtige Ausgabeformat zu erhalten, mit dem Trennzeichen "-" (kann alles sein, was Sie als Trennzeichen mögen)

12X - Lücken, um das Chaos zu beseitigen, das es uns ermöglicht hat, es auf so kurze Weise zu tun

Die Ergebnisse für 2014 lauten wie folgt:

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

Es ist etwas erforderlich, um der SORT zu sagen, was zu tun ist. Es gibt keine Standardeinstellung. OPTION COPYist die kürzeste, SORT FIELDS=COPYentspricht aber länger.

Die Arbeit selbst erledigte es diesmal in OUTFIL(um die Verwendung von REPEAT zu ermöglichen). Der Arbeitscode ist wahrscheinlich einer von 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) oder 138 (70 + 68) (ohne die führenden Leerzeichen, erzwungenen Fortsetzungs- und nachfolgenden Leerzeichen).

Angesichts der Tatsache, dass der Empfänger wissen müsste, was er tut, kann ich sagen, dass der DFSORT - Code den letzten Sonntag eines jeden Monats für jedes Jahr ab 1900 auflistet (ab dem Jahr 0001), aber ich vermeide die Forschung als gut) bis 9999 (obwohl DFSORT Jahre bis 9999 unterstützt, würde die vorherige Lösung im Jahr 9999 nicht funktionieren, da das 12. Datum in das folgende Jahr fällt) kann getwittert werden.

Warum ist der Code so lang, wenn es besonders geeignete eingebaute Funktionen gibt?

Felddefinitionen sind kurzlebig. Ein Feld wird nur als eine bestimmte Position innerhalb der Daten (die ein Datensatz ist) für die sofortige Verwendung definiert. Anders ausgedrückt, Felder sind nicht als solche definiert, sondern werden für jede Verwendung und nur für die Verwendung definiert. Datumsfunktionen müssen wissen, welche (von vielen) Datumsformaten für die Quelle verwendet werden, und die Ausgabe muss in einem Datumsformat erfolgen, sodass angegeben werden muss.

Jetzt, wo wir ein julianisches Date haben ... TBC?


 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) 

Braucht welche JCL

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

Und eine Eingabedatei (eine weitere Zeile der JCL und drei Instream-Datenelemente):

//SORTIN DD *
2014 
1900 
2000 

Produziert:

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

Funktioniert tatsächlich bis zum Jahr 9999.

DFSORT ist das Mainframe-Sortierprodukt von IBM. Daten können manipuliert werden, aber da die Sortierung von entscheidender Bedeutung ist und die Sortierung häufig langwierig und umfangreich ist, verfügen die DFSORT-Steuerkarten über keine Schleifenkonstrukte. Daher können wir eine SORT nicht in eine Schleife einfügen. Macht die Dinge für Aufgaben wie Golf etwas langatmig.

Warum die Antwort posten, liegt daran, dass DFSORT eine PREVDdayFunktion hat. So ist letzter Sonntag in einem Monat einfach. Es ist der Sonntag vor (PREVDSUN) dem ersten Tag des folgenden Monats.

Es hat auch Spaß gemacht, es in einem "Operanden" (OVERLAY) zu machen, ein bisschen wie alles in einem sprintfoder ähnlichem.

Hier ist es ungolfed:

 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) 

Es ist zwar kein Missbrauch, aber es wäre nicht üblich, zu versuchen, dies alles in ein OVERLAY zu packen, und es gibt einige scheinbar unnötige Dinge, die erforderlich sind, damit alles in ein OVERLAY passt. Es gibt etwas Platz zum Golfen, aber da es höchstens eine Linie entfernen würde, bin ich nicht versucht.

Die INREC wird für jeden Datensatz verarbeitet.

Mit OVERLAY kann der Inhalt eines vorhandenen Datensatzes geändert werden. Wenn der Datensatz dabei über seine Länge hinaus verlängert wird, ist dies kein Problem.

1,4 ist das kommende Jahr. Es wird das Literal 0201 angehängt, und die nachfolgenden 1,8 wiederholen es elf Mal, um ein langes Chuck mit 96 Bytes zu erhalten.

Das 12. Jahr des erweiterten aktuellen Datensatzes wird um 1 erhöht und der Monat auf 1 (Januar) gesetzt.

Die verbleibenden 10 Monate werden in 3 bis 11 geändert.

Dann gibt es 12 in umgekehrter Reihenfolge (aufgrund von OVERLAY) dieser Art von Dingen:

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

Das n: ist eine Spaltennummer im Datensatz. Das X fügt ein Leerzeichen ein. 89,8 nimmt die Daten aus dieser Spalte / Länge, Y4T behandelt sie als CCYYMMDD-Datum, PREVDSUM berechnet den vorherigen Sonntag, TOGREG = Y4T (-) gibt sie als gregorianisches CCYY-MM-DD-Datum aus.

Weil Sie Müll bekommen, wenn sich die Quelle und das Ziel eines bestimmten Teils eines OVERLAYs zerstörerisch überlappen, ordnet sich das Endergebnis 11:X,18,120,6X)neu und maskiert ein bisschen Chaos.

Handbücher und Dokumente finden Sie unter: http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 . Enthält das 900-seitige DFSORT Application Programming Guide.

Wie bei allen IBM Produkten sind alle Handbücher kostenlos erhältlich (mit Ausnahme einer unglaublich kleinen Menge sehr teurer Handbücher, die nur eine sehr kleine Anzahl von Menschen auf der Welt zu verstehen vorgibt).

Alle DFSORT-Steuerkarten müssen mit einem Leerzeichen beginnen. Die Spalte 72 wird nur zur Fortsetzung verwendet (jedes Nicht-Leerzeichen reicht aus, aber * ist konventionell). Auf die Spalte 72 folgt ein Sequenznummernbereich, der ignoriert wird, so dass jeder Datensatz 80 Bytes umfasst.

Vielleicht noch ein paar Lösungen.

Bill Woodger
quelle
5

Bash, 63 Bytes

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

Ausgabe:

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
michael501
quelle
for i in {1..12};{ date -v30d -v${i}m -v$1y -v0w +%Y-%m-%d;}- 60 Bytes
Digitales Trauma
-vparam to dateist spezifisch für das BSD-Datum. Dies funktioniert also unter OSX, aber nicht unter den meisten Linux-Betriebssystemen - vielleicht sollte dies in der Antwort angegeben werden.
Digital Trauma
@DigitalTrauma, funktioniert auf Mac und meinem Linux.
Michael501
4

Python 2 - 189 Bytes

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),

Geben Sie das Datum über STDIN ein.

Es kann noch viel mehr Golf gespielt werden. Das Programm geht ein wenig über Bord, nur zum Spaß:

  • Keine Importe, insbesondere keine eingebauten Datumsfunktionen
  • Verwendet Zellers Kongruenz zur Berechnung der Wochentage

Anmerkungen

  • 1322 ist eine magische Nachschlagetabelle zum Bestimmen, ob ein Monat, der nicht Februar ist, 30 oder 31 Tage hat
  • zfillAufgrund des Eingabebereichs sind seit Jahren keine Eingaben erforderlich, auch keine Tage, da diese immer über 20 liegen

Python 2 - 106 Bytes

Die nicht so spaßige Lösung:

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.monthrangegibt zwei Zahlen zurück: den Wochentag, an dem der Monat beginnt ( w) und die Anzahl der Tage im Monat ( n). Die Lösung ist aufgrund eines Fehlers etwas eingängig - der zurückgegebene Wochentag beginnt bei 0 für Montag und nicht für Sonntag! Dies wird jedoch durch die Tatsache ausgeglichen, dass n1-basiert ist.

Sp3000
quelle
1
Eine sehr dumme Pyth-Antwort:$from calendar import monthrange as gt$V12AGH>QhN%"%d-%02d-%d"(QhN-H%+GH7
FryAmTheEggman
3

JavaScript (ES6) 155 145

Bearbeiten Behobene Zeitzonenprobleme Könnten kürzer sein, wenn sie rekursiv sind. Vielleicht.

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(' ')
}
edc65
quelle
Sie können verwenden new Date(y,0,++i,9). Dies schlägt auch für Schaltjahre ab 2100 fehl, da JS keine Informationen über diese Schaltjahre hat und daher für Schaltjahre ab 2100 überhaupt keine Informationen hat Feb 29.
Optimierer
@Optimizer es ist nicht JS: 2100,2200,2300 sind keine Schaltjahre. 2014 ist ein Schaltjahr und JS weiß es. Was die Verwendung von Stunde 9 betrifft, kann ich nicht verifizieren, aber ich denke, dass dies nicht funktioniert, wenn Sie sich zum Beispiel in Melbourne befinden ...
edc65
Ah .. Ich wusste nie, dass wir 3 Tage pro 400 Jahre fallen. Über die 9 - änderte ich meine Zeitzone von -1.000 (Hawaii) bis +1100 (Melbourne) und new Date(2014,0,26,9)war ein Sonntag richtig geben ISOString sowie getDay()als 0.
Optimierer
3

JavaScript, ES6, 222 219 199 Bytes

Ich habe keine JavaScript-Antwort im Rosetta-Wiki gesehen.

Auf geht's:

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(" ")}

Dadurch wird eine Funktion erstellt, Sdie eine Zeichenfolge mit der gewünschten Ausgabe zurückgibt. Die Funktion kümmert sich auch um Schaltjahre.

Aufgrund von ES6 funktioniert dies nur in einem aktuellen Firefox.

Danke an apsillers für den Tipp, der ihn auf 200 Bytes reduziert hat

Finden Sie die ungolfed-Version unten als Stack-Snippet, das Sie hier selbst ausführen können:

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())))

Optimierer
quelle
Sie können + prompt () anstelle von parseInt verwenden und einige Bytes entfernen
Jacob
@Jacob Diese Eingabeaufforderung wird nicht zur Byteanzahl hinzugefügt.
Optimierer
OIC. Ich hätte die Frage lesen sollen ...
Jacob
@apsillers Danke eine Tonne! Das Problem wurde behoben und aufgrund Ihres Trinkgeldes stark reduziert.
Optimierer
Eingabe 2100Ausgabe 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-02ist falsch.
Qwertiy
3

Rebol - 120 116 80 79 76

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


Ungolfed + einige Anmerkungen:

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
    ]
]

Beispiel für die Sonntagsberechnung in der Rebol-Konsole:

>> ; 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
draegtun
quelle
Potenzielle 87: d: 1-1-1 d / Jahr: Eingabe drucken sammeln [Wiederholung m 12 [d / Monat: m + 1 halten d - d / Wochentag]]
rgchris
@rgchris Danke Chris. Konnte weitere 7 Zeichen davon rasieren.
Draegtun
Nett!! Es ist schlecht, aber man sollte FOR nie als Abkürzung betrachten.
Rgchris
2

CJam, 122 102 Bytes

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

Dies verwendet keine Form der Datumsbibliothek. Es kann auch noch viel Golf gespielt werden, denke ich.

Teste es hier.

Martin Ender
quelle
3
Ich bin so begeistert, dass eine CJam-Antwort ausnahmsweise nicht die beste Antwort bei einer Code-Golf-Herausforderung ist. Ich kann glücklich sterben. Heute ist ein guter Tag (bis es offensichtlich auf 6 Bytes heruntergolfen hat)
Brandon
@ Brandon: Das war der Grund, warum ich dachte, dass es interessant sein würde. Ich hoffe wirklich, eine wundersame Bibliothek zu sehen, die das so einfach macht, aber bisher enttäuscht.
Phil H
1

R 128 Zeichen

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

Mit Zeilenumbrüchen:

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)))))
Plannapus
quelle
1

C # 255

Ungolfed

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

Bearbeiten: geändert, um nur den letzten Sonntag zu drucken :)

Bacchusbeale
quelle
Nicht das erforderliche Ausgabeformat. + Dies ist Code Golf
edc65
1

q, 67

{({{1<>x mod 7}-[;1]/x}')14h$1_til[13]+13h$"D"$(($)x),".01.01"}
tmartin
quelle
Gibt es dafür in q keine verwendbaren Datumsbibliotheken?
Phil H
1

"Oh nein, er schon wieder!"

Java - 259 246 Bytes

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

Ungolfed-Version:

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

Verwendung:

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

Ausgabe:

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

Noch eine andere "Lassen Sie uns eine Java-Antwort nur für Kicks setzen" Antwort. Naja. Aber zumindest, da Sie sich die Mühe gemacht haben, diesen Punkt meiner Antwort zu erreichen, werde ich versuchen, Ihnen noch mehr zu langweilen und meine Argumentation zu erklären.

Die Methode gerhält das gewünschte Jahr und erstellt für jeden Monat ein GregorianCalendarObjekt (Monate von 0 bis 11). Dann c.setlegt der erste den Wochentag als Sonntag fest und der zweite erklärt, dass wir die letzte Woche des Monats wollen - wie aus der offiziellen Dokumentation hervorgeht . Der System.out.printlnAusdruck gibt das Datum dieses Sonntags aus (wenn wir dies richtig machen, würde das Jahr wie folgt gedruckt c.get(c.YEAR), aber bei yerneuter Verwendung werden 13 Zeichen weggelassen). Der Monat muss formatiert werden, um von Januar bis September eine führende Null hinzuzufügen (und die Der Wert wird inkrementiert, da hier die Monate mit 0-11 dargestellt werden und der Tag des letzten Sonntags gedruckt wird. Und dieser Vorgang wird für die anderen elf Monate wiederholt.

Rodolfo Dias
quelle
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);}}

Mit Zeilenumbrüchen

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

Ausgabe für 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"
Darren Breen
quelle
Nicht das erforderliche Ausgabeformat
edc65
Dort behoben. Besser?
Darren Breen
0

C # 171

Funktion, die einen String zurückgibt.

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

Ungolfed

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;
}
edc65
quelle
0

C # 194

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

Ungolfed

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

Ausgabe

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
Manuel Schweigert
quelle
0

Mathematica - 171

Wird in eine anonyme Funktion eingeschlossen, wird die Zeichenfolge zurückgegeben

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

Erster Mathematica Golf. Ich denke, es könnte erheblich reduziert werden.

schelmisch
quelle
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

Könnte schlimmer sein ^^

Mein zweiter und letzter Eintrag (glaube nicht, dass ich ihn kleiner bekommen kann)

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
Dwana
quelle
0

Rubin 76

Verwendet einen Befehlszeilenparameter ruby sundays.rb 1900. Verwendet die Date-Bibliothek.

require'date';puts (1..12).map{|m|d=Date.new($*[0].to_i,m,-1);d-d.wday}*" "
steenslag
quelle