Ostatni poniedziałek


27

Poniedziałek, 31 października, to Halloween. I to dało mi do myślenia - Zastanawiam się, co inni mają miesiąc ostatni dzień miesiąca również być poniedziałek?

Wkład

  • Dodatnia liczba całkowita w dowolnym, wygodnym formacie reprezentujących w roku 10000 > y > 0.
  • W razie potrzeby dane wejściowe można uzupełnić zerami (np. 0025Dla roku 25).

Wydajność

  • Lista miesięcy tego roku, w których ostatnim dniem miesiąca jest poniedziałek.
  • Mogą to być nazwy miesięcy (np. January, March, October), Skrócone nazwy ( Jan, Mar, Oct) lub cyfry ( 1, 3, 10), oddzielne wiersze lub lista albo rozdzielone, itp., O ile czytelnik nie jest do tego jednoznaczny.
  • Format wyjściowy musi być spójny:
    • Dane wejściowe dla wszystkich lat (co oznacza, że ​​nie można wyprowadzać nazw miesięcy dla niektórych danych wejściowych i liczb miesięcy dla innych danych wejściowych)
    • Jak również spójny dla poszczególnych wyników (co oznacza, że ​​nie można generować 1dla Januarytego samego wyniku, co Juldla July)
    • Zasadniczo wybierz jeden format i trzymaj się go.

Zasady

  • Załóżmy kalendarz gregoriański dla wejścia / wyjścia, nawet do y = 1.
  • Lata przestępne muszą być odpowiednio rozliczone (przypomnienie: co roku można podzielić przez 4, z wyjątkiem lat niepodzielnych przez 100, chyba że podzielne przez 400 - 1700, 1800, 1900 nie były latami przestępnymi, ale 2000 był).
  • Możesz użyć dowolnych wbudowanych narzędzi lub innych narzędzi do obliczania daty.
  • Dopuszczalny jest pełny program lub funkcja. Jeśli funkcja, możesz zwrócić dane wyjściowe zamiast je wydrukować.
  • Standardowe luki są zabronione.
  • To jest więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).

Przykłady

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

Tabela liderów



1
Powiązane, ale nie duplikaty lub?
ElPedro

@ElPedro Powiązane, ale nie duplikaty. Pierwszy nie zezwala na żadne wbudowane i prosi o ustaloną kombinację daty / dnia (piątek 13), podczas gdy drugi prosi o ostatnią niedzielę każdego miesiąca w roku, ograniczoną między 1900 a 3015.
AdmBorkBork

Przepraszamy @TimmD. Moje niezrozumienie twojego komentarza.
ElPedro

1
@ElPedro Nie ma problemu! Wolę zadać pytanie i wyjaśnić, niż nie zadawać pytania i mieć coś niejasnego.
AdmBorkBork

Odpowiedzi:


2

Dyalog APL z dfns jest cal , wersja 15.0: 22; Wersja 16.0: 19 bajtów

Funkcja cal jest dostarczana z domyślną instalacją, wystarczy wejść )copy dfns.

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

zaciągnąć się (spłaszczyć)

⎕{... dane liczbowe jako lewy argument do następującej anonimowej funkcji, przyjmując kolejno każdą z wartości po prawej stronie jako prawy argument

⍵/⍨ argument if (daje pustą listę, jeśli nie)

2= dwa (mianowicie niedziela i poniedziałek) są równe

suma z

liczby w

⊢⌿ najniższy wiersz

cal kalendarz dla

⍺⍵ rok lewy argument, miesiąc prawy argument, ten ostatni

⍳12 Od 1 do 12

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

wskaźniki gdzie

2= dwa równe (tj. niedziela i poniedziałek)

⎕{... dane liczbowe jako lewy argument do następującej anonimowej funkcji, przyjmując kolejno każdą z wartości po prawej stronie jako prawy argument

suma z

liczby w

⊢⌿ najniższy wiersz

cal kalendarz dla

⍺⍵ rok lewy argument, miesiąc prawy argument, ten ostatni

⍳12 Od 1 do 12


19

JavaScript (Firefox 30+), 112 109 103 95 bajtów

Spójrz, nie ma wbudowanych!

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]

Oto 107-bajtowa wersja ES6:

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)

A oto moja poprzednia próba, 123 113 bajtów 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]

