Найти последнее воскресенье в каждом месяце данного года


21

Решения F # известны внутри 140 символов , и это проблема кода Розетты .

Требуемый результат в stdout или в строковой переменной для года ввода 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

Как было запрошено, на 1900 год:

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

И 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

Из-за того, что на большинстве языков даты кажутся неловкими. Надеюсь увидеть их больше, чем разрешить библиотеки дат! Но если он не относится к базовому языку, объявите его в названии поста (например, C # + Joda Skeet's NodaTime).

Разъяснения:

  • Годовой диапазон от 1900 до 3015
  • Григорианский календарь
  • Если это имеет значение, то, что является обычным для Великобритании / Лондона.
  • Программа, использующая переключатель командной строки или стандартный ввод, работает нормально, выдает результат в стандартный вывод
  • Функция, принимающая значение года и возвращающая строку, тоже подойдет.

Стандартные лазейки исключены . Ждем решений APL, J, K и увидим несколько новых библиотек дат.


@ Sp3000 - 1752 может быть особенно неловко :-)
брезгливое оссифраж

@ MartinBüttner: Пожалуйста, используйте библиотеки дат, отредактировали вопрос, чтобы попросить людей объявить тех, кого они используют с языком.
Фил Х

1
Вы должны указать диапазон лет, которые являются действительными входными данными, и соображения о григорианском усыновлении. (Т. Е. Если диапазон лет включает любые до 1930 года, то следует указать, что григорианский календарь должен использоваться для всего диапазона независимо от локали; или что выходные данные могут варьироваться в зависимости от локали; или вы должны указать дату отсечения, до которой следует использовать юлианский календарь и тестовые случаи в течение трех лет с момента замены).
Питер Тейлор

1
@squeamishossifrage: я ограничил его 1900 годом и григорианским, потому что я бы предпочел избежать исследовательского проекта по созданию спецификации ...
Фил Х

1
@ Adám: Извините, что заставил вас так долго ждать ответа :) Да, действительно.
Фил Х

Ответы:


1

Dyalog APL с cal от dfns , 19 байтов

Лучше поздно, чем никогда!

Запрашивает год, возвращает список дат в формате гггг мд .

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

запросить числовой ввод и пусть это будет левый аргумент

{... анонимная функция (см. ниже) применяется к каждому из

⍳12 цифры от 1 до 12 (месяцы)

Вышеуказанная анонимная функция выглядит следующим образом:

⍺⍵, добавить левый и правый аргументы (например, год и месяц), чтобы

2↑ первые два символа

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

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

⍺⍵ левый аргумент и правый аргумент (год и месяц)

TryAPL онлайн:

  1. Вернитесь на эту страницу после нажатия здесь для импорта calи его зависимостей.

  2. Нажмите здесь, чтобы запустить тестовые случаи.


Очень хорошо. Я надеялся на библиотеку APL, которая понимала, что означают даты, но cal - это разумно!
Фил Х

@PhilH дата и дни ?
Адам

1
@PhilH Также есть пространство имен Dates от MiServer.
Адам

1
@PhilH И двоичные примитивы Dyalog APL + - < = и работа с объектами даты .Net .
Адам

7

Рубин, 91 + 6 = 97

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

Работает довольно хорошо. select(&:sunday?)довольно, и удивительно, *' 'делает все форматирование само по себе.


Хорошие трюки! Вы можете сохранить еще три символа, используя chunkвместо group_by.
Кристиан Лупаску

Так что я могу, мило.
гистократ

6

Баш 4.х + нкал, 57

Если разделители новой строки в порядке вместо пробелов, то мы можем удалить -nпереключатель и завершающий пробел из echoоператора. И я думаю, что это все еще будет работать без шебанга, поэтому я тоже это убрал:

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

Оригинальный скрипт (73 байта):

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

Использование:

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

Примечание. Версии Bash до 4.0 не будут содержать начальные нули месяцев. Это можно исправить с добавлением 5 символов, изменив {01..12}на `seq -w 1 12)`. Кроме того, это tail -c-3может вызвать проблемы в некоторых системах, где вывод ncalвключает в себя конечные пробелы, но я не знаю ни одного, что делает.


1
Разница действительно связана с Дарвином, а не только с версией Bash? Был добавлен в Bash 4.0 (хотя позже в нем были некоторые ошибки). Во всяком случае, 1 персонаж все еще может быть избавлен с помощью `…`вместо хорошей привычки $(…).
Манатворк

Ах, может быть. Дарвин говорит, что использует версию 3.2.53; Debian использует 4.1.5.
брезгливое оссифраж

@manatwork PS Только что заметил ваш комментарий по поводу обратных тиков. Хороший улов, спасибо!
брезгливое оссифраж

Я не думаю, что вам нужно считать #!/bin/bashв целях игры в гольф.
Цифровая травма

@DigitalTrauma Это хорошо. Похоже, я тоже могу использовать разрывы строк вместо пробелов. Теперь до 57 байт :-)
брезгливое оссиффраж

