Планируйте свои воскресенья!


16

Кому не нравится отдыхать в воскресенье утром летом с охлажденным пивом и телевизором, а зимой играть в бадминтон или играть в ульт с друзьями?

Я всегда думаю, что зная, сколько дней вам нужно отдохнуть в месяце, вы будете хорошо информированы и поможете спланировать, что вы хотите сделать. Будь то сидение перед компьютером и решение проблемы игры в гольф или игра в футбол.

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

Кроме того, имейте в виду, что выигрывает самый короткий код.

Ограничения ввода

1000 <= Y <= 9999

1 <= M <= 12

Выход

Эти тесты будут иметь выходные данные с датами каждого воскресенья того месяца в этом году в формате DD-MM-YYYY.

Примеры тестовых случаев

Тестовый пример 1

Пример ввода

2017 1

Пример вывода

5
01-01-2017
08-01-2017
15-01-2017
22-01-2017
29-01-2017

Тестовый пример 2

Пример ввода

2018 2

Пример вывода

4
04-02-2018
11-02-2018
18-02-2018
25-02-2018

Тестовый пример 3

Пример ввода

2016 11

Пример вывода

4
06-11-2016
13-11-2016
20-11-2016
27-11-2016

2
Я рекомендую разрешить любой формат даты, включая Date()объект, и любой формат вывода, в том числе [4, [<dateobj>, <dateobj>, <dateobj>, <dateobj>]](где <dateobj>это фактический объект даты и []фактический массив).
wizzwizz4

2
Когда выходной формат является определяющей частью проблемы, сообщество единодушно считает, что это скучно. В будущем я рекомендую использовать Песочницу, но так как никто еще не ответил, вы можете сойти с рук, изменив ее.
wizzwizz4

1
Я сделаю правку. Вы можете откатить его обратно, если считаете, что это повредит вызову.
wizzwizz4

1
Итак, насколько гибкий формат вывода? Например, может ли он иметь /вместо -? Или это может быть месяц, потом день, потом год?
Луис Мендо

1
Какой-то конкретный регион? Обратите внимание, что до 1582 года юлианский календарь использовался повсеместно, а страны перешли на григорианский еще в 1952 году для Греции. В Англии они прыгнули вперед по календарю на 11 дней в сентябре 1752 года, что привело к массовым беспорядкам. Рекомендуется использовать что-то, называемое «Proleptic Gregorian Calendar», которое притворяется, что текущий календарь использовался столько раз, сколько вам нужно.

Ответы:


0

MATL , 46 45 42 35 байт

8BhtYOw47B~+YOq&:t8XO!s310=)tnw24XO

Ввод является массивом формы [2017 1]. Формат вывода29/01/2017 .

Попробуйте онлайн! Или проверьте все тестовые случаи .

объяснение

8B       % Push [1 0 0 0] (8 in binary)
h        % Implicit input. Concatenate. Gives something like [2017 1 1 0 0 0],
         % corresponding to the first day of input year and month
tYO      % Duplicate. Convert to serial date number
w        % Swap
47B~     % Push [0 1 0 0 0 0] (47 in binary, then negated)
+        % Add. Gives something like [2017 2 1 0 0 0]: first day of next month
YO       % Convert to serial number
q        % Subtract 1. This corresponds to last day of input month
&:       % Binary range. Gives an array with 28, 29, 30 or 31 days
t8XO     % Duplicate. Convert each number to three letters telling day of the week
!s       % Transpose, Sum of each column
310=     % True for values that equal 310, which is the sum of 'Sun' in ASCII
)        % Apply as a logical index
tnw      % Duplicate, number of elements, swap. This is the first part of output
24XO     % Convert to date format 'dd/mm/yyyy'. Gives 2D char array. Implicit display

Это работает с более старыми датами (как год 1217)?
Тит


Вупс не видел ТиО.
Тит

4

Python 2 , 150, 148, 145 байтов

from calendar import*
y,m=map(int,input().split())
z=filter(None,zip(*monthcalendar(y,m))[6])
print len(z)
for i in z:print'%02d-%02d-%s'%(i,m,y)

Попробуйте онлайн!

-3 байта, делающие вещи более питоническими (используя zip и filter!)


Будет 150, если вы приведете оператор печати к предыдущей строке и добавите '02' в первый% d в строке 3.
Koishore Roy

'02' в первом% d! да. пропустил это. Благодарность! в любом случае. сохранил два байта, хотя вместо увеличения на два!
Киртана Прабхакаран

4

JavaScript (ES6), 107 байт

f=
(y,m,a=[...Array(32)].map((_,i)=>new Date(y,m-1,i)).filter(d=>d.getMonth()==m-1&!d.getDay()))=>[a.length,a]
<div oninput=o.textContent=[].concat(...f(y.value,m.value)).map((d,i)=&gt;i?d.toDateString():d).join`\n`><input id=y type=number min=1000 max=9999 value=2017><input id=m type=number min=1 max=12><pre id=o>