Wyjaśnienie

Dzień tygodnia danego roku oblicza się w następujący sposób:

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

Innymi słowy:

  • Weź y.
  • Dodaj liczbę 4 lat przed y( y>>2).
  • Odejmij liczbę 100 lat przed y( y/100|0).
  • Dodajmy liczbę sprzed 400 lat y; to 1/4 y/100|0, więc używamy *3/4|0.

Następnie modulujemy wynik o 7. Jeśli pozwolimy na 0oznaczenie niedzieli, 1średniego poniedziałku itd., Wynik odpowiada dniu tygodnia 31 grudnia tego roku. Dlatego w grudniu chcemy sprawdzić, czy wynik jest 1. To daje nam ostatni znak w ciągu.

Ostatni dzień listopada to 31 dni przed ostatnim dniem grudnia. Oznacza to, że aby ostatni dzień listopada był poniedziałkiem, 31 grudnia musi być (1 + 31) % 7 = 4= czwartek.

Ta procedura jest powtarzana, dopóki nie wrócimy do marca (a 3). Niezależnie od tego, czy jest dzień przestępny, ostatni dzień lutego przypada 31 dni przed ostatnim dniem marca, więc możemy to również obliczyć (to jest (3 + 31) % 7 = 6). Trudną częścią jest znalezienie poprawnej wartości dla stycznia:

  • Jeśli jest to rok przestępny, ostatni dzień stycznia przypada 29 dni przed ostatnim dniem lutego, w wyniku czego (6 + 29) % 7 = 0.
  • W przeciwnym razie jest to 28 dni przed ostatnim dniem lutego, w wyniku czego (6 + 28) % 7 = 6.

Możemy obliczyć, czy jest to rok przestępny za pomocą następującego fragmentu kodu:

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

Daje to, 0jeśli ynie jest to rok przestępny, a dodatnią liczbę całkowitą w przeciwnym razie. To prowadzi nas do

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

do obliczenia dnia w styczniu. Możemy jednak zrobić to lepiej, odwracając warunki:

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

Ponieważ wynik fałszowania jest zawsze równy 0, możemy go zredukować do

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

oszczędzając jeszcze jeden cenny bajt.

Łącząc to wszystko, przeglądamy każdy znak w ciągu, sprawdzając, czy każdy z nich jest równy dniu tygodnia 31 grudnia. Zachowujemy indeksy pasujących, zwracając tę ​​tablicę na końcu. I tak wykonujesz obliczenia roku przestępnego bez wbudowanych funkcji.


Owww ... Mój mózg, czy byłeś odpowiedzialny za lata przestępne w tym wszystkim?
Magic Octopus Urn

2
@carusocomputing Po to !(y%4)*y%100|!(y%400)jest. co roku podzielne przez 4, z wyjątkiem lat niepodzielnych przez 100, chyba że podzielne przez 400
mbomb007

Mam nadzieję, że y+(y>>2)+(z=y/25>>2)+(z>>2)wciąż oszczędza bajt.
Neil

@Neil Dzięki, ale znalazłem lepszy sposób :-)
ETHproductions

Miły; Za pomocą zapisałem 6 bajtów na moim porcie wsadowym (y*5/4-(y/100)*3/4).
Neil,

11

JavaScript (Firefox 30-57), 67 65 64 63 61 bajtów

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

Zaoszczędź 2 4 6 bajtów dzięki @ETHproductions. Zapisano kolejny bajt, wyprowadzając miesiące w odwrotnej kolejności.


Myślę, że możesz zaoszczędzić 2 bajty, skrzydlując go bez .keys():y=>[for(_ of(m=0,Array(12)))if(new Date(y+400,++m).getDay()==2)m]
ETHprodukcji

@ETHproductions Mogę zapisać kolejny bajt, odwracając zamówienie!
Neil

Odwrotna kolejność jest w porządku. Formatowanie wyniku nie jest interesującą częścią tego wyzwania.
AdmBorkBork

Jakie są nasze zasady dotyczące interpretacji tablic teraz, gdy zostały usunięte ze specyfikacji?
MayorMonty

Możesz zapisać kolejne 2 bajty, pomijając Array(12)całkowicie: y=>[for(_ of(m=0,1e11+""))if(new Date(y+400,++m).getDay()==2)m]
ETHprodukcje

