Znajdź ostatnią niedzielę w każdym miesiącu danego roku

21

Rozwiązania F # znane w 140 znakach , a to jest problem z kodem Rosetta .

Wymagany wynik na stdout lub w zmiennej łańcuchowej dla roku wejściowego 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

Zgodnie z żądaniem, w 1900 r .:

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

I 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

Jest to spowodowane tym, że daty wydają się nieprzyjemne w większości języków. Bardziej niż zezwalanie na biblioteki dat, mam nadzieję je zobaczyć! Ale jeśli nie jest to język podstawowy, zadeklaruj w nazwie posta (np. C # + Jon Skeet's NodaTime).

Wyjaśnienia:

  • Zakres roku od 1900 do 3015
  • kalendarz gregoriański
  • Jeśli ma to inne znaczenie, cokolwiek jest konwencjonalne dla Wielkiej Brytanii / Londynu.
  • Program przyjmujący przełącznik wiersza polecenia lub standardowe wejście jest w porządku, co daje wynik na standardowe wyjście
  • Funkcja pobierająca wartość dla roku i zwracająca ciąg znaków jest również w porządku.

Nie dotyczy standardowych luk . Czekamy na rozwiązania APL, J, K i widzimy nowe biblioteki dat.

Phil H.
źródło
@ Sp3000 - 1752 może być szczególnie niezręczny :-)
squeamish ossifrage
@ MartinBüttner: Proszę korzystać z bibliotek dat, zredagowali pytanie, aby poprosić ludzi o zadeklarowanie tych, których używają w danym języku.
Phil H
1
Powinieneś określić przedział lat, które są prawidłowymi danymi wejściowymi, oraz uwagi na temat adopcji gregoriańskiej. (Tj. Jeśli zakres lat obejmuje jakieś przed 1930 r., Należy określić, że kalendarz gregoriański powinien być stosowany dla całego zakresu, niezależnie od ustawień regionalnych; lub że wyniki mogą się różnić w zależności od ustawień regionalnych; lub należy podać datę graniczną, przed którą należy użyć kalendarza juliańskiego i przypadków testowych na trzy lata po przejściu na euro).
Peter Taylor
1
@squeamishossifrage: Ograniczyłem go do 1900 i Gregoriańskiego, ponieważ wolałbym uniknąć projektu badawczego w celu ustalenia specyfikacji ...
Phil H
1
@ Adám: Przepraszam, że tak długo czekałeś na odpowiedź :) Tak, rzeczywiście.
Phil H

Odpowiedzi:

1

Dyalog APL z cal z dfns , 19 bajtów

Lepiej późno niż wcale!

Monituje o rok, zwraca listę dat w formacie rrrr md .

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

monit o wprowadzenie danych liczbowych i niech będzie to lewy argument do

{... anonimowa funkcja (znaleziona poniżej) zastosowana do każdego z nich

⍳12 liczby od 1 do 12 (miesiące)

Powyższa anonimowa funkcja wygląda następująco:

⍺⍵, wstaw lewy i prawy argument (tj. rok i miesiąc) do

2↑ pierwsze dwie postacie

⊢⌿ najniższy wiersz

cal kalendarz dla

⍺⍵ lewy argument i prawy argument (rok i miesiąc)

TryAPL online:

  1. Wróć do tej strony po kliknięciu tutaj, aby zaimportować cali jego zależności.

  2. Kliknij tutaj, aby uruchomić przypadki testowe.

Adám
źródło
Bardzo dobre. Miałem nadzieję na bibliotekę APL, która rozumie, co oznaczają daty, ale cal jest rozsądny!
Phil H
@PhilH data i dni ?
Adám
1
@PhilH Istnieje również przestrzeń nazw Dates od MiServer.
Adám
1
@PhilH And Dyalog Pradymiczne prymitywy APL + - < = i praca z obiektami daty .Net .
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]}*' '

Działa całkiem dobrze. select(&:sunday?)jest ładna i, co zaskakujące, *' 'sama formatuje.

histocrat
źródło
Niezłe sztuczki! Możesz zapisać jeszcze trzy znaki, używając chunkzamiast group_by.
Cristian Lupascu
Więc mogę, miło.
histocrat
6

Bash 4.x + ncal, 57

Jeśli separatory nowego wiersza są w porządku zamiast spacji, możemy usunąć -nprzełącznik i końcowe spacje z echoinstrukcji. Wydaje mi się, że nadal będzie działać bez shebang, więc też to usunąłem:

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

Oryginalny skrypt (73 bajty):

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

Stosowanie:

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