6

IBM DFSORT, 11 3 строки по 71, 72 или 80 символов

 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) 

Два ответа с колоночным форматом вывода выдержали испытание временем. Это дает мне "цикл", вроде того, что в OUTFIL REPEAT = копирует текущую запись много раз.

Другой способ получить значение, которое кажется длиннее, но короче, так как я не могу выработать какой-либо безусловный способ справиться с 12-й записью следующего года и сделать ее условной, включая IFTHEN=(WHEN=, дважды и некоторые другие вещи. Прибыль на колебаниях (первый месяц - самый простой способ сделать это) сильно проигрывает на перекрестках (особые требования к синтаксису).

При этом используется встроенная функция (все функции в DFSORT встроены), чтобы найти последний день месяца. Затем добавляет один день (функцию), чтобы перейти к первому из следующего месяца, и использует функцию PREVDSUN, чтобы получить предыдущее воскресенье (которое всегда будет последним воскресеньем в предыдущем месяце, как и раньше).

При преобразовании года (ввода) в действительную дату для месяца используется двузначный порядковый номер, и это значение копируется также и для дня, поскольку начальная точка не имеет значения, если она действительна, как мы после последнего дня месяца изначально: 5,2короче C'01'.

Вот деталь:

OPTION COPY - копировать входной файл в выходной

OUTFIL - позволяет нескольким выходным файлам с различным выбором и форматированием создавать отформатированные отчеты. Используется предпочтительнее, чем короче INRECиз-за использования REPEAT=.

REPEAT = 12 - произвести 12 копий каждой записи. В этом примере из-за SEQNUM может быть только одна входная запись (в отличие от предыдущей версии).

5: - начать с колонки 5 записи.

SEQNUM, 2, ZD - порядковый номер, по умолчанию начинается с одной, двух цифр, «десятичного зонного» (для беззнаковых, какими они будут, так же, как и символ).

1,8 - скопировать байты 1 на длину 8 в текущее местоположение (9). Это потому, что Y4T должен видеть это 8, иначе будет использоваться другой формат даты.

Y4T - дата в формате ccyymmdd (из-за 8 перед ним).

LASTDAYM - последний день месяца (также возможны неделя, квартал и год).

TOJUL = - выводить преобразование даты для функций даты (TOJUL на один символ меньше, чем TOGREG)

9,7 - теперь, когда это 7 длинных, Y4T будет CCYYDDD.

ADDDAYS - добавляет количество дней, корректируется автоматически, если переходит в следующий месяц / год (также могут быть ADDMONS и ADDYEARS)

PREVDSUN - наступает юлианская дата, расположено предыдущее воскресенье, TOGREG, чтобы получить правильный формат вывода, с разделителем "-" (может быть любым, что вам нравится в качестве разделителя)

12X - пробелы, чтобы убрать беспорядок, который позволил нам сделать это таким коротким способом

Выход из вышеперечисленного за 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-23
2014-12-28

Что-то требуется, чтобы сказать СОРТУ, что делать. Там нет по умолчанию. OPTION COPYсамый короткий, SORT FIELDS=COPYэквивалентный, но более длинный.

Саму работу он проделал на этот раз OUTFIL(чтобы разрешить использование REPEAT). Рабочий код может быть любым из 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) или 138 (70 + 68) (исключая начальные пробелы, принудительное продолжение и конечные пробелы).

Учитывая, что получатель должен знать, что он делает, я думаю, что могу сказать, что код DFSORT для перечисления последнего воскресенья каждого месяца для любого года с 1900 года (будет выполняться с года 0001, но я избегаю исследования, так как хорошо) до 9999 (хотя DFSORT поддерживает годы до 9999, предыдущее решение не будет работать в 9999, так как 12-е число переходит в следующий год) можно твитнуть.

Почему код такой длинный, если есть особенно подходящие встроенные функции?

Определения полей эфемерны. Поле определяется только как конкретное местоположение в данных (которое является записью) для его немедленного использования. Иными словами, поля не определены как таковые, но определены для каждого использования и только для использования. Функции даты должны знать, какой (из многих) форматов даты используется для источника, и выходные данные должны быть в формате даты, так что это должно быть указано.

Теперь, когда у нас свидание в юлианском стиле ... 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) 

Нуждается в некоторых JCL

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

И входной файл (еще одна строка JCL и три элемента данных instream):

//SORTIN DD *
2014 
1900 
2000 

Производит:

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

Будет действительно работать до 9999 года.