8

MySQL, 183 134 129 106 bajtów

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

Zamień 2016na żądany rok. Biegać.

Wersja 2: Używał help_topicstabeli w domyślnej instalacji zamiast tworzenia tabeli tymczasowej.

Rev.3: Przyjęty trick arossa- i zauważyłem, że mogę również pominąć cytaty "-1".
Jest to jednak -1wymagane w MySQL: potrzebuję pełnej daty.

Rev.4: Ograniczenie m BETWEEN 1 AND 12może być wykonane jako m>0 AND m<13(-6), ale w ogóle nie jest potrzebne - nieprawidłowe wartości zostaną zignorowane; ostrzeżenia zostaną policzone, ale nie wymienione.


Potrzebujesz naprawdę tabeli shema mysql? mariadb.com/kb/en/mariadb/mysqlhelp_topic-table
Jörg Hülsermann

@ JörgHülsermann Nie rozumiem.
Tytus

Czy FROM help_topicbez mysql.pracy? Nie próbowałem
Jörg Hülsermann

@ JörgHülsermann tylko wtedy, gdy przygotowujesz USE mysql;Poprawną bazę danych należy jakoś wybrać.
Tytus

5

Perl, 64 bajty

Obejmuje +1 dla -n

Podaj dane wejściowe 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

Partia, 160 152 bajtów

@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%%

Port odpowiedzi @ ETHproduction. Ze skrótami miesięcznymi dla 197 189 bajtów:

@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 bajtów

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

Zapisano 15 bajtów przy pomocy @ Adám .

Używa wbudowanego kalendarza do generowania tablicy ciągów reprezentujących miesiące, a następnie analizuje każdy ciąg w celu ustalenia, czy ostatni poniedziałek jest ostatnim dniem miesiąca. Dane wyjściowe są wysyłane każdego miesiąca jako numer każdego miesiąca. Oznacza to, że Jan = 0, Feb = 1, ..., Dec = 11.

Dane wyjściowe calendarto

   _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               │                     │                     │
└─────────────────────┴─────────────────────┴─────────────────────┘

Stosowanie

   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

Wyjaśnienie

[: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

czekaj, czy kalendarz faktycznie wyświetla sztukę ascii?
Destructible Lemon

@DestructibleWatermelon Aby być dokładnym, format wyjściowy calendarto tablica 12 pól, w których każde pole zawiera tablicę 2d znaków
mile

Nie wiem nawet, jak zrobić „każde” w J, ale jest to już znacznie krótsze: I.7=;#&.>".&.>,&.>_2{.&.>calendar 2016jeśli połączysz wszystkie „niedocenione”, powinieneś być w stanie to dość krótko.
Adám

@ Adám Dzięki, używa lepszej metody, ale nie jest czasownikiem w J. Myślę, że to nadal pomoże
mile

Moim zamiarem było tylko inspirowanie. Wiem, że to nie jest czasownik.
Adám

4

Mathematica, 62 57 bajtów

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

Funkcja anonimowa. Pobiera liczbę jako dane wejściowe i zwraca listę jednoelementowych list liczb jako danych wyjściowych. Naprawdę nie jestem już pewien, jak to działa.


4

Perl + cal, 46 bajtów

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

Przykład:

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

2







10


$

1
Ściśle mówiąc, jest to perl + cal, a nie tylko perl :-p. Na przykład mój komputer z systemem Windows ma perla, ale to nie zadziała.
philomory

W porządku, zaktualizowałem to i moją próbę bashu.
steve

4

Java 7,186 182 172 bajty

Dzięki Kevin za uratowanie 4 bajtów
Dzięki @cliffroot za uratowanie 10 bajtów

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

bez golfa

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

Ta wersja jest dostarczana przez @cliffroot ( 168 bajtów )

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

próbka wyjściowa

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

1
Po napisaniu odpowiedzi wiedziałem, że obliczenie wszystkiego samemu będzie krótsze .. :) A przy okazji możesz grać n%4==0w golfa n%4<1; n%400==0do n%400<1i int c=...;int[]b=...,a=...do int c=...,b[]=...,a[]=....
Kevin Cruijssen