Uwaga: wersje Bash wcześniejsze niż 4.0 pomijają wiodące zera z miesięcy. Można to naprawić dodając 5 znaków, zmieniając {01..12}na `seq -w 1 12)`. Ponadto, tail -c-3może powodować problemy w niektórych systemach, gdzie wyjście ncalzawiera spacje, ale nie jestem świadomy, że każdy zrobić.

piskliwy kostuch
źródło
1
Czy różnica naprawdę dotyczy Darwina, a nie tylko wersji Bash? Został dodany w Bash 4.0 (choć było w nim trochę błędów). W każdym razie można oszczędzić 1 postać, używając `…`dobrego nawyku $(…).
manatwork
Ach, może być. Darwin mówi, że używa wersji 3.2.53; Debian używa 4.1.5.
piskliwy kostek kostny
@manatwork PS Właśnie zauważyłem twój komentarz dotyczący tyknięć. Dobry chwyt, dzięki!
piskliwy kostek kostny
Nie sądzę, że musisz liczyć #!/bin/bashdo celów golfa.
Cyfrowy uraz
@DigitalTrauma To dobrze. Wygląda na to, że mogę również używać podziałów linii zamiast spacji. Teraz do 57 bajtów :-)
piskliwy ossifrage
6

IBM DFSORT, 11 3 wiersze po 71, 72 lub 80 znaków

 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) 

Dwie odpowiedzi z kolumnowym formatem wyjściowym przetrwały próbę czasu. To daje mi coś w rodzaju „pętli” w OUTFIL REPEAT = tyle razy kopiuje bieżący rekord.

Inna technika, aby dojść do wartości, która wydaje się dłuższa, ale krótsza, ponieważ nie mogę wypracować żadnego bezwarunkowego sposobu poradzenia sobie z 12. rekordem z następnego roku, a uczynienie go warunkowym oznacza włączenie IFTHEN=(WHEN=, dwa razy i kilka innych rzeczy. Zyskaj na huśtawkach (pierwszy miesiąc jest najprostszym sposobem, aby to zrobić) mocno stracić na rondach (szczególne wymagania dotyczące składni).

Używa wbudowanej funkcji (wszystkie funkcje w DFSORT są wbudowane), aby znaleźć ostatni dzień miesiąca. Następnie dodaje jeden dzień (funkcja), aby przejść do pierwszego następnego miesiąca, i używa funkcji PREVDSUN, aby uzyskać poprzednią niedzielę (która zawsze będzie ostatnią niedzielą poprzedniego miesiąca, jak poprzednio).

Podczas przekształcania roku (danych wejściowych) w prawidłową datę, dla miesiąca używany jest dwucyfrowy numer sekwencyjny, a ta wartość jest również kopiowana dla danego dnia, ponieważ punkt początkowy nie ma znaczenia tak długo, jak jest ważny, ponieważ jesteśmy po ostatnim dniu miesiąca początkowo: 5,2jest krótszy niż C'01'.

Oto szczegół:

OPCJA KOPIUJ - skopiuj plik wejściowy do wyjścia

OUTFIL - aby zezwolić na wiele plików wyjściowych, z różnym wyborem i formatowaniem, tworzyć sformatowane raporty. Używany zamiast krótszego INRECze względu na użycie REPEAT=.

REPEAT = 12 - wyprodukuj 12 kopii każdego rekordu. W tym przykładzie może istnieć tylko jeden rekord wejściowy (w przeciwieństwie do poprzedniej wersji) z powodu SEQNUM.

5: - zacznij od kolumny 5 w rekordzie.

SEQNUM, 2, ZD - numer porządkowy, domyślnie zaczyna się od jednej, dwóch cyfr, „strefy dziesiętnej” (w przypadku znaku bez znaku, który będzie taki sam jak znak).

1,8 - skopiuj bajty 1 o długości 8 do bieżącej lokalizacji (9). Wynika to z faktu, że Y4T musi zobaczyć, że 8, w przeciwnym razie zostanie użyty inny format daty.

Y4T - data w formacie ccyymmdd (ze względu na 8 bezpośrednio przed nim).

LASTDAYM - Ostatni dzień miesiąca (możliwy również w tygodniu, kwartale i roku).

TOJUL = - wyjściowa konwersja daty dla funkcji daty (TOJUL jest o jeden znak mniejszy niż TOGREG)

9,7 - teraz, gdy ma 7 lat, Y4T będzie CCYYDDD.

ADDDAYS - dodaje liczbę dni, dostosowując się automatycznie, jeśli przejdzie do następnego miesiąca / roku (mogą to być również ADDMONS i ADDYEARS)

PREVDSUN - nadchodzi data juliańska, znajduje się poprzednia niedziela, TOGREG, aby uzyskać prawidłowy format wyjściowy, z separatorem „-” (może być czymkolwiek, co lubisz jako separatorem)

12X - puste miejsca, aby usunąć bałagan, który pozwolił nam to zrobić w tak krótkim czasie

Dane wyjściowe z powyższego na 2014 r. Wynoszą:

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

Potrzebne jest coś, aby powiedzieć SORT, co ma robić. Nie ma wartości domyślnej. OPTION COPYjest najkrótszy, SORT FIELDS=COPYjest równoważny, ale dłuższy.

Praca, którą wykonał tym razem OUTFIL(aby umożliwić użycie REPEAT). Kod roboczy to prawdopodobnie dowolny ze 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) lub 138 (70 + 68) (z wyłączeniem wiodących odstępów, wymuszonej kontynuacji i końcowych odstępów).

