I have been working on this problem for a while. It's a problem that says you have to find how many Sundays land on the First of the Month in the years 1901 to 2000. I've made it mostly work, but it still outputs 173, instead of 171 (the correct answer).
Does anyone why this is?
months = {1:31, 2:28, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31}
start, end = 1900, 2001
years = range(start, end)
leap_years = range(1904, 2001, 4)
Sundays = 0
days = 1
for year in years:
if year in leap_years:
months[2] = 29
else:
months[2] = 28
for month in range(1, 13):
for day in range(1, months[month]+1):
if days == 7:
if day == 1:
print(year, month, day)
Sundays += 1
days = 1
else:
days += 1
print(Sundays)
Your algorithm is completely correct - just the inputs are wrong. start and end should be:
start, end = 1901, 2000
The range(a, b) function is not inclusive of b, but it is inclusive of a. Thus start should be 1901 instead of 1900.
The end is a bit more tricky, you have to think about the phrasing of the question:
... in the years 1901 to 2000
Think about it - this means every day up to, but not including, Jan 1 2000. Thus the last year that you actually want to iterate through and check is 1999. Thus, setting end to 2000 will cause the range() function to return all the years up to, but not including, 2000. Which is exactly what the question asks for.
Your days assumes day equal 1 is days equal 1, (Monday) starting from the first month (and then progresses through the months, years). I don't think this will accurately calculate the count of Sundays that fall on the first of each month over the years.
If you enter the following code at the beginning of your program (and delete the line before your loop that says days = 1), it will correctly give the number of Sundays == 171. This will start out the day of week for the first day of the first month of the first year accurately.
from calendar import weekday
start, end = 1901, 2001
days = 1 + weekday(start, 1, 1)
Note that the weekday function uses zero based counting, (Monday through Sunday is 0 to 6) so that's why 1 is added to the result in the initialization of days. (Because your Monday to Sunday is 1 to 7).
Just to illustrate how the solution could find Sundays without iterating through every day of all the years:
from calendar import weekday
sundays = 0
for yr in range(1901, 2001):
for month in range(1, 13):
if weekday(yr, month, 1) == 6:
sundays += 1
print(sundays) # prints 171
I have to write a for loop program that asks the user to input a year and a number of years, to determine firstly if the year entered is a leap year, the secondly enter the number of years thereafter to check if those are leap years as well.
My output should look like this:
What year do you want to start with? 1994
How many years do you want to check? 8
1994 isn’t a leap year
1995 isn’t a leap year
1996 is a leap year
1997 isn’t a leap year
1998 isn’t a leap year
1999 isn’t a leap year
2000 is a leap year
2001 isn’t a leap year
The code I have thus far works to check the specific year, but I am struggling to loop it so that it continues for the years thereafter.
Here is my code:
print ("""Enter a year to see if it is a leap year,
then enter the number of years there after you want to check""")
year_start = int(input("\nWhat year do you want to start with?\n"))
num_of_years = int(input("How many years do you want to check?\n"))
# I can't figure out the 'for loop' syntax to loop this statement
if (year_start % 4) == 0:
if (year_start % 100) == 0:
if (year_start % 400) == 0:
print (f"{year_start} is a leap year")
else:
print (f"{year_start} isn't a leap year")
else:
print (f"{year_start} is a leap year")
else:
print (f"{year_start} isn't a leap year")
Try changing your code to:
print ("""Enter a year to see if it is a leap year,
then enter the number of years there after you want to check""")
year_start = int(input("\nWhat year do you want to start with?\n"))
num_of_years = int(input("How many years do you want to check?\n"))
# I can't figure out the 'for loop' syntax to loop this statement
for i in range(year_start, year_start + num_of_years):
if (i % 4) == 0:
print (f"{i} is a leap year")
else:
print (f"{i} isn't a leap year")
Example output:
Enter a year to see if it is a leap year,
then enter the number of years there after you want to check
What year do you want to start with?
1994
How many years do you want to check?
8
1994 isn't a leap year
1995 isn't a leap year
1996 is a leap year
1997 isn't a leap year
1998 isn't a leap year
1999 isn't a leap year
2000 is a leap year
2001 isn't a leap year
You can use a for loop and use range for the sequence to iterate. Then you only need (i % 4) == 0, and you don't need the other conditions.
Only division by 4 is not enough for finding leap year. You have to check 100 and 400.
Please check https://en.wikipedia.org/wiki/Leap_year#/media/File:Leap_Centuries.jpg for leap year.
def is_leap_year(year: int) -> bool:
# Returns True if the given year is a leap year
return bool((not year % 400) or ((not year % 4) and year % 100))
Use range(num_of_years) as follows:
for i in range(num_of_years):
you should encapsulate all the leap year logic inside that for loop and make some adjustments but you should be able to figure that on your own, good luck.
I am a novice working on a short program with the purpose of detecting dates and printing out whether the given dates are valid or not. Here's how it looks like :
dateRegex = re.compile(r'''(
(0[1-9]|[12]\d|30|31)
[.\\ /]
(0[1-9]|1[0-2])
[.\\ /]
([1-2][0-9]{3})
)''', re.VERBOSE)
def dateValidation(date):
text = str(pyperclip.paste())
mo = date.findall(text)
for groups in mo:
day = groups[1]
month = groups[2]
year = groups[3]
leapyear = ''
if ( month == '04' or month == '06' or month == '09' or month == '11' ) and ( int(day) > 30 ):
print(f'The {groups[0]} string is not a date.')
continue
if int(year) % 4 == 0:
leapyear += year
if int(year) % 100 == 0:
leapyear = ''
if ( int(year) % 100 == 0 ) and ( int(year) % 400 == 0 ):
leapyear += year
if month == '02' and leapyear == year:
if int(day) > 29:
print(f'The {groups[0]} string is not a date.')
continue
elif month == '02' and leapyear != year:
if int(day) > 28:
print(f'The {groups[0]} string is not a date.')
continue
print(f'The {groups[0]} string is a date.')
dateValidation(dateRegex)
I know a lot of the code isn't clean or practical, so I'm open to suggestions about optimizing it, of course ( I'm fairly new to this after all, and apparently doing horribly ), but the question is mainly regarding the output of the program.
I copied 01.02.2016 21.6.2003 26.7.1999 to clipboard and expected to get a result regarding all three dates. Instead, the output was only ''The 01.02.2016 string is a date.'' Did I overlook something ? What could've gone wrong ?
If it isn't obvious from the code, here is a detailed description of what the program is supposed to do :
Write a regular expression that can detect dates in the DD/MM/YYYY format. Assume that the days range from 01 to 31, the months range from 01 to 12, and the years range from 1000 to 2999. Note that if the day or month is a single digit, it’ll have a leading zero.
The regular expression doesn’t have to detect correct days for each month or for leap years; it will accept nonexistent dates like 31/02/2020 or 31/04/2021. Then store these strings into variables named month, day, and year, and write additional code that can detect if it is a valid date. April, June, September, and November have 30 days, February has 28 days, and the rest of the months have 31 days. February has 29 days in leap years. Leap years are every year evenly divisible by 4, except for years evenly divisible by 100, unless the year is also evenly divisible by 400. Note how this calculation makes it impossible to make a reasonably sized regular expression that can detect a valid date.
Thanks in advance.
I think the problem with the regular expression follows from the format of the dates in the text. Since some of the dates are given as 21.6.2003 and not 21.06.2003, your regex misses that.
For the dates you can use the following one:
r'(0*[0-9]|1[0-9]|2[0-9]|3[0-1])\.(0*[0-9]|1[0-2])\.[1-2][0-9]{3})'
Here,
(0*[0-9]|1[0-9]|2[0-9]|3[0-1]) matches the days ranging in 00-31. In the first case, 0* tells regex to match zero or more of the preceding token. So, if the date is given in 06 or 6 format, it can catch both cases
Similar approach also follows in (0*[0-9]|1[0-2]), which finds the month in the range 00-12
I have a string representing a birth date I want to know how old the person is in years and days.
e.g: birth = 07/04/1994 (month/days/years)
So the person is 25y 78d old
But so far, using datetime when I do substraction between dates the result it as number of days. And because of leap years I can never be sure of the exact number of days.
In [1]:
from datetime import date, datetime
today = date.today()
birth = '10/21/1996'
birth_date = datetime.strptime(datetime.strptime(birth, '%m/%d/%Y').strftime('%Y-%m-%d'),'%Y-%m-%d').date()
delta = today - birth_date
print(delta.days)
Out [1]:
8369
Not as simple as a built-in Python function, but certainly doable using the following logic:
Construct a date based on the current year minus one, but the birth month and day. Call this lastYearBirthday. Also construct a date based on the current year but the birth month and day. Call this currYearBirthday.
If currYearBirthday is after today (the birthday is yet to occur this year), the number of full years can be obtained by subtracting year(birthdate) from year(lastYearBirthday). The number of days over and above (days since last birthday) that is obtained with (today - lastYearBirthday).days.
Otherwise this years birthday has already happened (or is happening today) and the number of full years can therefore be obtained by subtracting year(birthdate) from year(currYearBirthday) - the number of days over that is obtained with (today - currYearBirthday).days.
Turning that into a Python function you can use easily, we get:
from datetime import date
# Functions to return tuple of (fullYears, extraDays) for
# a given birth date.
def ageInYearsAndDays(birthDate):
# Create relevant dates to ease task.
today = date.today()
lastYearBirthday = date(today.year - 1, birthDate.month, birthDate.day)
currYearBirthday = date(today.year, birthDate.month, birthDate.day)
# Work out years and days based on whether this years
# birthday has happened. Basic idea is that years can
# be calculated as difference between birth year and
# year of most recent birthday. Days is the number of
# days between most recent birthday and today.
if currYearBirthday > today:
years = lastYearBirthday.year - birthDate.year
days = (today - lastYearBirthday).days
else:
years = currYearBirthday.year - birthDate.year
days = (today - currYearBirthday).days
return (years, days)
And some test code shows my own precarious position on this mortal coil:
(years, days) = ageInYearsAndDays(date(1965, 2, 2))
print(years, "years and", days, "days")
The output being (on the day this answer was posted) a rather depressing:
54 years and 230 days
:-)
Note that I just constructed my birthdate from year, month and day directly. Since you already know how to turn a string into one of those (as per your question), I didn't bother using that method.
A user built this following code for another answer on stack that captures the leap year logic. With that said, you will need to refactor to fit your needs...
#Calculate the Days between Two Date
daysOfMonths = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
def isLeapYear(year):
# Pseudo code for this algorithm is found at
# http://en.wikipedia.org/wiki/Leap_year#Algorithm
## if (year is not divisible by 4) then (it is a common Year)
#else if (year is not divisable by 100) then (ut us a leap year)
#else if (year is not disible by 400) then (it is a common year)
#else(it is aleap year)
return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0
def Count_Days(year1, month1, day1):
if month1 ==2:
if isLeapYear(year1):
if day1 < daysOfMonths[month1-1]+1:
return year1, month1, day1+1
else:
if month1 ==12:
return year1+1,1,1
else:
return year1, month1 +1 , 1
else:
if day1 < daysOfMonths[month1-1]:
return year1, month1, day1+1
else:
if month1 ==12:
return year1+1,1,1
else:
return year1, month1 +1 , 1
else:
if day1 < daysOfMonths[month1-1]:
return year1, month1, day1+1
else:
if month1 ==12:
return year1+1,1,1
else:
return year1, month1 +1 , 1
def daysBetweenDates(y1, m1, d1, y2, m2, d2,end_day):
if y1 > y2:
m1,m2 = m2,m1
y1,y2 = y2,y1
d1,d2 = d2,d1
days=0
while(not(m1==m2 and y1==y2 and d1==d2)):
y1,m1,d1 = Count_Days(y1,m1,d1)
days+=1
if end_day:
days+=1
return days
# Test Case
def test():
test_cases = [((2012,1,1,2012,2,28,False), 58),
((2012,1,1,2012,3,1,False), 60),
((2011,6,30,2012,6,30,False), 366),
((2011,1,1,2012,8,8,False), 585 ),
((1994,5,15,2019,8,31,False), 9239),
((1999,3,24,2018,2,4,False), 6892),
((1999,6,24,2018,8,4,False),6981),
((1995,5,24,2018,12,15,False),8606),
((1994,8,24,2019,12,15,True),9245),
((2019,12,15,1994,8,24,True),9245),
((2019,5,15,1994,10,24,True),8970),
((1994,11,24,2019,8,15,True),9031)]
for (args, answer) in test_cases:
result = daysBetweenDates(*args)
if result != answer:
print "Test with data:", args, "failed"
else:
print "Test case passed!"
test()
How to calculate number of days between two given dates?
A lot of exercises from the good old days on stack overflow in September. This should illustrate you the logic. Note that a year is leap only when is perfectly divided by 4, 100 or 400. You can then make use of datetime attributes to have fun.
from datetime import date, datetime
today = date.today()
birth = '10/21/1996'
birth_date = datetime.strptime(datetime.strptime(
birth, '%m/%d/%Y').strftime('%Y-%m-%d'), '%Y-%m-%d').date()
delta = today - birth_date
days = delta.days
year_counter = 0
if today.day >= birth_date.day and today.month >= birth_date.month:
full_years = today.year
else:
full_years = today.year - 1
for year in range(1996, full_years):
if (year % 4) == 0 or (year % 100) == 0 or (year % 400) == 0:
days -= 366
year_counter += 1
else:
days -= 365
year_counter += 1
print("years: " + str(year_counter) + "\ndays: " + str(days))
Obviously there are more Pythonic way to write it, but I suppose you wanted some readability.
I have to calculate the time between two dates in days in Python, but without the datetime module.
I managed to parse a date without datetime:
def date(error):
global sdate
if error:
print(sdate," isn't a valable date ! ")
sdate = input('Date : ')
try:
ldate = sdate.split('.')
ldate = [ int(x) for x in ldate]
day,month,year = ldate
except ValueError:
date(True)
if year%4==0 and year%100!=0 or year%400==0:
bis = True
else:
bis = False
if month not in range(1,13):
date(True)
if month not in(1,3,5,7,8,10,12):
mmax = 31
elif month in(4,6,9,11):
mmax = 30
elif month == 2 and bis == True:
mmax = 29
elif month == 2 and bis == False:
mmax = 28
if day not in range(1,mmax+1):
date(True)
date(None)
print(ldate)
But didn't figure out how to get time between dates.
What's the easiest way?
Thanks,
Blaxou
PS: It's not a Homework at all, I need it for a personal project where I use any of too easy-life-making modules ;)
You will have to do much more than that to check the difference between two dates.
I will give you pseudo code to do this, write your own program.
• get the dates
• validate the dates
-> (ex. It should be false for feb 29 2007)
• calculate total number of days of that particular year for both dates
-> (ex 1 jan 2015 = 01 and 28 feb 2016 = 59)
• calculate the year difference
• calculate number of leap years between two days (excluding both end)
-> (2004 and 2008 leap year is 0)
• calculate the difference by
diff(number of days) + (year difference * 365) + number of leap years