1
bi amożna je zdefiniować w intczęści w ten sposób: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;}zapisano kilka bajtów
Cliffroot

1
Można również zmieniać bsię b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3}i i+30aby i+28przez 2 bajty
cliffroot

1
i kolejne 3 bajtyint[]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 bajtów

Ugh. Matematyka z datami nie jest tak prosta, jak bym chciał.

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]

Wypróbuj online

Ta sama długość:

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]

Nie zamierzałem nawet wypróbować Pythona z tym. Niezły wysiłek.
ElPedro

3

MATL , 21 bajtów

12:"G@QhO6(YO9XO77=?@

Miesiące są wyświetlane jako liczby.

Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie

Korzysta z wbudowanych funkcji konwersji daty. W danym roku sprawdza, który ostatni dzień miesiąca to poniedziałek.

Zamiast wyraźnego określania ostatniego dnia miesiąca k(który może wynosić 28, 29, 30 lub 31), określamy 0-ty dzień miesiąca k+1, który jest równoważny i nie zależy od miesiąca ani roku.

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

Narzędzia Bash + GNU, 56 bajtów

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

Wygląda na wymaganą datewersję 8.25. Wersja 8.23 ​​w Ideone tego nie wycina.


3

Excel, 537 bajtów

Ponieważ - wiesz - Excel!

Zajmuje rok wejścia w A1. Zwraca szesnastkową listę miesięcy; 1 = styczeń, C = grudzień. Ponieważ każdy miesiąc jest pojedynczą cyfrą, separator nie jest potrzebny.

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

Przykład: A1 zawiera 2016. B1 zawiera powyższą formułę i wyświetla się jako 2A, co oznacza luty i październik.


3

PHP, 109 180 159 bajtów

for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";
  • Wyprowadza podany rok, nie wszystkie (... zawsze czytaj pytanie)
  • Ignorowane powiadomienia (dzięki Titus)
  • Zmiana whiledo forjak jest to obecnie jeden rok (znowu, dzięki Titus)

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

Obsługuje wszystkie lata od kropki do 10000, pozbyłem się również niezdefiniowanego ostrzeżenia var, którego nie znałem na jednym komputerze. Tak, jest dłuższy niż stara wersja, ale jest bardziej niezawodny.

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

Jeśli działa na systemie Windows lub 32-bitowym, pojawi się przerażający błąd 2038, ale na 64-bitowym systemie Linux jest w porządku.

