Останній понеділок


27

Понеділок, 31 жовтня, - Хеллоуїн. І мене це задумалося - мені цікаво, які інші місяці останнім днем ​​місяця також є понеділок?

Вхідні дані

Вихідні дані

  • Список місяців того року, коли останнім днем ​​місяця є понеділок.
  • Це можуть бути назви місяців (наприклад, January, March, October), або короткі імена ( Jan, Mar, Oct), або цифри ( 1, 3, 10), як окремі рядки чи список, або з обмеженим доступом тощо., Тільки якщо це однозначно для читача.
  • Формат виводу повинен відповідати:
    • За всі роки введення даних (тобто не можна виводити назви місяців для деяких входів та номерів місяців для інших даних)
    • Так само, як і на один вихід (тобто ви не можете виводити 1на Januaryтой же вихід, що і Julдля July)
    • В основному, виберіть один формат і дотримуйтесь його.

Правила

  • Припустимо, григоріанський календар для введення / виведення, навіть до y = 1.
  • Випускні роки повинні бути належним чином враховані (як нагадування: кожен рік ділиться на 4, за винятком випадків, коли не ділиться на 100, якщо тільки вони не поділяються на 400 - 1700, 1800, 1900 рр. - всі не були високосні роки, але 2000 рік).
  • Ви можете використовувати будь-які вбудовані або інші інструменти для обчислення дати, які вам подобаються.
  • Прийнятна або повна програма, або функція. Якщо функція, ви можете повернути вихід, а не надрукувати його.
  • Стандартні лазівки заборонені.
  • Це тому діють усі звичайні правила гольфу, і найкоротший код (у байтах) виграє.

Приклади

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

Таблиця лідерів



1
Пов’язані, але не дублікати або?
ElPedro

@ElPedro Пов’язані, але не дублікати. Перший не дозволяє вбудовувати будь-які вбудовані модулі та просить встановити комбіновану дату / день (п’ятниця 13 числа), а другий просить останню неділю кожного місяця року, обмежений між 1900 та
3015 роками.

Вибачте @TimmD. Моє нерозуміння вашого коментаря.
ElPedro

1
@ElPedro Немає проблем! Я б скоріше поставив питання і чи було б це зрозуміло, ніж не мати питання і мати щось незрозуміле.
AdmBorkBork

Відповіді:


2

Dyalog APL з dfns 's cal , версія 15.0: 22; Версія 16.0: 19 байт

Функція cal постачається з установкою за замовчуванням, просто введіть )copy dfns.

Версія 15.0: ∊⎕{⍵/⍨2=≢⍎⊢⌿cal⍺⍵}¨⍳12

заручитися (згладити)

⎕{... числовий введення як аргумент зліва для наступної анонімної функції, приймаючи по черзі кожне з значень правого боку як правий аргумент

⍵/⍨ аргумент if (дає порожній список, якщо ні)

2= два (а саме в неділю та понеділок) дорівнює

підрахунок

числа в

⊢⌿ самий нижній ряд

cal календар для

⍺⍵ рік лівий аргумент, місяць праворуч, останній -

⍳12 1 - 12

Версія 16.0: ⍸2=⎕{≢⍎⊢⌿cal⍺⍵}¨⍳12

індекси де

2= дві рівні (а саме в неділю та понеділок)

⎕{... числовий введення як аргумент зліва для наступної анонімної функції, приймаючи по черзі кожне з значень правого боку як правий аргумент

підрахунок

числа в

⊢⌿ самий нижній ряд

cal календар для

⍺⍵ рік лівий аргумент, місяць праворуч, останній -

⍳12 1 - 12


19

JavaScript (Firefox 30+), 112 109 103 95 байт

Дивись ма, ніяких вбудованих!

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]

Ось 107-байтна версія 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)

І ось моя попередня спроба, 123 113 байт 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]

Пояснення

День тижня конкретного року обчислюється так:

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

Іншими словами:

  • Беріть y.
  • Додайте число 4-х років до y( y>>2).
  • Відніміть число 100-ти років до y( y/100|0).
  • Додайте ще за 400 років до цього y; це 1/4 y/100|0, тому ми використовуємо *3/4|0.

Тоді ми модулюємо результат на 7. Якщо ми маємо на 0увазі неділю, 1середній понеділок тощо, результат відповідає дню тижня 31 грудня цього року. Тому на грудень ми хочемо перевірити, чи є результат 1. Це дає нам останній знак у рядку.