DFSORT - это продукт IBM для сортировки мэйнфреймов. Данными можно манипулировать, но поскольку сортировка является ключевой, а сортировки часто бывают большими и длительными, у контрольных карт DFSORT нет циклических конструкций, поэтому мы не можем поместить SORT в цикл. Делает вещи немного скучными для таких задач, как гольф.

Зачем размещать ответ, потому что DFSORT имеет PREVDdayфункцию. Так что в последнее воскресенье месяца это просто. Это предыдущее воскресенье (PREVDSUN) первого дня следующего месяца.

Было также забавно делать это в пределах одного «операнда» (OVERLAY), немного похоже на то, чтобы делать все это внутри sprintfили аналогично.

Вот это не разгромлено:

 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) 

Хотя это и не совсем оскорбление, не принято пытаться втиснуть все это в один ОВЕРЛАЙ, и есть некоторые, казалось бы, ненужные вещи, которые необходимы, чтобы все это могло войти в один ОВЕРХЛЕЙ. Есть кое-что для игры в гольф, но так как он удалит только одну строчку, я не испытываю соблазна.

INREC обрабатывается для каждой записи.

OVERLAY позволяет изменять содержимое существующей записи. Если в процессе запись выходит за пределы его длины, это не проблема.

1,4 наступает год. К нему добавляется литерал 0201, а затем последовательные 1,8 повторяют это 11 раз, чтобы получить один длинный патрон из 96 байт,

К 12-му году расширенной текущей записи добавляется 1, а месяц - 1 (январь).

Оставшиеся 10 месяцев заменены на 3-11.

Тогда есть 12, в обратном порядке (из-за OVERLAY) этого типа вещи:

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

N: номер столбца в записи. X вставляет пробел. 89,8 берет данные из этого столбца / длины, Y4T обрабатывает их как дату CCYYMMDD, PREVDSUM определяет предыдущее воскресенье, TOGREG = Y4T (-) выводит их как григорианскую дату CCYY-MM-DD.

Поскольку вы получаете мусор, если источник и цель определенной части OVERLAY деструктивно перекрываются, финал 11:X,18,120,6X)переставляет и маскирует немного беспорядка.

Руководства и документы можно найти по адресу: http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 , и включает руководство по программированию приложений DFSORT на 900+ страниц.

Как и для всех продуктов IBM, все руководства доступны бесплатно (за исключением мучительно небольшого количества очень дорогих книг, которые даже очень небольшое количество людей в мире даже притворятся, что поймут).

Все контрольные карты DFSORT должны начинаться с пробела. Столбец 72 используется только для продолжения (подойдет любой непустой, но * обычный). За столбцом 72 следует область порядкового номера, которая игнорируется, делая каждую запись 80 байтов.

Может быть, еще пара решений.


5

Баш, 63 байта

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

Выход:

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

for i in {1..12};{ date -v30d -v${i}m -v$1y -v0w +%Y-%m-%d;}- 60 байт
цифровая травма

-vПараметр к dateявляется специфическим для даты BSD. Так что это работает на OSX, но не на большинстве Linux - возможно, это должно быть указано в ответе.
Цифровая травма

@DigitalTrauma, работает на Mac и моем Linux.
michael501

4

Python 2 - 189 байт

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

Введите дату через STDIN.

Еще можно поиграть в гольф. Программа идет немного за борт, просто для удовольствия:

  • Без импорта, в частности без использования каких-либо встроенных функций даты
  • Использует конгруэнтность Целлера для расчета дней недели

Примечания

  • 1322 - это волшебная таблица для определения, имеет ли месяц, не относящийся к февралю, 30 или 31 день.
  • Нет zfillнеобходимости в течение многих лет из-за диапазона ввода или дней, поскольку они всегда будут превышать 20

Python 2 - 106 байт

Решение не так весело:

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.monthrangeвозвращает два числа: день недели, с которого начинается месяц ( w), и количество дней в месяце ( n). Решение немного нелогично из-за уловки - возвращаемый день недели начинается с 0 для понедельника , а не воскресенья! Однако это компенсируется тем фактом, что nон основан на 1.