Próbowałem użyć, date("t"...która ma oznaczać ostatnią datę danego miesiąca, ale wyniki nie były zgodne z poprzednio wymienionymi w tym wątku.


2
-2: „$ z” nie potrzebuje cudzysłowów -7: zignoruj powiadomienia (nie są drukowane z ustawieniami domyślnymi: nie inicjuj $z, bez cudzysłowów N) -1: forzamiast while -43 : weź dane zgodnie z żądaniem zamiast zapętlania lat -3: joinzamiast implode-16: wyjście bezpośrednie: 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, jeśli nalegasz, aby nie wstawiać przecinka:echo$o=$o?",$m":$m;
Titus

Ahh źle odczytał pytanie! Myślałem, że tak było przez wszystkie lata .. ups: B Dziękuję również za inne sugestie,
trafię

3

PHP, 92 bajty

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

sprawdź 12 razy 1 miesiąc po pierwszym dniu roku jest wtorek. Jeśli tak, to dzień poprzedzający ostatni dzień miesiąca to poniedziałek.


Możesz użyć echa zamiast wydrukować i zapisać 1
Octopus

1
@Octopus poza operatorem trójskładnikowym
Jörg Hülsermann

3

C, 214 bajtów

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

Skompilować

gcc -std=c99 -o foo foo.c

Nie golfił

Z kredytami dla odpowiednich guru.

Michael Keith i Tom Craver dla programu C, aby znaleźć dzień tygodnia dla podanej daty .

Collin Biedenkapp dla Q&A: Jak dowiedzieć się, jaki jest ostatni dzień miesiąca?

/* 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
Co się stanie, jeśli odwrócisz się ifw drugą stronę, aby uzyskać elsezwrot 31, a zatem możesz wyeliminować wielki ==łańcuch?
AdmBorkBork

1
byłoby lepiej, gdyby (x == 1) {z część} jeszcze gdyby (x == 3 || x == 5 || x == 8 || x == 10) zwrócił 30 inaczej zwrócił 31
RosLuP

1
co z: return 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: dzięki za punkty return (), 100 bajtów zapisanych.
steve

1
możliwe jest dalsze zmniejszanie aż do tego: u (y, m) {return m-1? 30 + ((2773 >> m) i 1): 28+ (y% 4 == 0 i&y% 100 || y% 400 == 0);} gdzie y oznacza rok im miesiąc
RosLuP

3

C, 119 bajtów

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

Wykorzystuje to tabelę, która zawiera przesunięcie dni tygodnia ostatniego dnia każdego miesiąca dla roku przestępnego, zakodowanego w 32-bitowym słowie ze znakiem 7. Jeśli nie jest to rok przestępny, dodajemy 1 do przesunięcia stycznia (jak widać y&3||y%25<1&&y&15służy do sprawdzania przez lata bez dni przestępnych). Następnie po prostu przeglądamy co miesiąc i sprawdzamy, czy ostatni dzień to poniedziałek. Właściwie dość proste, bez brzydkich hacków i sztuczek. Tutaj jest nieco nie golfa:

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

Mógłbym ponownie to zrobić, aby przepisać to jako funkcję zapisywania kilku znaków. printfTeż zajmuje trochę zbyt dużo miejsca ...


Printf („% d”, m) wypisuje coś jako 1 lub 2, 3, więc zawsze jest jeden ”,„ więcej ... Wolę używać tylko spacji
RosLuP

Rzeczywiście, wolę spacje na wyjściu, ale zwykle piszę moje rozwiązania C w golfie, aby nie potrzebowały żadnych białych znaków, więc mogę po prostu usunąć wszystkie białe znaki z mojej wersji w połowie golfa, gdy chcę sprawdzić liczbę moich postaci .
Fors

3

PHP, 96 95 76 71 69 64 61 bajtów

Uwaga: numery roku muszą być uzupełnione do 4 znaków, np 0070.

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

Uruchom tak:

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

Wyjaśnienie

Iteruje od -1 do -12. Utwórz datę, używając mktime, dzień 0(ostatni dzień poprzedniego miesiąca) i miesiąc 2..13. Sformatuj datę jako numer dnia , a jeśli wynik to 1, wydrukuj bieżący numer. Znak ujemny -jest używany jako separator.

Millenium Bug znów uderza!

Zauważ, że w tej wersji zakres 0..100jest interpretowany jako 1970..2069. Nie stanowi to problemu dla zakresu 0..69, ponieważ tygodnie mają wzorzec powtarzający się co 400 lat (146097 dni, dokładnie 20871 tygodni), ale dla zakresu 70..99dodaje się 1900 do numeru roku, który nie jest wielokrotnością 400. Aby naprawić ten problem TYLKO dla liczb 30-letnich w zakresie 10k, najprostszym sposobem jest dodanie 400 do numeru roku, aby zapobiec dwucyfrowej interpretacji ( +4 bajty ):

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

Poprawki

  • Zapisane bajt za pomocą !~-$iporównać $iz 1( -1binarny zanegowana jest 0logicznie negowana jest true, co drugi numer jest false), więc nie są potrzebne nawiasy
  • Zapisano 19 bajtów, używając last day ofYYYY-mnotacji do utworzenia daty
  • Zapisano 5 bajtów za pomocą datei strtotimezamiastdate_create
  • Zapisano 2 bajty, licząc od liczb ujemnych, używając znaku ujemnego jako separatora wyjściowego (ujemne liczby miesięcy nie istnieją), a także jako separatora w YYYY-mczęści daty
  • Zapisano 5 bajtów, używając mktimezamiast strtotime. Przywrócono używanie dnia 0( mktimeobsługuje również miesiąc 13, więc 0-13== 31-12)
  • Zapisano 3 bajty za pomocą, -Raby $argnudostępnić

mktimeusuwa konieczność wypełniania roku, prawda?
Tytus

@Titus, ostry. Właśnie się zorientowałem, że mktimejest to sprzeczne z intuicją , ponieważ argumenty są traktowane jako INTs. Oznacza to, że nie możesz wypełnić roku ... więc wszystko w zasięgu 0..100jest interpretowane jako 1970..2070. Nie stanowi to problemu dla zakresu, 0..70ponieważ 400 lat ma dokładną liczbę tygodni (więc kalendarze powtarzają wzór co 400 lat), ale 70..99dodaje 1900 (nie wielokrotność 400!). Dlatego nowa wersja. ma błąd.
aross

Jedyne rozwiązanie, jakie teraz widzę, to $argv[1]+400... chyba że dni tygodnia w Julianie i Gregoriańskim są różne.
Tytus

@Titus, tak. Zasady użytkowania powiedzieć gregoriański CAL
aross

3

Excel, 428 97 96 bajtów

Wprowadź w A1. Wyjście niepodzielonych wartości szesnastkowych (styczeń = 0, grudzień = B)

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

Dodano 10 bajtów („+2000”), aby umożliwić obsługę dat sprzed 1990 r.

Zaoszczędź 11 bajtów dzięki @ Engineer Toast .


Pierwsza próba (428 bajtów), intensywne pożyczanie z rozwiązania @ 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","")

Jak to działa w latach wcześniejszych niż 1900? Przypadek testowy 297 -> Maypowraca 6z tą formułą. Czy nie powinno być 4? 1776daje 7Azamiast tylko 8na wrzesień.
Inżynier Toast

Jeśli jednak sprawisz, że zadziała, prawdopodobnie możesz użyć Date(A1,3,0)zamiastEOMONTH(DATE(A1,2,1),0)
Engineer Toast

2

Bash + cal, 58 bajtów

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

+1 - działa dla BSD cal(np. OSX), ale uważaj na końcowe spacje na GNU cal.
Digital Trauma

2

Python 2, 94 bajty

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

Funkcja nienazwana, rok całkowity, wyświetla listę numerów miesięcy [1-12].

Próbowałem również pokonać liczbę bajtów arytmetyką bez powodzenia (110 bajtów). :

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)

Nienazwana funkcja, która zwraca listę wartości logicznych reprezentujących, czy miesiące [styczeń-grudzień] kończą się w poniedziałek


2

Java 7, 200 249 bajtów

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

W Javie GregorianCalendarjest mieszanką kalendarza gregoriańskiego i kalendarza juliańskiego. Z tego powodu rok 1dał nieprawidłowe wyniki. Zmiana Calendar c=Calendar.getInstance();do GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));poprawek to przez wymuszanie użycia tylko w kalendarzu gregoriańskim. Dzięki @JonSkeet na stackoverflow.com za wyjaśnienie mi tego.

Kod niepoznany i testowy:

Wypróbuj tutaj.

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

Wydajność:

4 12
5 
9 
1 7 
2 10 
1 2 10 

2

C # 6 C #, 171 167 135 bajtów

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 bajty dzięki Shebang

Drukuj miesiące jako liczby; z ograniczeniem miejsca; z końcową przestrzenią. Teraz ta odpowiedź działa również dla wcześniejszych wersji C #.


Stary, 167 bajtów

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 bajty dzięki TimmyD

Miesiące wyjściowe to liczby w ciągu zwracanym, rozdzielane przecinkami

Nie golfił

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 Tak, ale potrzebujesz jawnej obsady. Odpowiedź zaktualizowana
Link Ng

LINQ to zabawa, ale jest to 126 bajtów: 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);}}};) Również byłoby krótsze oddanych DayOfWeekdo intniż byłoby rzucić intsięDayOfWeek
Kade

@Shebang Thanks. Naprawdę nie powinienem grać w golfa w linijce z jedną linią --- Tylko Jon Skeet może to zrobić. Sprawdź, czy mam czas na aktualizację jutro. Zmęczony teraz.
Link Ng

Możesz przekonwertować to na, Action<int>aby zaoszczędzić trochę bajtów
TheLethalCoder

2

Rubinowy, 54 + 6 = 60 bajtów

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

6 bajtów -rdatew wierszu polecenia, aby uzyskać klasę Date ze standardowej biblioteki.

Wyjaśnienie: całkiem proste dzięki doskonałej Dateklasie Ruby stdlib . Nie tylko mieć metod, takich jak monday?, tuesday?itp, konstruktor odbędzie liczby ujemne dla każdej dziedzinie ubiegłym roku oznacza „zalicza to pole wstecz od końca okresu reprezentowane przez poprzedniego pola”. $*jest skrótem ARGV, więc $*[0]jest to szybki sposób na uzyskanie pierwszego argumentu wiersza poleceń.


2

PHP, 84 bajty

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

Mój pierwszy Code Golf. Jest to najkrótszy jak dotąd PHP w tej kwestii.

EDYCJA: wydaje się, że nie działa przez rok 1. Muszę dowiedzieć się, dlaczego, ale teraz muszę iść.


1
Powiedziałbym „Witamy w PPCG!” ale jesteś tu zarejestrowany dłużej niż ja! : D Miły pierwszy golf.
AdmBorkBork

Twój błąd polega na tym, że tworzysz 1-13-1 i 1-14-1 na rok 1 <13 wystarczy. Jeśli to rozwiążesz, możesz w tej chwili usunąć nieprzyzwoite nawiasy i pomyśleć o użyciu operatora trójskładnikowego
Jörg Hülsermann

To powinno rozwiązać twoje problemyfor(;$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 bajtów

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

Sekwencja ostatnich dni każdego miesiąca jest określona przez seq(as.Date(paste0(x,-2,-1)),,'m',12)-1:

  • paste0wymusza -2 i -1 na znaki. Jeśli xbyło 2016 na przykład, paste0(x,-2,-1)daje "2016-2-1"która jest następnie przekształcany do 1 lutego 2016 przez as.Date.

  • seqzastosowany do POSIXct lub obiektu Date jest seq(from, to , by, length.out): tutaj tonie jest podany, byjest podany jako taki, 'm'który jest dopasowany 'month'dzięki częściowemu dopasowaniu, i length.outjest oczywiście 12.

  • Powstała w ten sposób sekwencja jest pierwszym dniem 12 miesięcy, poczynając od lutego danego roku. -1daje nam wtedy ostatni dzień z 12 miesięcy, poczynając od stycznia danego roku.

Przypadki testowe:

> 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

Stara wersja z 95 bajtami, wyświetlająca nazwy miesięcy zamiast tylko ich liczb:

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

Ta odpowiedź jest po prostu genialna. Nie miałem pojęcia, seqże mam metodę dla Date-objektów, co rozwiązuje problem as.Datebraku obsługi lat powyżej 10000w mojej usuniętej odpowiedzi.
Billywob

@Billywob tak seq.Datei seq.POSIXtsą dość imponujące: mogą nawet przetwarzać polecenia takie jak seq(time1, time2, by="10 min")lub seq(date1, date2, by="quarter"). Bardzo przydatne podczas kreślenia szeregów czasowych.
plannapus

2

Japt, 24 bajty

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

Przetestuj online! Zwraca tablicę liczb,falsezamiast miesięcy, które nie kończą się w poniedziałek.

Wystąpił błąd w interpretatorze, który nie pozwalał mi korzystać Ðz treści funkcji £. Po usunięciu błędu i dodaniu innej funkcji w bieżącym zatwierdzeniu jest to 18 bajtów:

Do1@Ð400+UX e ¥2©X

1

Java, 143 129 bajtów

Korzysta z nowego interfejsu API czasu 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;}

Wydajność

Zauważ, że każda linia ma dodatkowe spacje na końcu.

4 12 
5 
9 
1 7 
2 10 
1 2 10 

Niegolfowany i testowany

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

Goli

  1. 143 do 129 bajtów: użyj DayOfWeek::ordinaldo porównania ze stałą numeryczną zamiast stałej wyliczeniowej.
    Dzięki @TimmyD za ogólny pomysł, jeśli nie dokładne rozwiązanie! ;-)

@ TimmyD niestety, to wyliczenie. Ma jednak getValue()metodę, która zaoszczędziłaby kilka bajtów.
Celos

@Celos ordinal()pozwala zaoszczędzić 1 bajt więcej w porównaniu do getValue(), chociaż zaleca się, aby nigdy go nie używać.
Olivier Grégoire

tak, dobre myślenie. Zamieściłem swój komentarz bez pierwszego odświeżenia, więc nie widziałem twojej odpowiedzi i nie edytowałem.
Celos

1

GNU awk, 80 bajtów

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

Przykład

$ gawk '{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}' <<<2016
2
10
$
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.