Редактировать: добавление явного подсчета стоит 15 байт. Форматирование вывода будет стоить как минимум еще 33 байта в зависимости от того, насколько строгим является формат вывода.


> outputs the number of Sundays in that particular year and month; Похоже, что это не выводит количество воскресений.
Numbermaniac

Вы могли бы использовать <input type='date'>.
Мэтью Ро,

@SIGSEGV Пока не поддерживается в Firefox, которым я и пользуюсь.
Нил

2
@Neil Используйте Chrome m8
Мэтью Ро

3
@SIGSEGV Мне нравится Chrome даже меньше, чем Internet Explorer.
Нил

2

PowerShell , 91 байт

param($y,$m)($a=(1..31|%{Date "$m/$_/$y"}|?{!$_.dayofweek})).count;$a|%{"{0:d-M-yyyy}"-f$_}

Попробуйте онлайн!

(Особое примечание - это зависит от настроек локали и культуры. Поскольку TIO работает какen-us , он работает там, где есть, и может потребоваться изменить этот код для разных локалей.)

Принимает ввод как два целых числа $yи $m. Переходя от 1к к 31, получая новый datetimeобъект для каждой возможной даты (через Get-Dateкомандлет). Будет выбрасывать ошибки в STDERR (по умолчанию игнорируется при вызовах кода-гольфа) в течение месяцев с количеством дней менее 31, но это не влияет на результат. Мы берем каждый из этих datetimeобъектов и используем для них Where-Object( |?{...}) с предложением !$_.dayofweek. Свойство .dayofweekпредставляет собой число от 0до 6, с 0удобным соответствием Sunday, поэтому значение !true, которое экономит пару байт по сравнению с проверкой равенства, например-eq0 .

Затем воскресенья собираются в парен и хранятся в $a. Затем мы берем .countих, и это помещается на конвейер. Далее мы перебираем цикл $aи используем -fоператор ormat для создания правильного выходного формата. Обратите внимание, что это не выводит лидирующие нули в течение нескольких дней или месяцев. Эти строки даты также остаются в конвейере, и неявное Write-Outputпри завершении программы печатает их с разделителями новой строки.


NB. Если бы выходной формат был более гибким, мы могли бы просто оставить его $aв конвейере, и не нужно было бы проходить через него. Это преобразует datetimeобъекты в формат длинных дат, включающий информацию о времени, но сокращает нас до 69 байтов , которые (в настоящее время) будут побеждены только Mathematica и MATL.


1

Октава, 72 байта

@(y,m)cellfun(@disp,flip({datestr(x=nweekdate(1:6,1,y,m)(x>1)),nnz(x)}))

nweekdateвозвращает номер даты, соответствующий N-ому вхождению определенного дня недели в указанный месяц / год. Мы используем массив 1:6вместо, Nчтобы получить все вхождения за месяц. Если число Nдней недели в этом месяце меньше, чем число , то результирующий номер даты равен 0. По этой причине мы выбираем только действительные даты, используя, (x>1)а затем конвертируем их в строки, используя datestr.

Затем, чтобы посчитать количество воскресений, мы посчитаем количество ненулевых ( nnz) чисел даты в результате.

Затем мы оборачиваем все, cellfunчтобы отобразить каждое значение.


0

Рубин, 140 132 129 118 байт

require'date'
d=Date.parse gets.split*?-+'-1'
s=(d...d>>1).select &:sunday?
puts s.size,s.map{|d|d.strftime'%d-%m-%Y'}

0

Excel - 103 символа

Поместите год в ячейку A1и месяц в ячейку A2.

Количество в ячейке D1, а воскресенье в ячейках D2:D6.

Предположения D2:D6отформатированы ДД-ММ-ГГГГ.

   A      B       C              D
1  [year] [month] =DATE(A1,B1,1) =COUNTIF(D2:D7,">0")
2                                =C1+7-WEEKDAY(C1,2)
3                                =D2+7
4                                =D3+7
5                                =D4+7
6                                =IF(MONTH(D5+7)=MONTH(C1),D5+7,"")

0

Mathematica, 82 68 байт