Останній день листопада за 31 день до останнього грудня. Це означає, що останнім днем ​​листопада, щоб бути понеділком, 31 грудня має бути (1 + 31) % 7 = 4= четверг.

Ця процедура повторюється, поки ми не повернемося до березня (а 3). Незважаючи на те, чи є чи не високосний день, останній день лютого є на 31 день до останнього березня, тому ми можемо обчислити і це (це (3 + 31) % 7 = 6). Хитра частина - знаходження правильного значення для січня:

  • Якщо це високосний рік, останній день січня за 29 днів до останнього дня лютого, в результаті чого (6 + 29) % 7 = 0.
  • В іншому випадку це за 28 днів до останнього дня лютого, в результаті чого (6 + 28) % 7 = 6.

Ми можемо обчислити, чи є це високосний рік із наступним фрагментом:

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

Це дає, 0якщо yце не високосний рік, а додатне ціле число в іншому випадку. Це призводить нас до

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

для розрахунку дня на січень. Однак ми можемо зробити краще, скасувавши умови:

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

Оскільки результат хибної помилки завжди дорівнює 0, ми можемо зменшити його до

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

збереження ще одного дорогоцінного байта.

Збираючи все це разом, ми пров'язуємо кожну таблицю в рядку, перевіряючи, чи дорівнює кожен день тижня 31 грудня. Ми зберігаємо індекси відповідних, повертаючи цей масив у підсумку. І саме так ви робите розрахунки високосного року без вбудованих модулів.


Оууу ... Мій мозок, чи були ви рахунки за високосні роки в цьому?
Magic Octopus Urn

2
@carusocomputing Це для чого !(y%4)*y%100|!(y%400). щорічно ділиться на 4, за винятком років, не поділених на 100, якщо також не ділиться на 400
mbomb007

Сподіваємось, y+(y>>2)+(z=y/25>>2)+(z>>2)все-таки економиться байт.
Ніл

@Neil Дякую, але я знайшов кращий спосіб :-)
ETHproductions

Ніцца; На моєму пакетному порту я зберег 6 байт (y*5/4-(y/100)*3/4).
Ніл

11

JavaScript (Firefox 30-57), 67 65 64 63 61 байт

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

Збережено 2 4 6 байт завдяки @ETHproductions. Збережено ще один байт шляхом виведення місяців у зворотному порядку.


Я думаю, що ви можете зберегти 2 байти, .keys()y=>[for(_ of(m=0,Array(12)))if(new Date(y+400,++m).getDay()==2)m]
розправивши

@ETHproductions Я можу зберегти подальший байт, змінивши замовлення!
Ніл

Зворотний порядок - це добре. Форматування вихідних даних не є цікавою частиною цього завдання.
AdmBorkBork

Яка наша політика щодо розуміння масиву тепер, коли вони були вилучені з специфікації?
МерМонті

Ви можете зберегти ще два байти, пропустивши Array(12)цілком: y=>[for(_ of(m=0,1e11+""))if(new Date(y+400,++m).getDay()==2)m]
ETHproductions

8

MySQL, 183 134 129 106 байт

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

Замініть 2016бажаним роком. Біжи.

Rev. 2: Використовується help_topicsтаблиця в установці за замовчуванням замість створення тимчасової таблиці.

Rev.3: Прийнятий через -хитрість і помітив, що я також можу опустити цитати "-1".
Однак -1це потрібно в MySQL: мені потрібна повна дата.

Rev.4: обмеження m BETWEEN 1 AND 12можна зробити як m>0 AND m<13(-6), але воно взагалі не потрібно - недійсні значення будуть ігноровані; попередження будуть враховані, але не перераховані.


Вам справді потрібна таблиця shema mysql? mariadb.com/kb/en/mariadb/mysqlhelp_topic-table
Jörg Hülsermann

@ JörgHülsermann Я не розумію твоєї точки зору.
Тит

Невже FROM help_topicбез mysql.роботи? Я пробував не так
Йорг Гюльсерманн

@ JörgHülsermann, лише якщо ви додасте попередньо USE mysql;Правильну базу даних потрібно вибрати якось.
Тит

5

Perl, 64 байти

Включає +1 для -n

Введіть дані про 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

Пакетна, 160 152 байт

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

Порт відповіді @ ETHproduction. З місячними скороченнями для 197 189 байт:

@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 байт

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

Збережено 15 байт за допомогою @ Adám .