Biorąc pod uwagę, że odbiorca musiałby wiedzieć, co robią, myślę, że mogę powiedzieć, że kod DFSORT wymienia ostatnią niedzielę każdego miesiąca dla każdego roku od 1900 roku (będzie działał od roku 0001, ale unikam badań, ponieważ cóż) do 9999 (chociaż DFSORT obsługuje lata do 9999, poprzednie rozwiązanie nie działałoby w roku 9999, ponieważ 12 data przypada na rok następny) można opublikować na Twitterze.

Dlaczego kod jest tak długi, jeśli istnieją szczególnie trafne funkcje wbudowane?

Definicje pól są efemeryczne. Pole jest zdefiniowane jako określona lokalizacja w danych (która jest rekordem) do natychmiastowego użycia. Innymi słowy, pola nie są zdefiniowane jako takie, ale są zdefiniowane dla każdego zastosowania i tylko do użytku. Funkcje daty muszą wiedzieć, które (spośród wielu) formatów daty są używane dla źródła, a dane wyjściowe muszą być w formacie daty, więc należy to określić.

Teraz, kiedy mamy randkę juliańską .... 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) 

Potrzebuje trochę JCL

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

I plik wejściowy (inny wiersz JCL i trzy elementy danych instream):

//SORTIN DD *
2014 
1900 
2000 

Produkuje:

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

Będzie działał do 9999 roku.

DFSORT to produkt IBM do sortowania komputerów mainframe. Danymi można manipulować, ale ponieważ sortowanie jest kluczowe, a sortowanie jest często duże i długotrwałe, karty kontrolne DFSORT nie mają konstrukcji zapętlonych, więc nie możemy umieścić SORT w pętli. Sprawia, że ​​rzeczy takie jak Golf są nieco zbyt skomplikowane.

Dlaczego publikować odpowiedź, ponieważ DFSORT ma PREVDdayfunkcję. Tak więc ostatnia niedziela w miesiącu jest łatwa. Jest to poprzednia niedziela (PREVDSUN) do pierwszego dnia następnego miesiąca.

Fajnie było też robić to w jednym „operandzie” (OVERLAY), trochę tak, jakbyś robił to wszystko wewnątrz sprintflub podobnie.

Tutaj nie jest golfem:

 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) 

Chociaż nie jest to do końca nadużycie, nie byłoby w zwyczaju próbować wtłoczyć to wszystko w jedną OVERLAY, a jest kilka pozornie niepotrzebnych rzeczy, które są potrzebne, aby wszystko mogło przejść w jedną OVERLAY. Jest trochę miejsca na grę w golfa, ale ponieważ usunęłoby to co najwyżej jedną linię, nie jestem kuszony.

INREC jest przetwarzany dla każdego rekordu.

OVERLAY pozwala na zmianę treści istniejącego rekordu. Jeśli rekord zostanie przedłużony poza jego długość, nie stanowi to problemu.

Nadchodzi rok 1,4. Ma dosłownie 0201, a następnie kolejne 1,8 s powtarzają je 11 razy, aby dać jeden długi uchwyt 96 bajtów,

12. rok w rozszerzonym bieżącym rekordzie zostaje dodany do 1, a miesiąc do 1 (styczeń).

Pozostałe 10 miesięcy zmienia się na 3 do 11.

Następnie jest 12, w odwrotnej kolejności (z powodu OVERLAY) tego typu rzeczy:

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

N: jest numerem kolumny w rekordzie. X wstawia spację. 89,8 pobiera dane z tej kolumny / długości, Y4T traktuje je jako datę CCYYMMDD, PREVDSUM opracowuje poprzednią niedzielę, TOGREG = Y4T (-) wyprowadza je jako gregoriańską datę CCYY-MM-DD.