d=DateObject;{Length[x=DayRange[d@{#,#2,1},d@{#,#2+1,0},Sunday]],x}&

Анонимная функция. Выводит список количества дней, за которым следует список воскресений как DateObjects. Оказывается, в Mathematica 0-й день месяца интерпретируется как последний день предыдущего месяца.


0

C #, 183 байта

y=>m=>{var s=new string[6];int i=1,n=0;for(DateTime d;i<=DateTime.DaysInMonth(y,m);)if((int)(d=new DateTime(y,m,i++)).DayOfWeek<1)s[++n]=d.ToString("dd-MM-yyyy");s[0]=n+"";return s;};

Анонимный метод, который возвращает массив строк, содержащий сначала количество воскресений, а затем каждое воскресенье в указанном формате. Если в месяце только 4 воскресенья, последняя строка равна нулю.

Полная программа с методикой ungolfed и тестовыми примерами:

using System;

class P
{
    static void Main()
    {
        Func<int, Func<int, string[]>> f =
        y=>m=>
        {
            var s=new string[6];
            int i=1,n=0;
            for(DateTime d;i<=DateTime.DaysInMonth(y,m);)
                if((int)(d=new DateTime(y,m,i++)).DayOfWeek<1)
                    s[++n]=d.ToString("dd-MM-yyyy");

            s[0]=n+"";
            return s;
        };

        // test cases:
        var result = f(2017)(1);
        foreach (var x in result)
            Console.WriteLine(x);

        result = f(2018)(2);
        foreach (var x in result)
            Console.WriteLine(x);

        result = f(2016)(11);
        foreach (var x in result)
            Console.WriteLine(x);
    }
}

0

REXX, 168 байт

arg y m
signal on syntax
do d=1 to 31
  m=right(m,2,0);d=right(d,2,0)
  if date(w,y||m||d,s)='Sunday' then queue d'-'m'-'y
  end
syntax:n=queued()
say n
do n
  pull a
  say a
  end

Я думаю, это не работает с меньшими годами. Ты пробовал 1217?
Тит

0

Bash + bsdmainutils, 94 байта

a=(`for i in $(cal $2 $1|cut -b1-2);{ echo $i-$2-$1;}`);echo $[${#a[@]}-1];fmt -1 <<<${a[@]:1}

Использует команду cal которая печатает календарь, устанавливается по умолчанию в нескольких UNIX / LINUX / BSD (к сожалению, не в TIO).

Для того, чтобы попробовать сохранить на file, chmod +x fileи запустить./file 2017 9

Сохраняет в массив первые два байта выходных данных калибровки, к которым добавляется строка «MM-YYYY», передаваемая в качестве второго и первого параметров (необходимо изменить, если ваша локаль не запускается неделями по воскресеньям).

Далее отражается длина массива, вычтенная одним (первый элемент - слово, представляющее воскресенье) и массив без первого элемента, по одному на строку fmt -1


Он обрабатывает особый случай 1752 9
marcosm

0

SAS, 182 байта

%macro s(y,m);%let c=%eval(%sysfunc(intck(week,%sysfunc(nwkdom(1,1,&m,&y)),%sysfunc(nwkdom(5,1,&m,&y))))+1);%put&c;%do i=1%to&c;%put%sysfunc(nwkdom(&i,1,&m,&y),ddmmyy10.);%end;%mend;

0

T-SQL, 316 311 байт

DECLARE @ DATE=DATEADD(ww,-52*(2017-@y),'20170101')IF DATEPART(d,@)>7SET @=DATEADD(ww,-1,@);WITH c(d)AS(SELECT d FROM(SELECT DATEADD(ww,ROW_NUMBER()OVER(ORDER BY name)-1,@)d FROM sys.stats)a WHERE @y=DATEPART(yy,d)AND @m=DATEPART(m,d))SELECT CAST(COUNT(*)AS CHAR(1))FROM c UNION SELECT CAST(d AS CHAR(10))FROM c

Я не знаю, если это правильный ответ, так как он выводит количество воскресений после даты

Попробуй здесь

ungolfed:

DECLARE @m INT = 1,@y INT = 2017

DECLARE @ DATE=DATEADD(ww,-52*(2017-@y),'20170101')

IF DATEPART(d,@)>7
    SET @=DATEADD(ww,-1,@)

;WITH c(d)
AS
(SELECT d 
 FROM (SELECT DATEADD(ww,ROW_NUMBER()OVER(ORDER BY name)-1,@)d 
       FROM sys.stats) a 
 WHERE @y = DATEPART(yy,d)
   AND @m = DATEPART(m,d)
)

SELECT CAST(COUNT(*) AS CHAR(1))
FROM c 
UNION 
SELECT CAST(d AS CHAR(10))
FROM c

0

PHP 127 118 112 107 байт

for([,$y,$m]=$argv;$d++<date(t,($t=strtotime)($y.-$m));)date(w,$t($s="
$d.$m.$y"))?:$r.=$s.!++$c;echo$c,$r;

принимает входные данные из аргументов командной строки; запустить -rили проверить это онлайн .

сломать

for([,$y,$m]=$argv;                     # import arguments to $y and $m
    $d++<date(t,strtotime($y.-$m))      # loop while ($d < number of days in that month)
    ;)
    date(w,strtotime($s="\n$d.$m.$y"))?:    # if date(w) is falsy (0 == sunday)
        $r.=$s.!++$c;                       # then append date to $r and increment $c
echo$c,$r;                              # print result

0

Excel VBA, 190 байт

Function p(y, m)
d = CDate("1/" & m & "/" & y)
e = DateAdd("m", 1, d)
Do While d < e
    If Weekday(d) = 1 Then Debug.Print d: i = i + 1
    d = d + 1
Loop
Debug.Print i
End Function

Пример вывода для p (2000, 1) (не уверен, соответствует ли это)

02-01-2000 
09-01-2000 
16-01-2000 
23-01-2000 
30-01-2000 
 5 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.