Використовує вбудований календар для створення масиву рядків, що представляють місяці, а потім аналізує кожен рядок, щоб визначити, чи є останній понеділок останнім днем ​​місяця. Він виводиться щомісяця як число місяця кожного. Тобто Jan = 0, Feb = 1, ..., Dec = 11.

Вихід calendarє

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

Використання

   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

Пояснення

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

зачекайте, чи насправді календар виводить мистецтво ascii?
Руйнуючий лимон

@DestructibleWatermelon Точністю, вихідний формат calendar- це масив з 12 полів, де кожне поле містить 2d масив символів
миль

Я навіть не знаю, як зробити "кожного" в J, але це вже набагато коротше: I.7=;#&.>".&.>,&.>_2{.&.>calendar 2016якщо ви об'єднаєте всі "недостатньо відкриті", ви повинні мати можливість отримати його досить коротко.
Adám

@ Adám Спасибі, він використовує кращий метод, але це не дієслово в J. Я думаю, що він все ще допоможе, хоча
милі

Мій намір був лише надихнути. Я знаю, що це не дієслово.
Adám

4

Математика, 62 57 байт

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

Анонімна функція. Приймає число як вхідне і повертає список одноелементних списків чисел як вихід. Я, чесно кажучи, не впевнений у собі, як це більше працює.


4

Perl + cal, 46 байт

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

Приклад:

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

2







10


$

1
Строго кажучи, це perl + cal, а не просто perl :-p. Наприклад, моя машина Windows має Perl, але це не працює.
філомонія

Справедливий пункт, оновив це і мою спробу башти.
steve

4

Java 7,186 182 172 байти

Завдяки Кевіну за збереження 4 байт
Завдяки @cliffroot за збереження 10 байт

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

неозорий

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

Цю версію надає @cliffroot ( 168 байт )

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

вихідний зразок

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

1
Після того, як я написав свою відповідь, я знав, що все обчислити все буде коротше .. :) До речі, можна покататися n%4==0на гольфі n%4<1; n%400==0до n%400<1і int c=...;int[]b=...,a=...до int c=...,b[]=...,a[]=....
Кевін Круїйсен

1
bі aможе бути визначений у intтакій частині:int ... ,b[]=...,a[]=...
Олів'є Грегоар

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;}збережено кілька байтів
скелі

1
також можна змінити bна b[]={3,(n%4<1&n%100>0)|n%400<1?1:0,3,2,3,2,3,3,2,3,2,3}та i+30на i+28ще 2 байти
cliffroot

1
і ще 3 байти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;}
скеля

3

Python 2, 100 байт

Тьфу. Математика з датами не така проста, як хотілося б.

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]

Спробуйте в Інтернеті

Однакова довжина:

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]

Я навіть не збирався спробувати Python з цим. Приємні зусилля.
ElPedro

3

MATL , 21 байт

12:"G@QhO6(YO9XO77=?@

Місяці відображаються у вигляді цифр.

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

Для цього використовуються вбудовані функції перетворення дат. Для даного року він перевіряє, який останній день місяця - понеділок.

Замість того, щоб чітко вказати останній день місяця k (який може бути 28, 29, 30 або 31), ми вказуємо 0-й день місяця k+1, який є еквівалентним і не залежить від місяця чи року.

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

Утиліти Bash + GNU, 56 байт

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

Здається, потрібна dateверсія 8.25. 8.23 версія в Ideone не скорочує.


3

Excel, 537 байт

Тому що - знаєте - Excel!

Приймає рік введення в А1. Повертає шістнадцятковий список місяців; 1 = січень, С = грудень. Оскільки кожен місяць є однозначним, роздільник не потрібен.

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

Приклад: A1 містить 2016. B1 містить вищевказану формулу і відображається як 2A, що означає лютий та жовтень.


3

PHP, 109 180 159 байт

for($z=$argv[1];$m++<12;)if(date(N,strtotime(sprintf("%04d-$m-",$z).cal_days_in_month(0,$m,$z)))<2)echo"$m,";
  • Виводить передбачений рік, не всі з них (... завжди читайте питання)
  • Проігноровані повідомлення (дякую Тіту)
  • Зміна whileдо , forяк це тепер один рік (знову ж , завдяки Titus)

Старий 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)."
":"";}

Підтримує всі роки від точки до 10000, а також позбувся не визначеного попередження var, про який я не знав на одному ПК. Так, він довший, ніж у старої версії, але він більш надійний.