Ponieważ dostajesz śmieci, jeśli źródło i cel konkretnej części OVERLAY nakładają się destrukcyjnie, końcowe zmiany 11:X,18,120,6X)układają i maskują trochę bałaganu.

Podręczniki i dokumenty można znaleźć na stronie : http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 i zawierają ponad 900 stron przewodnika programowania aplikacji DFSORT.

Podobnie jak w przypadku wszystkich produktów IBM, wszystkie podręczniki są dostępne za darmo (z wyjątkiem bardzo drogiej liczby bardzo drogich, które tylko niewielka liczba ludzi na świecie mogłaby nawet udawać, że rozumie).

Wszystkie karty kontrolne DFSORT muszą zaczynać się od pustego pola. Kolumna 72 służy tylko do kontynuacji (każda niepusta wystarczy, ale * jest umowna). Po kolumnie 72 następuje obszar numeru sekwencji, który jest ignorowany, dzięki czemu każdy rekord ma 80 bajtów.

Może jeszcze kilka rozwiązań.

Bill Woodger
źródło
5

Bash, 63 bajty

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

Wynik:

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
źródło
for i in {1..12};{ date -v30d -v${i}m -v$1y -v0w +%Y-%m-%d;}- 60 bajtów
cyfrowy uraz
-vparam to datejest specyficzny dla daty BSD. To działa na OSX, ale nie na większości Linuksa - być może powinno to być zaznaczone w odpowiedzi.
Cyfrowy uraz
@DigitalTrauma, działa na Macu i moim Linuksie.
michael501,
4

Python 2 - 189 bajtów

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

Wprowadź datę za pomocą STDIN.

Jeszcze więcej golfa można zrobić. Program trochę przesadza, dla zabawy:

  • Brak importu, w szczególności brak korzystania z wbudowanych funkcji daty
  • Wykorzystuje zgodność Zellera do obliczania dni tygodnia

Uwagi

  • 1322 to magiczna tablica przeglądowa do określania, czy miesiąc inny niż luty ma 30, czy 31 dni
  • Nie zfilljest potrzebny przez lata ze względu na zakres wejściowy ani dni, ponieważ zawsze będą one przekraczać 20 lat

Python 2 - 106 bajtów

Nie takie zabawne rozwiązanie:

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.monthrangezwraca dwie liczby: dzień tygodnia, w którym miesiąc zaczyna się od ( w) oraz liczbę dni w miesiącu ( n). Rozwiązanie jest trochę sprzeczne z intuicją ze względu na haczyk - powracający dzień tygodnia zaczyna się od 0 dla poniedziałku , a nie niedzieli! Jest to jednak równoważone przez fakt, że njest oparty na 1.

Sp3000
źródło
1
Bardzo głupia odpowiedź Pytha:$from calendar import monthrange as gt$V12AGH>QhN%"%d-%02d-%d"(QhN-H%+GH7
FryAmTheEggman
3

JavaScript (ES6) 155 145

Edycja Naprawiono problemy ze strefą czasową Może być krótsza, jeśli zostanie wykonana cyklicznie. Może.

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
źródło
Możesz użyć new Date(y,0,++i,9). Nie udaje się to również w przypadku 2100 i więcej lat przestępnych, ponieważ JS nie ma informacji o tych latach przestępnych, a zatem nie ma Feb 29wcale w latach przestępnych w przypadku 2100 lat i powyżej.
Optymalizator
@Optimizer to nie JS: 2100,2200,2300 to lata przestępne. 2014 jest rokiem przestępnym i JS wie. Jeśli chodzi o korzystanie z godziny 9, nie mogę zweryfikować, ale myślę, że to nie działa, jeśli jesteś na przykład w Melbourne ...
edc65
Ach .. Nigdy nie wiedziałem, że spadamy 3 dni na 400 lat. O 9 - Zmieniłem strefę czasową od -1000 (Hawaje) do +1100 (Melbourne) i new Date(2014,0,26,9)była niedziela podając prawidłowy ISOciąg, jak również getDay()jako 0.
Optymalizator
3

JavaScript, ES6, 222 219 199 bajtów

Nie widziałem żadnej odpowiedzi JavaScript na wiki rosetta.

No to ruszamy:

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

Tworzy to funkcję, Sktóra zwraca ciąg o pożądanym wyniku. funkcja dba również o lata przestępne.

Ze względu na ES6 działa to tylko w najnowszym Firefoksie.

Dzięki apsillerom na końcówkę, która zmniejszyła ją do 200 bajtów

Znajdź nieprzygotowaną wersję poniżej jako fragment kodu, który możesz uruchomić tutaj:

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

Optymalizator
źródło
Możesz użyć + prompt () zamiast parsować i ogolić niektóre bajty
Jacob
@Jacob Ten monit nie jest dodawany do liczby bajtów.
Optymalizator
OIC. Powinienem był przeczytać pytanie ...
Jakub
@apsillers Thanks a tonne! Naprawiono problem i znacznie go ograniczano na podstawie Twojej wskazówki.
Optymalizator
2100Wyjście wejściowe 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-02jest nieprawidłowe.
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]]


