Plan your Sundays!

16

3

Who doesn't like to chill on a Sunday morning in summer with a chilled beer and TV or in winter playing badminton or ultimate with friends?

I always think knowing how many days you have to chill in a month keeps you well-informed and helps you plan what you want to do. Be it sitting in front of your pc and solving a code-golf problem or going out to play football.

So, help me write a program or function which takes as input 2 positive integers, Y and M and outputs the number of Sundays in that particular year(Y) and month(M) (according to the Gregorian Calendar), followed by the date of each Sunday.

Also, do keep in mind that the shortest code wins.

Input Constraints

1000 <= Y <= 9999

1 <= M <= 12

Output

These test cases will have output will have the dates of each Sunday of that month in that year in the format DD-MM-YYYY.

Sample Test Cases

Test Case 1

Sample Input

2017 1

Sample Output

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

Test Case 2

Sample Input

2018 2

Sample Output

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

Test Case 3

Sample Input

2016 11

Sample Output

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

Koishore Roy

Posted 2017-04-09T09:22:09.503

Reputation: 1 144

2I recommend allowing any date format, including a Date() object, and any output format, including [4, [<dateobj>, <dateobj>, <dateobj>, <dateobj>]] (where <dateobj> is an actual date object, and [] is an actual array). – wizzwizz4 – 2017-04-09T09:33:34.770

Wont that make it too easy? The least number of bytes can probably be achieved in PHP, regardless of format. I'm looking for the most clever solution in any other language (read: Python, Java, Scala, Perl, C++, JavaScript) – Koishore Roy – 2017-04-09T09:39:44.190

2When the output format is the defining part of a challenge, community consensus is that it's boring. In future I recommend using the Sandbox, but as nobody's answered yet you could get away with changing it. – wizzwizz4 – 2017-04-09T09:46:14.523

I'm new to making questions. Can you help me out here and change the question to make it better? @wizzwizz4 – Koishore Roy – 2017-04-09T09:57:00.537

1I'll make an edit. You can roll it back if you think it damages the challenge. – wizzwizz4 – 2017-04-09T10:01:20.223

I doubt it'll damage the challenge. Thanks for the help. :) – Koishore Roy – 2017-04-09T10:02:31.390

1So how flexible is the output format? For example, can it have / instead of -? Or can it be month, then day, then year? – Luis Mendo – 2017-04-09T17:06:54.997

1Any particular locale? Note that prior to 1582, the Julian calendar was in common use, with countries transitioning to Gregorian as late as 1952 for Greece. In England they jumped the calendar ahead 11 days in the month of September, 1752, leading to mass riots. Recommendation is to use something called the "Proleptic Gregorian Calendar" which pretends the current calendar was in use for as far back as you need. – None – 2017-04-09T19:01:38.867

Read the question. I've clearly mentioned Gregorian Calendar. Even the range of years is given – Koishore Roy – 2017-04-09T22:47:32.380

1Would you please answer my question (previous comment) about output format? In comments you seem to agree that the format is flexible, but the challenge doesn't clarify this – Luis Mendo – 2017-04-09T23:36:53.633

DD-MM-YYYY. Feel free to use ".", "-" or "/". – Koishore Roy – 2017-04-10T12:09:52.733

Thanks for answering. You should incorporate that into the challenge text. People are not expected to read the comments – Luis Mendo – 2017-04-10T22:01:33.647

Answers

0

MATL, 46 45 42 35 bytes

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

Input is an array of the form [2017 1]. Output format is 29/01/2017.

Try it online! Or verify all test cases.

Explanation

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

Luis Mendo

Posted 2017-04-09T09:22:09.503

Reputation: 87 464

Does this work with older dates (like year 1217)? – Titus – 2017-04-14T15:36:11.577

Woops didn´t see the TiO. – Titus – 2017-04-14T15:39:33.600

4

JavaScript (ES6), 107 bytes

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>

Edit: Adding an explicit count cost 15 bytes. Formatting the output would cost at least another 33 bytes depending on how strict the output format is.

Neil

Posted 2017-04-09T09:22:09.503

Reputation: 95 035

ockquote>

outputs the number of Sundays in that particular year and month; looks like this doesn't currently output the number of Sundays.

– numbermaniac – 2017-04-09T11:42:38.937

You could use <input type='date'>. – Matthew Roh – 2017-04-09T11:56:25.673

@SIGSEGV Not yet supported in Firefox, which is what I use. – Neil – 2017-04-09T15:00:44.850

2@Neil Use Chrome m8 – Matthew Roh – 2017-04-09T15:14:25.580

3@SIGSEGV I like Chrome even less than Internet Explorer. – Neil – 2017-04-09T16:18:21.283

4

Python 2, 150,148,145 bytes

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)

Try it online!

-3 bytes making stuff more pythonic (using zip and filter!)

Keerthana Prabhakaran

Posted 2017-04-09T09:22:09.503

Reputation: 759

It'll be 150 if you bring the print statement up to the previous line and if you add '02' in the first %d in line 3. – Koishore Roy – 2017-04-09T14:10:15.703