Старий 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)."
":"";}

Якщо ви працюєте в Windows або 32-бітовій системі, з’явиться жахлива помилка 2038, але в 64-бітовій системі Linux це нормально.

Я зробив спробу використання, date("t"...який мав на увазі останню дату місяця, але результати не відповідали тим, що згадувалося в цій темі.


2
-2: "$ z" не потребує лапок -7: ігноруйте сповіщення (вони не надруковані з налаштуваннями за замовчуванням: не вводити $z, не цитувати для N) -1: forзамість while -43 : приймати введення, як вимагається, а не циклічно прокручувати роки -3: joinзамість implode-16: прямий висновок: 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, якщо ви наполягаєте на відсутності кінцевої коми:echo$o=$o?",$m":$m;
Тіт

Ах неправильно прочитав питання! Думав, що це було на всі роки .. oops: B Дякую також за інші пропозиції, отримаю на них
CT14.IT

3

PHP, 92 байт

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

перевірка 12 разів на 1 місяць після першого дня року є вівторок. Якщо це тоді, то день до останнього дня в місяці - понеділок.


Ви можете використовувати ехо замість друку та зберегти 1
Восьминіг

1
@ Октопод не в межах потрійного Оператора
Йорг Гюльсерманн

3

C, 214 байт

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

Складіть

gcc -std=c99 -o foo foo.c

Безумовно

З кредитами відповідних гуру.

Майкл Кіт та Том Крейвер для програми C, щоб знайти день тижня за датою .

Collin Biedenkapp for Q&A: Як я можу зрозуміти, який останній день місяця?

/* 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
Що робити, якщо ви перевернете ifінший напрямок, щоб elseповернутись 31, і тому ви зможете усунути великий ==ланцюг?
AdmBorkBork

1
було б краще, якщо (x == 1) {z part} else if (x == 3 || x == 5 || x == 8 || x == 10) повернути 30 return return 31
RosLuP

1
як щодо: повернення 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: спасибі за бали return (), тепер збережено 100 байт.
Стів

1
можна продовжувати зменшувати нарешті до цього: u (y, m) {повернення m-1? 30 + ((2773 >> m) & 1): 28+ (y% 4 == 0 && y% 100 || y% 400 == 0);} де y - рік і м місяць
RosLuP

3

C, 119 байт

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

Для цього використовується таблиця, яка містить зміщення буднів дня останнього дня кожного місяця за високосний рік, закодованого в підписане 32-бітове слово з використанням бази 7. Якщо це не високосний рік, ми додаємо 1 до компенсації січня (як бачите y&3||y%25<1&&y&15, використовується для перевірки роками без високосних днів). Потім ми просто перебираємо кожен місяць і перевіряємо, чи останній день - понеділок. Насправді досить просто, жодних потворних хакерів і хитрощів. Ось це трохи невольф:

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

Я можу переглянути це, щоб переписати його як функцію для збереження кількох символів. printfТакож займає трохи занадто багато місця ...


Printf ("% d,", m) надрукував би щось як 1, або 2, 3, тому завжди є одне "," більше ... я вважаю за краще використовувати лише пробіли
RosLuP

Дійсно, я також віддаю перевагу пробіли у висновку насправді, але я зазвичай пишу свої рішення C для гольфу настільки, щоб їм не потрібен пробіл, тому я можу просто занурити весь пробіл з моєї напівгольф-версії, коли хочу перевірити кількість своїх символів .
Форс

3

PHP, 96 95 76 71 69 64 61 байт

Примітка: Номери року повинні бути замінені на 4 знаки, як-от 0070.

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

Бігайте так:

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

Пояснення

Ітератує від -1 до -12. Створіть дату, використовуючи mktime, день 0(останній день попереднього місяця) та місяць 2..13. Відформатуйте дату як номер дня , і якщо результат 1, надрукуйте поточне число. Негативний знак -використовується як роздільник.

Баг тисячоліття вражає знову!

Зауважте, що в цій версії діапазон 0..100трактується як 1970..2069. Це не є проблемою для діапазону 0..69, оскільки тижні мають схему, що повторюється кожні 400 років (146097 днів, рівно 20871 тиждень), але для діапазону 70..99до числа року додається 1900, що не кратне 400. Для виправлення ця проблема ПОСЛІДНО для 30-річних чисел у діапазоні 10k, найпростіший спосіб - додати 400 до номера року, щоб запобігти двозначній інтерпретації ( +4 байти ):

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

Налаштування

  • Збережені байти, використовуючи !~-$iдля порівняння $iз 1( -1двійковим інвертованим є 0логічно зведений на немає вtrue , кожен номерfalse ), тому круглі дужки не потрібні
  • Збережено 19 байт за допомогою використання last day ofYYYY-m позначення для створення дати
  • Збережено 5 байт за допомогою dateтаstrtotime замістьdate_create
  • Збережено 2 байти шляхом підрахунку від негативних чисел, використовуючи від'ємний знак як роздільник виводу (від’ємні числа місяця не існують), а також як розмежування в YYYY-m частині дати
  • Збережено 5 байт за допомогою, mktimeа не strtotime. Повернувся до використання дня 0( mktimeтакож підтримує місяць 13, так0-13 ==31-12 )
  • Збережено 3 байти, використовуючи, -Rщоб зробити $argnдоступними

mktimeзнімає необхідність підкладати рік, чи не так?
Тит

@Titus, гострий. Ну я просто зрозумів, що mktimeце протиінтуїтивно , тому що аргументи приймаються як INTs. Це означає, що ви не можете прокладати рік ... тому все в діапазоні 0..100трактується як 1970..2070. Це не є проблемою для діапазону, 0..70оскільки 400 років мають точну кількість тижнів (тому календарі повторюють закономірність кожні 400 років), але 70..99додають 1900 (не кратне 400!). Тому нова вер. має помилку.
aross

Єдине рішення, яке я бачу зараз, - це, $argv[1]+400якщо не відрізняються будні Джуліана та Григоріана.
Тит

@Titus, так. Правила говорять про використання григоріанської
кали

3

Excel, 428 97 96 байт

Введення в А1. Вивести нерозділені шістнадцяткові значення (січень = 0, грудень = В)

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

Додано 10 байт ("+2000"), щоб дозволити обробляти дати до 1990 року.

Збережено 11 байт завдяки @ Engineer Toast .


Перша спроба (428 байт), сильно запозичивши рішення @ 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","")

Як це працює на роки раніше 1900 року? Тестовий випадок 297 -> Mayповертається 6з цією формулою. Чи не повинно бути 4? 1776дає 7Aзамість просто 8на вересень.
Інженер Тост

Якщо ви змусите його працювати, то, ймовірно, ви можете використовувати Date(A1,3,0)замість ньогоEOMONTH(DATE(A1,2,1),0)
інженер Toast

2

Bash + cal, 58 байт

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

+1 - працює для BSD cal(наприклад, OSX), але слідкуйте за пробілами в GNU cal.
Цифрова травма

2

Python 2, 94 байти

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

Неназвана функція, займає цілий рік, виводить список номерів місяця [1-12] .

Я також намагався без успіху бити кількість байтів арифметикою (110 байт). :

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)

Безіменна функція, яка повертає список булевих значень, що представляють, якщо місяці [січень-грудень] закінчуються в понеділок


2

Java 7, 200 249 байт

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

На Яві GregorianCalendar- це суміш між григоріанським та юліанським календарем. Через це рік 1дав неправильні результати. Зміна Calendar c=Calendar.getInstance();в GregorianCalendar c=new GregorianCalendar();c.setGregorianChange(new Date(1L<<63));це виправлено, змушуючи використовувати тільки за григоріанським календарем. Дякую @JonSkeet на stackoverflow.com, що він мені пояснив це.

Невикористаний і тестовий код:

Спробуйте тут.

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

Вихід:

4 12
5 
9 
1 7 
2 10 
1 2 10 

2

C # 6 C #, 171 167 135 байт

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 байти завдяки Шебангу

Друкувати місяці як цифри; з обмеженим простором; із заднім простором. Тепер ця відповідь працює і для більш ранніх версій C #.


Старий, 167 байт

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 байти завдяки TimmyD

Вихідні місяці - це числа у зворотному рядку з комою

Безумовно

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 Так, але потрібен чіткий склад. Відповідь оновлено
Посилання Ng

LINQ це весело , але це 126 байт: 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);}}};) Крім того , було б коротше , закидати DayOfWeekна intніж було б закидати intдоDayOfWeek
Каде

@Shebang Дякую Я дійсно не повинен займатися гольфом в однорядковій лінійці --- Лише Джон Скіт може це зробити. Подивіться, чи є в мене час на оновлення завтра. Втомився зараз.
Посилання Ng

Ви можете перетворити це, Action<int>щоб зберегти деякі байти
TheLethalCoder

2

Ruby, 54 + 6 = 60 байт

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

6 байт для -rdate командного рядка для отримання класу Date зі стандартної бібліотеки.

Пояснення: досить просте завдяки чудовому Dateкласу Ruby stdlib . Мало того, що у нього є такі методи, як monday?, tuesday?тощо., Конструктор прийме від'ємні числа за будь-яке поле минулого року, щоб означати "рахувати це поле назад з кінця періоду, представленого попереднім полем". $*це скорочення ARGV, тому $*[0]це швидкий спосіб отримати перший аргумент командного рядка.


2

PHP, 84 байти

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

Мій перший гольф Code. Це найкоротший PHP до цього питання.

EDIT: начебто, не працює перший рік. Мені доведеться з’ясувати, чому, але зараз мені потрібно йти.


1
Я б сказав "Ласкаво просимо до PPCG!" але ти тут зареєстрований довше, ніж я! : D Гарний перший гольф.
AdmBorkBork

Ваша помилка в тому, що ви створюєте 1-13-1 і 1-14-1 за рік 1 <13 достатньо. Якщо ви вирішите це, ви можете зняти непотрібні дужки в даний момент і подумати про те, щоб скористатися
термінальним

Це повинно вирішити ваші проблемиfor(;$m++<12;)strftime("%w",strtotime($argv[1]+($m/12^0)."-".($m%12+1)."-1"))!=2?:print"$m ";
Йорг Гюльсерманн,

2

R, 106 99 95 83 78 77 74 байт

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

Послідовність останніх днів кожного місяця задається seq(as.Date(paste0(x,-2,-1)),,'m',12)-1:

  • paste0примушує -2 і -1 до символів. Якщо, xнаприклад, 2016 рік,paste0(x,-2,-1) дає , "2016-2-1"який потім перетворюється в 1 лютого 2016 року по as.Date.

  • seqзастосовано до POSIXct або об'єкта Date seq(from, to , by, length.out): тут toне вказано, byзадається те, 'm'що відповідає 'month'частковому збігу, і length.out, звичайно, 12.

  • Отримана послідовність є першим днем ​​12 місяців, починаючи з лютого відповідного року. -1дає нам тоді останній день 12 місяців, починаючи з січня відповідного року.

Тестові приклади:

> 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

Стара версія в 95 байт, виводить назви місяців, а не лише їх кількість:

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

Ця відповідь просто геніальна. Я не мав уявлення, seqчи є метод для Date-об'єктів, і це вирішує питання про as.Dateневиправлення років вище 10000в моїй видаленій відповіді.
Billywob

@Billywob так seq.Dateі seq.POSIXtдуже вражає: вони навіть можуть обробляти команди, такі як seq(time1, time2, by="10 min")або seq(date1, date2, by="quarter"). Дуже корисно при побудові часового ряду.
планнапус

2

Japt, 24 байти

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

Перевірте це в Інтернеті!Виводить масив чисел, зfalse замість місяців, які не закінчуються в понеділок.

У інтерпретаторі була помилка, яка не дозволила мені використовувати Ðв тілі функції £. Після виправлення помилки та іншого доповнення функції, це 18 байт у поточному комітеті:

Do1@Ð400+UX e ¥2©X

1

Java, 143 129 байт

Тут використовується новий API часу 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;}

Вихідні дані

Зауважте, що в кожному рядку в кінці є додаткове місце.

4 12 
5 
9 
1 7 
2 10 
1 2 10 

Безгольовий і тестування

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

Гоління

  1. 143 - 129 байт: використовуйте DayOfWeek::ordinalдля порівняння з числовою константою замість константи enum.
    Дякую @TimmyD за загальну ідею, якщо не точне рішення! ;-)

@TimmyD, на жаль, це перерахунок. getValue()Однак у нього є метод, який би заощадив кілька байт.
Целос

@Celos ordinal()економить ще 1 байт порівняно з getValue(), хоча рекомендується ніколи не використовувати його.
Олів'є Грегоар

так, гарне мислення. Я опублікував свій коментар без попереднього оновлення, тому не побачив вашої відповіді та редагування.
Целос

1

GNU awk, 80 байт

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

Приклад

$ gawk '{for(;m<13;a=mktime($0" "++m" 1 9 0 0")){if(strftime("%w",a-8e4)~1){print m-1}}}' <<<2016
2
10
$
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.