Number of first days of the month equals to Mondays
    15 visualizzazioni (ultimi 30 giorni)
  
       Mostra commenti meno recenti
    
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 Commento
  Geoff Hayes
      
      
 il 26 Feb 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?
Risposte (4)
  Srishti Saha
      
 il 13 Mag 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 Commento
  Jan
      
      
 il 26 Feb 2018
        
      Modificato: Jan
      
      
 il 26 Feb 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 Commenti
  Jan
      
      
 il 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
 il 3 Gen 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 Commento
  Walter Roberson
      
      
 il 3 Gen 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
 il 7 Feb 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 Commenti
Vedere anche
Categorie
				Scopri di più su Dates and Time in Help Center e File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!