Niegolfowany + kilka adnotacji:

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

Przykład obliczeń niedzielnych w konsoli 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
draegtun
źródło
Potencjał 87: d: 1-1-1 d / rok: wykonaj wydruk wejściowy odbierz [powtórz m 12 [d / miesiąc: m + 1 zachowaj d - d / dzień tygodnia]]
rgchris
@rgchris Thanks Chris. Był w stanie ogolić kolejne 7 znaków.
draegtun
Ładny!! Jest źle, ale tak naprawdę nigdy nie myśl o FOR jako skrócie.
rgchris
2

CJam, 122 102 bajtów

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

Nie korzysta z żadnej formy biblioteki dat. Sądzę, że nadal można dużo grać w golfa.

Sprawdź to tutaj.

Martin Ender
źródło
3
Jestem tak spektakularnie oszołomiony, że odpowiedź CJam nie jest jedną z najlepszych odpowiedzi w wyzwaniu golfa. Mogę umrzeć szczęśliwy .. Dzisiaj jest dobry dzień (oczywiście aż do golfa do 6 bajtów)
Brandon
@Brandon: To był powód, dla którego myślałem, że będzie interesujący. Naprawdę mam nadzieję zobaczyć jakąś cudowną bibliotekę, która sprawia, że ​​jest to łatwe, ale jak dotąd rozczarowane.
Phil H
1

R, 128 znaków

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

Z podziałami linii:

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
źródło
1

C # 255

Nie golfił

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

Edycja: zmodyfikowano, aby drukować tylko w ostatnią niedzielę :)

Bacchusbeale
źródło
Nie wymagany format wyjściowy. + To jest kod golfowy
edc65
1

q, 67

{({{1<>x mod 7}-[;1]/x}')14h$1_til[13]+13h$"D"$(($)x),".01.01"}
tartin
źródło
Czy w q nie są dostępne biblioteki dat?
Phil H
1

„Och, nie, on znowu!”

Java - 259 246 bajtów

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

Wersja bez golfa:

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

Stosowanie:

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

Wynik:

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

Jeszcze inna odpowiedź „wstawmy odpowiedź Javy tylko dla kopnięć”. No cóż. Ale przynajmniej, skoro starałeś się dotrzeć do tego punktu mojej odpowiedzi, postaram się zanudzić trochę więcej i wyjaśnię moje rozumowanie.

Metoda gotrzymuje żądany rok i dla każdego miesiąca tworzy GregorianCalendarobiekt (miesiące zaczynają się od 0 do 11). Następnie pierwszy c.setustawia dzień tygodnia jako niedzielę, a drugi deklaruje, że chcemy ostatniego tygodnia miesiąca - jak widać w oficjalnej dokumentacji . W System.out.printlndrukuje daty tej niedzieli (jeśli robimy to prawo, rok będzie drukowane c.get(c.YEAR), ale używając yponownie golenie off 13 znaków), a miesiąc ma być sformatowany dodać zera w okresie od stycznia do września (oraz wartość jest zwiększana, ponieważ cóż, miesiące tutaj są reprezentowane 0-11) i drukowany jest dzień ostatniej niedzieli. Ta procedura jest powtarzana przez pozostałe jedenaście miesięcy.

Rodolfo Dias
źródło
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);}}

Z podziałem linii

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

Produkcja za 2014 r

"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
źródło
Nie wymagany format wyjściowy
edc65
Tam naprawione. Lepszy?
Darren Breen
0

C # 171

Funkcja zwraca ciąg znaków.

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

Nie golfił

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
źródło
0

C # 194

używając 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")));}

Nie golfił

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

Wynik

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
źródło
0

Mathematica - 171

Zawinięte w anonimową funkcję zwraca ciąg

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

Pierwszy golf matematyczny. Wydaje mi się, że można to znacznie zmniejszyć.

globby
źródło
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

Mogło być gorzej ^ ^

Mój drugi i ostatni wpis (nie sądzę, że mogę go zmniejszyć)

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
źródło
0

Rubinowy 76

Używa parametru wiersza polecenia ruby sundays.rb 1900. Korzysta z biblioteki daty.

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