Number of first days of the month equals to Mondays
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Hello guys,
I have an assignment that states: "Write a function called day_counter that returns the number of Mondays that fell on the first day of the month in a given year between 1776 and 2016 inclusive where the requested year is the only input to your function and it is a positive integer scalar. Note that a leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400. In a leap year, February has 29 days. You are not allowed to use the datenum built-in function."
Now, I am having a problem with this code:
function [ numMon ] = day_counter( givenYear )
startYear = 1776;
totalDaysYear=0;
% First day of 1776 is Monday.
numMon=1; % Jan 1st,1776 was Monday.
% Calculate leap year for input year.
for countYear= startYear:givenYear
% Determine whether it is leap year.
if mod(countYear, 4)==0 || (mod(countYear, 100)==0 && mod(countYear, 400)==0)
Febdays=29;
else
Febdays=28;
end
% Set the corresponding number of days per month.
monthDays = {'Jan', 'Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dic'; ...
31,Febdays,31,30,31,30,31,31,30,31,30,31};
% Sum all days until you complete a year. It the sum per month is
% devisible by 7 (since the initial condition), then is it Monday.
for ii = 1:length(monthDays(1,:))
totalDaysYear = (totalDaysYear) + monthDays{2,ii};
if rem(totalDaysYear,7)==0
numMon = numMon+1;
end
end
totalDaysYear= totalDaysYear-1;
% Calculate the number of first day of a month equal to Monday PER EACH
% YEAR, which mean the variable numMon has to be reset.
Mondays = numMon;
% Verify whether first day of the input year is Monday.
firstDayYear = mod(totalDaysYear+1,7);
if firstDayYear==0
numMon = 1;
else
numMon=0;
end
end
numMon = Mondays;
end
I cannot find the "bug" causing an error in the output variable "totalDaysYear" (total days accumulated yearly since 1776). A correct output for year 1776 is 3, for 1800 is 2, and for year 2000 is 2. I already solved the problem using the built-in functions "weekday" and "datetime", but I would like to do it in this way.
I would really appreciate some guidance or help in order to improve coding.
Thank you in advance.
Jorge
1 commentaire
Geoff Hayes
le 26 Fév 2018
Jorge - I don't understand this comment
% Sum all days until you complete a year. It the sum per month is
% devisible by 7 (since the initial condition), then is it Monday.
How do you know this is true?
Réponses (4)
Srishti Saha
le 13 Mai 2018
I have written the following function and it has worked perfectly for me:
%problem day counterfunction n = day_counter(year)
%creating a vector for number of days in a month starting January
months = [31 28 31 30 31 30 31 31 30 31 30 31];
start = 1776;
y = year - start; % computing number of years since 1776
% number of days since January 1, 1776:
ndays = y*365 + ceil(y/4) - floor((year-1)/100) + floor(start/100) + floor((year-1)/2000);
% if it is a leap year, adjust nbr of days in February to 29; condition for checking a leap year:
if mod(year,4) == 0 && (mod(year,100) ~= 0 || mod(year,400) == 0)
months(2) = 29;
end
%for previous month
months = [0 cumsum(months(1:end-1))];
n = sum(mod(ndays+months,7) == 0); %for Mondays
end
1 commentaire
Jan
le 26 Fév 2018
Modifié(e) : Jan
le 26 Fév 2018
This does not define a leap year:
if mod(countYear, 4)==0 || (mod(countYear, 100)==0 && mod(countYear, 400)==0)
You want:
if mod(countYear, 4)==0 && (mod(countYear, 100)~=0 || mod(countYear, 400)==0)
By the way: Do you see, that the line is easier to read with a shorter name of the variable:
if mod(Y, 4) == 0 && (mod(Y, 100) ~= 0 || mod(Y, 400) == 0)
The is no need to process former years completely. Better create a subfunction to detect leap years:
function L = isLeap(Y)
L = mod(countYear, 4)==0 & (mod(countYear, 100)~=0 | mod(countYear, 400)==0);
end
Here you use & instead of && to allow a vector input. Then for the year Y you can determine the day of the 01-January:
YL = 1776:(Y-1);
ALdays = 366 * YL + 365 * ~YL + 1;
Now a mod() is enough.
2 commentaires
Jan
le 5 Nov 2018
@Adarsh Agarwal: You find a working solution in this thread already and my answer contains instruction to solve the problem also. So please try to implement it by your own and ask a specific question on demand.
Mosen shk
le 3 Jan 2019
you can use weekday function to define which day is the start of each month. this gives you a logical array and you just need to define how many logical '1' exist in the response
1 commentaire
Walter Roberson
le 3 Jan 2019
True. However, weekday() requires a serial date number as input, and you do not have that to start; or weekday() can take a date character vector, but I wonder if that would be considered to be against the rules about not using datenum() ?
RAMAKANT SHAKYA
le 7 Fév 2019
function counter=day_counter(y)
counter=0;
year=rem(y,100); % no of years in century
lp=fix(year/4); %leap year
if y~=1900 && (rem(y,4)==0 || rem(y,400)==0)
mday={[1:31],[1:29],[1:31],[1:30],[1:31],[1:30],[1:31],[1:31],[1:30],[1:31],[1:30],[1:31]};%days in the months...
mcode={0,3,4,0,2,5,0,3,6,1,4,6};%code are assign for months
daycode={1,2,3,4,5,6,0};% start from sun,mon....
else
mday={[1:31],[1:28],[1:31],[1:30],[1:31],[1:30],[1:31],[1:31],[1:30],[1:31],[1:30],[1:31]};%code are assign for months
mcode={1,4,4,0,2,5,0,3,6,1,4,6};%code are assign for months
daycode={1,2,3,4,5,6,0};% start from sun,mon....
end
%code for the centuries
%1700-1799 code is 4
%1800-1899 code is 2
%1900-1999 code is 0
%2000-2099 code is 6
%2100-2199 code is 4 and this pattern continue in same manner
function cen= century(y)
if y>=1700 && y<=1799
cen=4;
elseif y>=1800 && y<=1899
cen=2;
elseif y>=1900 && y<=1999
cen=0;
elseif y>=2000 && y<=2099
cen=6;
end
end
cen=century(y);
firstd=rem((1+mcode{1}+year+lp+cen),7);% to find the day on 1 Jan of given year
%reminder =(date+monthcode+year+leap year till that year)/7
dday={};
for r=1:12 % for months
for c=mday{r}(1:end) % for dates of respective months
dday{r}(1,c)=firstd; %starting from january
firstd=firstd+1; % for next day on next loop of c means next day
firstd=rem(firstd,7); % days of week
end
if dday{r}(1,1)==2 %if first day of month is monday
counter=counter+1; % starting counting
end
end
end
0 commentaires
Voir également
Catégories
En savoir plus sur Dates and Time dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!