1
$\begingroup$

I am attempting to solve the Most-Occurring Weekdays in a Year challenge to teach myself Mathematica.

Specifically, the challenge is:

Write a function MostOccurringWeekday that takes an integer representing a year as input and returns a list of the most-occurring weekdays throughout that year.

I have this code written:

year = 2012
isLeapYear = LeapYearQ[{year}]
firstDay = DateObject[{year, 1, 1}]
frequentDays = {DateString[firstDay, "DayName"]}
secondDay = DateObject[{year, 1, 2}]
secondFrequentDays = DateString[secondDay, "DayName"]

If[isLeapYear == True, AppendTo[frequentDays, secondFrequentDays]]

Return[frequentDays]

This appears to work, but I need to put it in the format MostOccurringWeekday[year_Integer]:= to submit it. I'm not sure how to convert what I have to a one line?

$\endgroup$
  • 4
    $\begingroup$ Please look up Module and go through the first two sections of this tutorial: reference.wolfram.com/language/tutorial/… Return is not needed. $\endgroup$ – Szabolcs Apr 25 at 19:45
  • $\begingroup$ @DavidGStork @HighPerformanceMark @ubpdqn As far as I can see, none of the proposed solutions so far give the correct answer for the year 1582 when the switchover from the Julian to the Gregorian calendar occurred. This problem requires a proper parsing of tzdata for the relevant time zone, which Mathematica doesn't seem to do. Not even using DateObject with an explicit TimeZone fixes this, as it assumes a fixed calendar (Gregorian or Julian). There are likely many more such thorny issues, like the March-to-January shift of the year's beginning etc. No idea how to proceed. $\endgroup$ – Roman Apr 26 at 9:08
  • $\begingroup$ @Roman: the problem you raise with the switch from Julian to Gregorian is worse than you mention - it didn't occur in 1582, it was mandated by papal bull that year, but not universally adopted by 'western' countries until 1923. I intend to proceed in the usual manner, by ignoring such historical concerns :-) $\endgroup$ – High Performance Mark Apr 28 at 11:45
  • $\begingroup$ Yes @HighPerformanceMark it's a can of worms that's best left unopened. Some Eastern Europeans still celebrate Christmas in January... I just meant to point out that this problem, as put forth, is a very difficult one that cannot be answered correctly without a massive investment and nitty gritty database lookups. $\endgroup$ – Roman Apr 28 at 13:09
4
$\begingroup$
mostOccuringWeekday[year_Integer] := 
  Commonest[
  StringTake[DateString[#], 3] & /@ 
  DateRange[
  DateObject[{year, 1, 1}], DateObject[{year, 12, 31}]]]

This is the core functionality you need. No need to worry about leap years and such... the Mathematica curated database knows all about that.

$\endgroup$
3
$\begingroup$

The most occuring day(s) will occur 53 times. In leap years there will be 2 days that occur with this frequency.

You could do:

f[y_] := Cases[Tally[DayName /@ DateRange[{y, 1, 1}, {y, 12, 31}]], {a_, 53} :> a]

For Example,

Table[j -> f[j], {j, 2000, 2019, 1}] // TableForm

enter image description here

$\endgroup$
  • $\begingroup$ Greetings, old MMA SE chum! This post reminded me of that challenge - so I had to go break the records ;-) $\endgroup$ – ciao Apr 26 at 7:09
  • $\begingroup$ @ciao nice to get your message...have been under a heavy rock...just thought I’d participate again...🖖 $\endgroup$ – ubpdqn Apr 26 at 7:12
3
$\begingroup$

This won't take the laurels for the challenge, but makes use of what we (and Mathematica) know about the fall of days each year, and is an alternative to figuring out the day name for each day. I guess it might be a tad quicker for that reason.

mostOccurringWeekday[yr_Integer] := 
 If[LeapYearQ[{yr}], {DateString[{yr}, "DayName"], 
   DateString[{yr, 1, 2}, "DayName"]}, DateString[{yr}, "DayName"]]

I came back to this one and compared its speed to that of the other answers. Where I wrote a tad quicker above I might have wrote two-orders of magnitude quicker, which is perhaps not surprising since it only figures out one or two day names for each year, rather than 365 or 366.

$\endgroup$
  • $\begingroup$ Unfortunately, this returns incorrect results, try e.g. 1904... $\endgroup$ – ciao Apr 26 at 18:13
  • $\begingroup$ @ciao: I did try 1904, the function returned {Friday, Saturday} which I believe is correct. It's also what the other two answers return. Where's the error ? $\endgroup$ – High Performance Mark Apr 28 at 11:05
  • $\begingroup$ Sorry, must have had a brain fart when comparing methods - your's is fine. Mea culpa. $\endgroup$ – ciao Apr 28 at 20:31
0
$\begingroup$

Using a dayOfWeek function from the Mathematica Navigator, p. 552, which is much faster than DateString[... , "DayName"].

dayOfWeek[{y_, m_, d_, _, _, _}] := Module[
  {\[Delta] = If[m >= 3, 2, 0], z = If[m < 3, y - 1, y], a,
   days = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}},
  a = \[LeftFloor](23 m)/9\[RightFloor] + d + y + 
    4 + \[LeftFloor]z/4\[RightFloor] - \[LeftFloor]z/
     100\[RightFloor] + \[LeftFloor]z/400\[RightFloor] - \[Delta];
  days[[Mod[a, 7] + 1]]]

mostfrequent[year_Integer] := Module[{},
  ndays = DateDifference[{year, 1, 1}, {year + 1, 1, 1}][[1]];
  dates = DateList[{year, 1, #}] & /@ Range[ndays];
  First /@ Cases[Tally[dayOfWeek /@ dates], {_, 53}]]

mostfrequent[2012]

{Sun, Mon}

$\endgroup$

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.