29
\$\begingroup\$

Monday, October 31st, is Halloween. And it got me thinking -- I wonder what other months have the last day of the month also be a Monday?

Input

  • A positive integer in any convenient format representing a year, 10000 > y > 0.
  • The input can be padded with zeros (e.g., 0025 for year 25) if required.

Output

  • A list of the months of that year where the last day of the month is a Monday.
  • This can be as month names (e.g., January, March, October), or shortnames (Jan, Mar, Oct), or numbers (1, 3, 10), as separate lines or a list or delimited, etc., just so long as it's unambiguous to the reader.
  • The output format must be consistent:
    • For all years input (meaning, you can't output month names for some inputs, and month numbers for other inputs)
    • As well as consistent per output (meaning, you can't output 1 for January in the same output as Jul for July)
    • Basically, pick one format and stick to it.

Rules

  • Assume the Gregorian calendar for input/output, even down to y = 1.
  • Leap years must be properly accounted for (as a reminder: every year divisible by 4, except not years divisible by 100, unless also divisible by 400 -- 1700, 1800, 1900 all weren't leap years, but 2000 was).
  • You may use any built-ins or other date calculation tools you like.
  • Either a full program or a function are acceptable. If a function, you can return the output rather than printing it.
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply, and the shortest code (in bytes) wins.

Examples

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

Leaderboard

var QUESTION_ID=97585,OVERRIDE_USER=42963;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

\$\endgroup\$
9
  • 1
    \$\begingroup\$ Related 1 and Related 2. \$\endgroup\$ – AdmBorkBork Oct 26 '16 at 18:33
  • 1
    \$\begingroup\$ Related but not duplicates or? \$\endgroup\$ – ElPedro Oct 26 '16 at 20:13
  • \$\begingroup\$ @ElPedro Related but not duplicates. The first does not allow any built-ins and asks for a fixed date/day combo (Friday the 13th), while the second asks for the last Sunday of every month of the year, limited between 1900 to 3015. \$\endgroup\$ – AdmBorkBork Oct 26 '16 at 20:17
  • \$\begingroup\$ Sorry @TimmD. My misunderstanding of your comment. \$\endgroup\$ – ElPedro Oct 26 '16 at 20:56
  • 1
    \$\begingroup\$ @ElPedro No problem! I would rather have a question and have it be clear, than to not have a question and have something unclear. \$\endgroup\$ – AdmBorkBork Oct 26 '16 at 20:57

39 Answers 39

1
2
1
\$\begingroup\$

C, 175 217 bytes

#define R return
#define L(i) for(;i-->0;) 
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}s(y,m,g){g+=4;L(m)g+=u(y,m),g%=7;L(y)g+=1+u(y,1),g%=7;R g;}w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}

Code for to find the last day for febrary taken from K&R2; try http://ideone.com/XtuhGj the function for debug is w

z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}

/*    
// ritorna il numero dei giorni di anno=y mese=m con mese in 0..11
// m==1 significa febbraio   y%4?0:y%100?1:!(y%400) non funziona
u(y,m){R m-1?30+((2773>>m)&1):28+(y%4==0&&y%100||y%400==0);}

// argomenti anno:y[0..0xFFFFFFF]  mese:m[0..11]  giorno:g[1..u(y,m)]
// ritorna il numero del giorno[0..6]
s(y,m,g)
{g+=4; // correzione per il giorno di partenza anno mese giorno = 0,1,1
 L(m)g+=  u(y,m),g%=7; // m:0..m-1  somma mod 7 i giorni del mese dell'anno y
 L(y)g+=1+u(y,1),g%=7; // y:0..y-1  somma mod 7 gli anni da 0..y-1
                       // g+=1+u(y,1) poiche' (365-28)%7=1 e 1 e' febbraio
 R g;
}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
// calcola tutti gli ultimi giorni del mese dell'anno y che cadono di lunedi'
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
w(y,m,r){m=12;L(m)s(y,m,u(y,m))||(r|=1<<(m+1));R r;}

// argomenti anno:y[0..0xFFFFFFF], m=0 r=0 
//ritorna in r il numero dei mesi che ha giorno 13 di venerdi[==4]
// e mette tali mesi come bit, dal bit 1 al bit 12 [il bit 0 sempre 0] in r
z(y,m,r){m=12;L(m)s(y,m,13)-4||(r|=1<<(m+1));R r;}
*/