1
Очень глупый ответ $from calendar import monthrange as gt$V12AGH>QhN%"%d-%02d-%d"(QhN-H%+GH7
Pyth

3

JavaScript (ES6) 155 145

Редактировать Исправлены проблемы с часовым поясом. Может быть короче, если сделать рекурсивным. Может быть.

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

Вы можете использовать new Date(y,0,++i,9). Кроме того, это терпит неудачу в течение 2100 и более високосных лет, поскольку у JS нет информации об этих високосных годах и, таким образом, вообще нет Feb 29в високосных годах для 2100 года и выше.
Оптимизатор

@ Оптимизатор это не JS: 2100,2200,2300 не високосные годы. 2014 год високосный, и JS знает. Что касается использования часа 9, я не могу проверить, но я думаю, что это не сработает, если вы, например, в Мельбурне ...
edc65

Ах .. Никогда не знал, что мы бросаем 3 дня за 400 лет. О 9 - я изменил часовой пояс от -1000 (Гавайи) +1100 (Мельбурн) и new Date(2014,0,26,9)был воскресеньем давая правильную ISOстроку, а также в getDay()качестве 0.
Оптимизатор

3

JavaScript, ES6, 222 219 199 байт

Я не видел никакого ответа JavaScript в розетке вики.

Вот так:

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

Это создает функцию, Sкоторая возвращает строку с желаемым выводом. функция также заботится о високосных годах.

Благодаря ES6, это работает только в последней версии Firefox.

Спасибо апсиллерам за полученный совет, уменьшенный до 200 байт

Найдите приведенную ниже версию в виде фрагмента стека, которую вы можете запустить здесь:

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


Вы можете использовать + prompt () вместо parseInt и сбрить некоторые байты
Jacob

@Jacob Это приглашение не добавляется в счетчик байтов.
Оптимизатор

ОИС. Я должен был прочитать вопрос ...
Джейкоб

@apsillers Спасибо за тонну! Решил проблему и сильно ее уменьшил, основываясь на ваших советах.
Оптимизатор

Входной 2100вывод 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-02неверный.
Qwertiy

3

Реболь - 120 116 80 79 76

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


Ungolfed + некоторые аннотации:

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

Пример расчета воскресенья в консоли 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

Потенциал 87: d: 1-1-1 d / year: сделать ввод печатать сбор [повторить m 12 [d / month: m + 1 сохранить d - d / weekday]]
rgchris

@rgchris Спасибо, Крис. Был в состоянии побрить еще 7 символов этого.
draegtun

Ницца!! Это плохо, но никогда не думаешь, что FOR - это ярлык.
rgchris

2

CJam, 122 102 байта

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

Это не использует какую-либо форму библиотеки дат. Я думаю, что это все еще может быть много в гольфе.

Проверьте это здесь.


3
Я так впечатлен, что ответ CJam на этот раз не лучший ответ в соревновании по коду-гольфу. Я могу умереть счастливым .. Сегодня хороший день (очевидно, пока он не заполнен до 6 байтов)
Брэндон

@ Брэндон: Это была та причина, по которой я думал, что это будет интересно. Очень надеюсь увидеть какую-нибудь чудесную библиотеку, которая делает это легко, но пока разочарован.
Фил Х

1

R, 128 символов

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

С переносами строк:

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

1

C # 255

Ungolfed

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

Изменить: изменено для печати только в последнее воскресенье :)


Не требуется выходной формат. + Это код гольфа
edc65

1

д, 67

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

Нет ли в q библиотек дат, пригодных для этого?
Фил Х

1

"О, нет, он снова!"

Ява - 259 246 байт

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

Безголовая версия:

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

Использование:

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

Выход:

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

Еще один ответ «давайте поместим ответ Java только для ударов». Ну что ж. Но, по крайней мере, так как вы потрудились достичь этой точки моего ответа, я постараюсь утомить вас еще немного и объяснить мои рассуждения.

Метод gполучает нужный год и для каждого месяца создает GregorianCalendarобъект (месяцы идут от 0 до 11). Затем первый c.setустанавливает день недели как воскресенье, а второй объявляет, что мы хотим последнюю неделю месяца - как видно из официальной документации . В System.out.printlnраспечатывает дату этого воскресенья (если мы делаем это правильно, год будет напечатан как c.get(c.YEAR), но с использованием yснова сбривает 13 символов), месяц должен быть отформатирован для добавления ведущего нуля с января по сентябрю (и значение увеличивается, потому что, ну, месяцы здесь представлены 0-11) и печатается день последнего воскресенья. И эта процедура повторяется в течение остальных одиннадцати месяцев.


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

С переносами строк

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

Выход за 2014 год

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

Не требуется выходной формат
edc65

Там исправлено. Лучше?
Даррен Брин

0

C # 171

Функция, возвращающая строку.

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

Ungolfed

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

0

C # 194

используя Linq:

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

Ungolfed

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

Выход

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

0

Mathematica - 171

Обернутый в анонимную функцию, возвращает строку

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

Первая математика гольфа. Я чувствую, что это может быть существенно уменьшено.


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

Могло быть и хуже ^^

Моя вторая и последняя запись (не думаю, что я могу получить ее меньше)

142

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

0

Ruby 76

Использует параметр командной строки ruby sundays.rb 1900. Использует библиотеку дат.

require'date';puts (1..12).map{|m|d=Date.new($*[0].to_i,m,-1);d-d.wday}*" "
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.