'02' in the first %d ! huh. missed that. Thanks! anyways. saved two bytes though instead of increasing by two! – Keerthana Prabhakaran – 2017-04-09T14:12:33.627

2

PowerShell, 91 bytes

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

Try it online!

(Special note - this is locale and culture settings dependent. Since TIO is running as en-us, it works correctly there as-is. This code may need to be changed for different locales.)

Takes input as two integers $y and $m. Loops from 1 to 31, getting a new datetime object for each possible date (via the Get-Date cmdlet). Will toss errors to STDERR (ignored by default on code-golf challenges) for months with fewer than 31 days, but that doesn't affect output. We take each of those datetime objects and use a Where-Object (|?{...}) on them, with the clause of !$_.dayofweek. The property .dayofweek is a number from 0 to 6, with 0 conveniently corresponding to Sunday, so the ! of that is truthy, which saves a couple bytes compared to an equality check like -eq0.

The Sundays are then gathered in parens and stored into $a. We then take the .count thereof, and that's placed on the pipeline. Next, we loop through $a and use the -format operator to construct the correct output format. Note that this doesn't output leading zeros for days or months. Those date strings are also left on the pipeline, and an implicit Write-Output at program completion prints them with newline separators.


NB - if the output format was more flexible, we could just leave $a on the pipeline and not need to loop through it. That will stringify the datetime objects as the long-date format including time information, but gets us down to 69 bytes, which would (currently) only be beaten by Mathematica and MATL.

AdmBorkBork

Posted 2017-04-09T09:22:09.503

Reputation: 41 581

1

Octave, 72 bytes

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

nweekdate returns the date number corresponding to the N-th occurrence of a particular weekday in the specified month/year. We use the array 1:6 in place of N to get all occurrences in a month. If there are fewer than N occurrences of that weekday in a month, then the resulting date number is 0. For this reason, we select only the valid dates using (x>1) and then convert them to strings using datestr.

Then to count the number of Sundays, we count the number of non-zero (nnz) date numbers in the result.

We then wrap the entire thing in cellfun to display each value.

Suever

Posted 2017-04-09T09:22:09.503

Reputation: 10 257

0

Mathematica, 82 68 bytes

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

Anonymous function. Outputs a list of the number of days, followed by a list of the Sundays as DateObjects. Turns out, in Mathematica the 0th day of a month is interpreted as the last day of the previous month.

numbermaniac

Posted 2017-04-09T09:22:09.503

Reputation: 639

0

Ruby, 140 132 129 118 bytes

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

emlai

Posted 2017-04-09T09:22:09.503

Reputation: 101

0

Excel – 103 characters

Put the year in cell A1, and month in cell A2.

The count is in cell D1, and Sundays in cells D2:D6.

Assumes D2:D6 are formatted DD-MM-YYYY.

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

user15259

Posted 2017-04-09T09:22:09.503

Reputation:

0

C#, 183 bytes

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

Anonymous method which returns an array of string, containing first the number of Sundays and then each Sunday in the specified format. If there are only 4 Sunday in a month, the last string is null.

Full program with ungolfed method and test cases:

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

adrianmp

Posted 2017-04-09T09:22:09.503

Reputation: 1 592

0

REXX, 168 bytes

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

idrougge

Posted 2017-04-09T09:22:09.503

Reputation: 641

I guess this does not work with smaller years. Have you tried 1217? – Titus – 2017-04-14T15:36:53.463

0

Bash + bsdmainutils, 94 bytes

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

Uses the command cal which prints a calendar, is installed by default in several UNIX/LINUX/BSD (unfortunately not in TIO).

To try it save to file, chmod +x file, and run ./file 2017 9

Saves to array a the first two bytes of cal output appended with the string "MM-YYYY" passed as second and first parameters (needs change if your locale does not starts weeks on sundays).

Next echoes array length substracted by one (first element is the word representing sunday) and the array without the first elemet, one per line fmt -1

marcosm

Posted 2017-04-09T09:22:09.503

Reputation: 986

It handles special case 1752 9 – marcosm – 2017-04-11T12:34:00.620

0

SAS, 182 bytes

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

J_Lard

Posted 2017-04-09T09:22:09.503

Reputation: 351

0

T-SQL, 316 311 bytes

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

I don't know if it is a valid answer though, since it outputs the number of sundays after the dates

Try it here

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

grabthefish

Posted 2017-04-09T09:22:09.503

Reputation: 161

0

PHP, 127 118 112 107 bytes

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

takes input from command line arguments; run with -r or test it online.

breakdown

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

Titus

Posted 2017-04-09T09:22:09.503

Reputation: 13 814

0

Excel VBA, 190 bytes

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

Sample Output for p(2000, 1) (not sure if this qualifies)

02-01-2000 
09-01-2000 
16-01-2000 
23-01-2000 
30-01-2000 
 5 

Stupid_Intern

Posted 2017-04-09T09:22:09.503

Reputation: 373