#define P printf
#define W while 
#define M main 
#define F for
#define U unsigned
#define N int
#define B break
#define I if
#define J(a,b)  if(a)goto b
#define G goto
#define P printf
#define D double
#define C unsigned char
#define A getchar()
#define O putchar
#define Y malloc
#define Z free
#define S sizeof
#define T struct
#define E else
#define Q static
#define X continue
M()
{N y,m,g,r,arr[]={1,297,1776,2000,2016,3385}, arr1[]={2016,1,1997,1337,123456789};
 C*mese[]={"gen","feb","mar","apr","mag","giu","lug","ago","set","ott","nov","dic"};
 C*giorno[]={"Lun","Mar","Mer","Gio","Ven","Sab","Dom"};
 P("Inserisci Anno mese giorno>");r=scanf("%d %d %d", &y, &m, &g);
 P("Inseriti> %d %d %d r=%d\n", y, m, g, r);
 I(r!=3||m>12||m<=0||g>u(y,m-1))R 0;
 r=s(y,m-1,g);// 12-> 11 -> 0..10
 P("Risultato=%d giorno=%s\n", r, giorno[r]);
 r=w(y,0,0);P(" r=%d ", r);P("\n");
 F(m=0;m<6;++m)
        {P("N anno=%d -->",arr[m]); 
         r=w(arr[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }
 F(m=0;m<4;++m)
        {P("N anno=%d -->",arr1[m]); 
         r=z(arr1[m],0,0); // ritorna in r i mesi tramite i suoi bit...
         F(y=1;y<13;++y) I(r&(1<<y))P("%s ",mese[y-1]);
         P("\n");
        }

}
\$\endgroup\$
1
\$\begingroup\$

JavaScript, 65 bytes

v=>[...""+1e11].map((x,i)=>new Date(v+400,++i).getDay()==2?i:"")

Stealing the ""+1e11 trick from the other JavaScript answer.

Returns ["", 2, "", "", "", "", "", "", "", 10, "", ""] for 2016, indicating that Feb and Oct end on a Monday.

Edited: Years 0-99 are parsed as 1900-1999 in JS. Adding 400 causes them to be parsed as 400-499, which are equivalent calendar years.

\$\endgroup\$
0
1
\$\begingroup\$

PowerShell Core, 73 65 bytes

param($a)1..12|?{"$_/1/$a"|get-date|% *hs 1|% *ys -1|? d*k -eq 1}

This requires the regional settings to use the en-US date format.

Explanations

Assumes the year is a string with padded zeros:

param($a)                     # Declares an input variable
1..12                         # Creates a range for each month
 |?                           # Filters each month
  {"$_/1/$a"                  # Creates a date for the first of the month Month/Day/Year
   |get-date
   |% *hs 1                   # *hs calls AddMonths
   |% *ys -1                  # *hs calls AddDays, -1 goes to the last day of the previous month
   |? d*k -eq 1}              # d*k calls DayOfWeek, 1 is the int value for the DayOfWeek.Monday

Thanks to mazzy for the idea of piping parameters into get-date!

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ [datetime]::new is really shorter! Nice! +a bit of CodeGolf \$\endgroup\$ – mazzy Nov 5 '20 at 9:47
  • 1
    \$\begingroup\$ -3 bytes :) \$\endgroup\$ – mazzy Nov 5 '20 at 10:09
  • 1
    \$\begingroup\$ thanks. the "$_/1/$a" works with the en_us region only. it does not work with german or russian regions. \$\endgroup\$ – mazzy Nov 6 '20 at 5:52
  • 1
    \$\begingroup\$ Yes, I did it on purpose and had to adapt it to the Try it online culture. Is it an ok approach? Or should use another solution? \$\endgroup\$ – Julian Nov 8 '20 at 19:58
  • 1
    \$\begingroup\$ I think it would be ok if you explicitly wrote about regional settings. \$\endgroup\$ – mazzy Nov 8 '20 at 20:46
0
\$\begingroup\$

CJam, 62 bytes

E,(;qiaf+{[~_2$3<_!-2*@@- 4/_25/_4/\W*](23*9/+:+7%4=}%ee::*0-`

Try it online!

Uses an algorithm adapted from Mike Keith. The program calculates the weekday of the first day of the next month, then checks if that day is a Tuesday. Output is a string representation of an array of month indices, e.g. [2 10].

If output can be in the form of a binary array with 0 meaning false and 1 meaning true for each of the 12 months, you can get away with 55 bytes.

\$\endgroup\$
0
\$\begingroup\$

Japt, 13 bytes

Outputs an array of all months, where 0s are months that don't end in Mondays and all other integers are the 1-based indices of the months.

CõÈ*=1¶ÐUXJ e

Try it

If run in a locale where Monday is the first day of the week, with 0-based indexing, we could save 2 bytes with:

CõÈ*!ÐUXJ e

Or push the loose output format a little further by returning an array of Booleans with:

Cõ@!ÐUXJ e

Explanation

CõÈ*=1¶ÐUXJ e      :Implicit input of integer U
C                  :12
 õ                 :Range [1,C]
  È                :Map each X
   *=              :  Multiply by and reassign
     1¶            :  Test 1 for equality with
       Ð           :  Create date object using
        U          :    U for the year
         X         :    X for the 0-based month ([0,11]=[Jan,Dec] but [1,12]=[Feb,Jan])
          J        :    -1 for the date, wrapping us back to the last day of the previous month
            e      :  0-based index of the day of the week (0=Sunday)
\$\endgroup\$
0
\$\begingroup\$

Java (JDK), 141 136 bytes

y->{for(int i=0;++i<13)if(java.time.LocalDate.of(y,i,1).plusMonths(1).minusDays(1).getDayOfWeek().getValue()<2)System.out.println(i);};

Try it online!

To get the last day of each month I get the first day of the next month and substract 1 day. Java date function getDayOfWeek() returns the day of the week (Monday=1)

141 -> 136 : small improvements (thanks to @ceilingcat)

\$\endgroup\$
0
0
\$\begingroup\$

T-SQL, 92 bytes

Input parameter needs to be padded with zeros if the year is before 1000

SELECT number+1FROM spt_values
WHERE number<12and
datepart(w,eomonth(@,number))=2and'P'=type 

Try it online

\$\endgroup\$
0
\$\begingroup\$

Groovy, 83 bytes

f={y->(1..12).findAll{sprintf('%ta',(java.time.YearMonth.of(y,it)+1<<1)-1)=='Mon'}}

Try it online!

The return format is a List of 1-based months.

(Doesn't currently work in TIO since it is using the YearMonth.plus(long months) method, which was added in Groovy 2.5.0. TIO currently uses Groovy 2.4.8).

sprintf('%ta',value) returns the 3-letter month name.

YearMonth.of(y,it)+1 returns the YearMonth after the given month; YearMonth<<1 returns the LocalDate of the first of the month. Subtracting 1 from this returns the last day of the previous month. This is all just a convoluted way of returning YearMonth.of(y,it).atEndOfMonth() in 4 fewer characters.

\$\endgroup\$
0
\$\begingroup\$

Groovy, 57 bytes

f={y->(1..12).findAll{"${new Date(y+100,it,0)}"[0]=='M'}}

Try it online!

The return format is a List<Integer> of 0-based months.

This uses the legacy Date(int year, int month, int date) constructor that takes a year (minus 1900), the 0-based month, and the day of month.

The legacy Date class uses the Julian calendar prior to 1583. However, the day-of-week is on a 400 year cycle, so I added 2000 (400*5) to the date. Since 1900 has to be subtracted from the input date, I'm actually passing in the three-character number 100 (2000-1900) for the year.

In order to get the last day of the month, I'm passing in months 1-12 (February through the following year's January, since Date uses 0-based months) and day-of-month 0 (the day before the first of that month). This gets me the last day of January - December of the given year.

Finally, the string representation of Date is in "Sun Nov 01 00:00:00 CDT 2020" format. I'm converting the date to a GString using string interpolation, and then comparing the first character of that string to "M" for "Monday".

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.