when i run it through a VPL it passes 13/16 tests - python

year=int(input("Year: "))
while year<1583 or year>9999:
print("Out of allowed range 1583 to 9999")
year=int(input("Year: "))
leap_year=year%4==0 and (year%100 !=0 or year%400==0)
month=[1,12]
month=int(input("Month: "))
while month<1 or month >12:
print ("Out of allowed range 1 to 12")
month=int(input("Month: "))
day=int(input("Day: "))
if month==1 or month==2:
month+=12
year-=1
if month in [1,3,5,7,8,10,12]:
while day<1 or day> 31:
print("Out of allowed range 1 to 31")
day=int(input("Day: "))
if month in [4,6,9,11]:
while day<1 or day >30:
print("Out of allowed range 1 to 30")
day=int(input("Day: "))
if month==2:
if leap_year:
while day<1 or day>29:
print("Out of allowed range 1 to 29")
day=int(input("Day: "))
weekday = ( day + 13*(month+1)// 5 + year + year// 4- year//100+year// 400)% 7
if weekday==0:
print("It is a Saturday.")
elif weekday==1:
print("It is a Sunday.")
elif weekday==2:
print("It is a Monday.")
elif weekday==3:
print("It is a Tuesday.")
elif weekday==4:
print("It is a Wednesday.")
elif weekday==5:
print("It is a Thursday.")
elif weekday==6:
print("It is a Friday.")`
This is the code I wrote and when i run it through a VPL it passes 13/16 tests. The ones it does not pass is :
year: 1900 month:2 day: 29
year: 2018 month:1 day: 32
year: 2018 month:2 day: 32
I've been trying different things but I dont know what is wrong ie. how to correct it. Excuse the low skill level, I've been learning for a week only.

First problem is this code:
if month==1 or month==2:
month+=12
year-=1
If month is 1 or 2 then month becomes 13 or 14, then the next validation tests fail to detect the bad day of the month.
And next problem, this fails to check for condition day < 1 or day > 28 if leap_year = False as in case of 1900, month=2, day=29.
if month==2:
if leap_year:
while day<1 or day>29:
...
Can rewrite like this:
if month==2:
if leap_year:
max_day = 29
else:
max_day = 28
while day < 1 or day > max_day:
print(f"Out of allowed range 1 to {max_day}")
day=int(input("Day: "))

Related

How do I properly categorize leap years in my if-statements?

I'm writing a code that gives the user the day of the week, depending on which ever date (between the year 1583 and 9999) the user puts in. My problem is leap years. Leap years can be mathematically calculated with Zellers congruence: https://en.wikipedia.org/wiki/Zeller%27s_congruence
You can boil down the formula to the following statement:
It is a leap year if the year is evenly divisible by 400, or if it is evenly divisible by 4 but not evenly divisible by 100.
My code does a fine job with this, unless the year is true in both if-statements. For example: 2016. It is a leap year, which makes the first if-statement true. But it´s also NOT evenly divisible by 400. Which makes it true in the second if-statement. So when I run the program I get prompted with "Day: " twice.
Any tips on how to fix this?
The code in question:
if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
day = int(input("Day: "))
while day < 1 or day > 29:
print("Out of allowed range 1 to 29")
day = int(input("Day: "))
continue
if ((year % 4 != 0) and (year % 100 == 0)) or (year % 400 != 0):
day = int(input("Day: "))
while day < 1 or day > 28:
print("Out of allowed range 1 to 28")
day = int(input("Day: "))
continue
I´ve tried changing the 'or' operator to 'and' but that doesn´t really do anything
if ((year % 4 != 0) and (year % 100 == 0)) or (year % 400 != 0):
if ((year % 4 != 0) and (year % 100 == 0)) and (year % 400 != 0):
I've also tried manually putting in the leap years that are similar to 2016. But that doesn't really solve my problem.
The entire code:
x = [1,3,5,7,8,10,12]
y = [4,6,9,11]
year = int(input("Year: "))
while year < 1583 or year > 9999:
print("Out of allowed range 1583 to 9999")
year = int(input("Year: "))
month = int(input("Month: "))
while month < 1 or month >12:
print("Out of allowed range 1 to 12")
month = int(input("Month: "))
if month in x:
day = int(input("Day: "))
while day < 1 or day > 31:
print("Out of allowed range 1 to 31")
day = int(input("Day: "))
elif month in y:
day = int(input("Day: "))
while day < 1 or day > 30:
print("Out of allowed range 1 to 30")
day = int(input("Day: "))
elif month == 2:
if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
day = int(input("Day: "))
while day < 1 or day > 29:
print("Out of allowed range 1 to 29")
day = int(input("Day: "))
continue
if ((year % 4 != 0) and (year % 100 == 0)) or (year % 400 != 0):
day = int(input("Day: "))
while day < 1 or day > 28:
print("Out of allowed range 1 to 28")
day = int(input("Day: "))
continue
if month == 1 or month == 2:
month += 12
year -= 1
weekday = (( day + 13*(month+1)//5 + year + year//4
- year//100 + year//400 ) % 7)
print("It is a", end = ' ')
if weekday == 0:
print("Saturday")
elif weekday == 1:
print("Sunday")
elif weekday == 2:
print("Monday")
elif weekday == 3:
print("Tuesday")
elif weekday == 4:
print("Wednesday")
elif weekday == 5:
print("Thursday")
elif weekday == 6:
print("Friday")
The condition in your first if is correct:
(year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))
But from De Morgan's law,
the opposite condition is
(year % 400 != 0) and ((year % 4 != 0) or (year % 100 == 0))
So you want to use that as the condition in your second if for February.
Or to be more clear, you can make a function for determining if it's a leap year:
def is_leap_year(year):
return (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))
And then for February:
if is_leap_year(year):
# Get a day between 1 and 29
else:
# Get a day between 1 and 28
There area bunch of built-in modules in Python that are really useful, one of them is the datetime module which makes calculations with dates much easier. Your solution could be condensed into this code:
import datetime
while True:
try:
year=int(input('Year:'))
month=int(input('Month:'))
day=int(input('Day:'))
date = datetime.datetime(year,month,day)
print(date.strftime('%A'))
break
except ValueError as e:
print(e)
The ValueError will have the reason why it failed to create a datetime from the input parameters. You can still check for additional constraints, like the year and raise a ValueError(<your message>) when it's out of range.

leap year python script

I am trying to write a code that will accept any of the months of the year and output the month entered plus a list of the days in the month. But if February is entered it should ask for the birth year and check if that is a leap year and output February plus the days in February.
Where did I go wrong?
month = input("Enter any month of the year: ")
for n in month:
if (n == "January" or
n == "March" or
n == "April" or
n == "May" or
n == "June" or
n == "July" or
n == "August" or
n == "September" or
n == "October" or
n == "November" or
n == "December"):
print (n + range(1, 32))
elif n == "February" :
year = input("Enter a year")
for i in year:
if i % 4 == 0:
print (year + range(1,29))
I will advise you to simply use the built-in calendar module
# Program to display calendar of the given month and year
# importing calendar module
import calendar
yy = 2014 # year
mm = 11 # month
# To take month and year input from the user
# yy = int(input("Enter year: "))
# mm = int(input("Enter month: "))
# display the calendar
print(calendar.month(yy, mm))
# output
# November 2014
#Mo Tu We Th Fr Sa Su
# 1 2
# 3 4 5 6 7 8 9
#10 11 12 13 14 15 16
#17 18 19 20 21 22 23
#24 25 26 27 28 29 30
Assuming your intent is to learn how to program (such as for a educational assignment), the following should help. If it's just to do the job, you should probably use some of the built-in Python modules (like datetime or calendar) since they'll do a lot of the hard work for you.
First, input returns a string and, when you iterate over a string (for n in month), you'll get one character at a time. So iterating over "May" will give you "M", "a", and "y", none of which are equal to "May". Don't iterate, just compare the entire string:
if month == "January" ...
Second, not all those months have 31 days, you'll need to distinguish those that have 30:
if month == "February":
doFebStuff()
elif month in ['September', 'April', 'June', 'November']:
do30DayStuff()
else:
do31DayStuff()
Third, you can't concatenate a string and a range, you'll need to do something like:
print(month, end='')
for i in range(1, 32):
print(f" {i}", end='')
print()
Fourth, again for the year, input gives you a string and you don't want to iterate over it. You also want to make it an integer if you're going to do mathematical calculations on it, something like:
year = int(input("Enter a year: "))
Fifth, the rules for leap years are slightly more complex than every four years, specifically:
if it's a multiple of 400, it's a leap year; else
if it's a multiple of 100, it's not; else
if it's a multiple of 4, it is; else
it's not.
Taking all that into account, here's one way to do it, with added checks for validity (month name and year):
Days30 = ["September", "April", "June", "November"]
Days31 = ["January", "March", "May", "July", "August", "October", "December"]
lastDay = None
month = input("Enter any month of the year: ")
if month == "February":
lastDay = 28
year = -1
while year < 0:
try:
year = int(input("Enter the year: "))
except:
year = -1
if year % 400 == 0 or (year % 100 != 0 and year % 4 == 0):
lastDay = 29
elif month in Days30:
lastDay = 30
elif month in Days31:
lastDay = 31
if lastDay is None:
print(f"I don't know the month {month}")
else:
print(f"{month}:", end="")
for day in range(1, lastDay + 1):
print(f" {day}", end="")
print()
I wouldn't try to pass that off as your own work (you'll almost certainly be pinged for plagiarism) but it's a good bit of code for getting some ideas.
If you are asking where did you go wrong, there are some places:
Your if and elif are not indented properly, they do not align.
When you write for n in month:, n takes value of every letter in the month inputed. e.g. if you entered "July", n would be iterating as "J", "u", "l", and "y". So comparing n to full names of months will always evaluate to False. Just compare the month instead of iterating over it.
When taking input, python stores the value entered by user as string (year = input("Enter a year")). So when you are iterating over the variable year (for i in year) you are iterating over a string of numbers and not the number. Furthermore, modulus operator won't work for strings (i % 4) as i in this case is a string. Just do year = int(input("Enter a year")) to convert year to ineger and do not iterate over it, check for remainder with 4 directly.
You can refer to the code by paxdiablo to get a working code.

Trying to build a python program that renders day of birth when user inputs birthday. Current attempt acts like a loop

We all know that in the Gregorian calendar that we are currently using, a random day of the week can be one of 7 options.
The intention of my code is based on a segment in Arthur Benjamin's Think Like A Math Genius (2006), whereby you can perform a simple party trick using mathematics. Using codes (basically implementing shortcuts based on the patterns of the Gregorian and finding the remainders after dividing by seven), one can quickly and accurately predict past and future days of the week.
My current attempt results in PyCharm overcomputing and eating up majority of CPU activity. I reckon that this could be because I have not limited the extent of user input 'Year' the same way I limited 'typedMonth'.
This is the original code:
print("Enter the full date: in dd/Month/yyyy")
Date = int(input("dd:"))
typedMonth = str(input("Month:"))
Year = int(input("yyyy: "))
while not int(Year) in range(0,3000):
Year = int(input("Please enter year (yyyy) limited to [0 - 3000] : "))
if typedMonth in ['January']:
Month = 3
while int(Year) % 4 == 0:
Month = 2
elif typedMonth in ['February']:
Month = 6
while int(Year) % 4 == 0:
Month = 5
elif typedMonth in ['March', 'November']:
Month = 6
elif typedMonth in ['April', 'July']:
Month = 2
elif typedMonth in ['May']:
Month = 4
elif typedMonth in ['August']:
Month = 5
elif typedMonth in ['September', 'December']:
Month = 1
elif typedMonth in ['October']:
Month = 3
elif typedMonth in ['June']:
Month = 0
else:
Month = 0
remYear = Year%400
if 300 <= remYear <= 400:
Year = Year + 1
elif 200 <= remYear <= 300:
Year = Year + 3
elif 100 <= remYear <= 200:
Year = Year + 5
else:
Year = Year + 0
print(remYear)
Day = (Date + int(Month) + remYear) % 7
print(Day)
Isolated testing shows that the first four lines of code work as intended (if I just print typedMonth), for instance.
In silo, the segment near the end from remYear= Year%400 also works as intended.
Hence, to my untrained eye, the 'overcomputation' is likely due to the stretch of code that I use to fix the Month variable from user input string typedMonth. To emphasise, the initial input for Month starts with the string typedMonth. I then use while statements to convert user input of string to an integer value. This integer value is attributed to variable 'Month' so that the final computation of integers 'Date', 'Month' and 'Year' can be made. Remainder will correspond to day of the week (e.g. 0 = Sunday, 1 = Monday, 2 = Tuesday, etc).
This is the updated code (third iteration). Thanks to the comments below, I am now able to enter most years as input and the program will run. Logic errors still persist, especially with the codes assigned to the months. I will fix them in future iterations.
print("Enter the full date: in dd/Month/yyyy")
Date = int(input("dd:"))
typedMonth = str(input("Month:"))
Year = int(input("yyyy: "))
while not int(Year) in range(1,3000):
Year = int(input("Please enter year (yyyy) limited to [0 - 3000] : "))
if typedMonth in ['January']:
Month = 3
while int(Year) % 4 == 0:
Month = 2
elif typedMonth in ['February']:
Month = 6
while int(Year) % 4 == 0:
Month = 5
elif typedMonth in ['March', 'November']:
Month = 6
elif typedMonth in ['April', 'July']:
Month = 2
elif typedMonth in ['May']:
Month = 4
elif typedMonth in ['June']:
Month = 0
elif typedMonth in ['August']:
Month = 5
elif typedMonth in ['September', 'December']:
Month = 1
elif typedMonth in ['October']:
Month = 3
remYear = Year%400
if 300 <= remYear <= 400:
Year = Year + 1
elif 200 <= remYear <= 300:
Year = Year + 3
elif 100 <= remYear <= 200:
Year = Year + 5
else:
Year = Year + 0
calcYear = int(Year % 100)
Day=(Date + Month + calcYear) % 7
print("The date is %d"%Date)
print("The month is %d"%Month)
print("The calculated year is %d"%calcYear)
print("The code for day is %d"%Day)
if Day in [0]:
print("You were born on a Sunday")
elif Day in [1]:
print("You were born on a Monday")
elif Day in [2]:
print("You were born on a Tuesday")
elif Day in [3]:
print("You were born on a Wednesday")
elif Day in [4]:
print("You were born on a Thursday")
elif Day in [5]:
print("You were born on a Friday")
elif Day in [6]:
print("You were born on a Saturday")
print("~~End Of Program~~")
Recommendations for restricting the range of computation of Year (limiting user input for Year does not fix the above problems) or restructuring the value for variable month from initial string input 'typedMonth' would be greatly appreciated.
P.S.1 Perhaps I should use another software for this project? I just started out with python so i don't know what applications would be more suited for such programs. Do recommend if you think that this could be a viable solution!
P.S.2 Made progress! The program kind of works for millennial babies (aka enter year after 2001), i still need to fix the logic!
P.S.3 Thanks to the comments below, I am now able to run the program. There are still glaring logic errors within the code. I endeavor to commence work on this project when time allows. I will update this post accordingly. Thanks for joining me in my learning journey!
You asked if Python was a suitable tool for this sort of project. It is, but it is much more suitable if you use it properly. In other words, don't make the problem unnecessarily difficult.
I understand your impulse to implement a particular algorithm to get comfortable with programming, but I have to say that this isn't a good choice. Date arithmetic is usually a pain. If you want to use computational shortcuts (and you should), then take a look at the shortcuts that the Python programming environment offers.
For example:
>>> import datetime
>>> from dateutil import parser
>>> date = "25/December/1999"
>>> datetime.datetime.strftime(parser.parse(date), "%A")
'Saturday'
The dateutil module isn't part of the standard library but it is well worth the trouble of installing.

Python Rainfall Calculator

I'm trying to solve a problem but I've been working on it for so long and have tried so many things but I'm really new to python and don't know how to get the input I'm after.
The calculator needs to be in a format of a nested loop. First it should ask for the number of weeks for which rainfall should be calculated. The outer loop will iterate once for each week. The inner loop will iterate seven times, once for each day of the week. Each itteration of the inner loop should ask the user to enter number of mm of rain for that day. Followed by calculations for total rainfall, average for each week and average per day.
The main trouble I'm having is getting the input of how many weeks there are and the days of the week to iterate in the program eg:
Enter the amount of rain (in mm) for Friday of week 1: 5
Enter the amount of rain (in mm) for Saturday of week 1: 6
Enter the amount of rain (in mm) for Sunday of week 1: 7
Enter the amount of rain (in mm) for Monday of week 2: 7
Enter the amount of rain (in mm) for Tuesday of week 2: 6
This is the type out output I want but so far I have no idea how to get it to do what I want. I think I need to use a dictionary but I'm not sure how to do that. This is my code thus far:
ALL_DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
total_rainfall = 0
total_weeks = 0
rainfall = {}
# Get the number of weeks.
while True:
try:
total_weeks = int(input("Enter the number of weeks for which rainfall should be calculated: "))
except ValueError:
print("Number of weeks must be an integer.")
continue
if total_weeks < 1:
print("Number of weeks must be at least 1")
continue
else:
# age was successfully parsed and we're happy with its value.
# we're ready to exit the loop!
break
for total_rainfall in range(total_weeks):
for mm in ALL_DAYS:
mm = int(input("Enter the amount of rain (in mm) for ", ALL_DAYS, "of week ", range(total_weeks), ": "))
if mm != int():
print("Amount of rain must be an integer")
elif mm < 0 :
print("Amount of rain must be non-negative")
# Calculate totals.
total_rainfall =+ mm
average_weekly = total_rainfall / total_weeks
average_daily = total_rainfall / (total_weeks*7)
# Display results.
print ("Total rainfall: ", total_rainfall, " mm ")
print("Average rainfall per week: ", average_weekly, " mm ")
print("Average rainfall per week: ", average_daily, " mm ")
if __name__=="__main__":
__main__()
If you can steer me in the right direction I will be so appreciative!
Recommendation: Break the problem into smaller pieces. Best way to do that would be with individual functions.
For example, getting the number of weeks
def get_weeks():
total_weeks = 0
while True:
try:
total_weeks = int(input("Enter the number of weeks for which rainfall should be calculated: "))
if total_weeks < 1:
print("Number of weeks must be at least 1")
else:
break
except ValueError:
print("Number of weeks must be an integer.")
return total_weeks
Then, getting the mm input for a certain week number and day. (Here is where your expected output exists)
def get_mm(week_num, day):
mm = 0
while True:
try:
mm = int(input("Enter the amount of rain (in mm) for {0} of week {1}: ".format(day, week_num)))
if mm < 0:
print("Amount of rain must be non-negative")
else:
break
except ValueError:
print("Amount of rain must be an integer")
return mm
Two functions to calculate the average. First for a list, the second for a list of lists.
# Accepts one week of rainfall
def avg_weekly_rainfall(weekly_rainfall):
if len(weekly_rainfall) == 0:
return 0
return sum(weekly_rainfall) / len(weekly_rainfall)
# Accepts several weeks of rainfall: [[1, 2, 3], [4, 5, 6], ...]
def avg_total_rainfall(weeks):
avgs = [ avg_weekly_rainfall(w) for w in weeks ]
return avg_weekly_rainfall( avgs )
Using those, you can build your weeks of rainfall into their own list.
# Build several weeks of rainfall
def get_weekly_rainfall():
total_weeks = get_weeks()
total_rainfall = []
for week_num in range(total_weeks):
weekly_rainfall = [0]*7
total_rainfall.append(weekly_rainfall)
for i, day in enumerate(ALL_DAYS):
weekly_rainfall[i] += get_mm(week_num+1, day)
return total_rainfall
Then, you can write a function that accepts that "master list", and prints out some results.
# Print the output of weeks of rainfall
def print_results(total_rainfall):
total_weeks = len(total_rainfall)
print("Weeks of rainfall", total_rainfall)
for week_num in range(total_weeks):
avg = avg_weekly_rainfall( total_rainfall[week_num] )
print("Average rainfall for week {0}: {1}".format(week_num+1, avg))
print("Total average rainfall:", avg_total_rainfall(total_rainfall))
And, finally, just two lines to run the full script.
weekly_rainfall = get_weekly_rainfall()
print_results(weekly_rainfall)
I use a list to store average rallfall for each week.
and my loop is:
1.while loop ---> week (using i to count)
2.in while loop: initialize week_sum=0, then use for loop to ask rainfall of 7 days.
3.Exit for loop ,average the rainfall, and append to the list weekaverage.
4.add week_sum to the total rainfall, and i+=1 to next week
weekaverage=[]
i = 0 #use to count week
while i<total_weeks:
week_sum = 0.
print "---------------------------------------------------------------------"
for x in ALL_DAYS:
string = "Enter the amount of rain (in mm) for %s of week #%i : " %(x,i+1)
mm = float(input(string))
week_sum += mm
weekaverage.append(weeksum/7.)
total_rainfall+=week_sum
print "---------------------------------------------------------------------"
i+=1
print "Total rainfall: %.3f" %(total_rainfall)
print "Day average is %.3f mm" %(total_rainfall/total_weeks/7.)
a = 0
for x in weekaverage:
print "Average for week %s is %.3f mm" %(a,x)
a+=1

Regarding summation with a for loop

I'm trying to get the user to input a birth date and then add the individual ints in those numbers. Also, if a sum of any of these digits is greater than or equal to 10, the loop repeats and the process runs again for the value. Here's my code so far
if (sumYear >= 10):
sumYear2=0
for num in str(sumYear):
sumYear2 += int(num)
print(sumYear2)
This works however I think it would be better done as a loop. And if there's some way I won't have to use something like sumYear2 that would be great. Note, I don't think I can use the sum() function.
Thanks guys for the help. I'm having an issue though. I'm not sure why this code isn't being evaluated when I provide the month as 02 and the day as 30
while True:
year=input("Please enter the year you were born: ")
month=input("Please enter the month you were born: ")
day=input("Please enter the day you were born: ")
if(int(month)==2 and int(day)<=29):
break
elif(int(month)==1 or 3 or 5 or 7 or 8 or 10 or 12 and int(day)<=31 ):
break
elif(int(month)==4 or 6 or 9 or 11 and int(day)<=30):
break
else:
print("Please enter a valid input")
Too much work.
singledigitsum = (int(inputvalue) - 1) % 9 + 1
Note that this will fail for numbers less than 1.
#Ignacio Vazquez-Abrams's answer provides the formula. But if there were none then your code as a loop without using sumYear2 could look like:
while sumYear >= 10:
sumYear = sum(map(int, str(sumYear)))
If you're not allowed to use sum (a homework) then:
while sumYear >= 10:
s = 0
for d in str(sumYear):
s += int(d)
sumYear = s
For the second question assuming Python 3:
while True:
try:
year = int(input("Please enter the year you were born: "))
month = int(input("Please enter the month you were born: "))
day = int(input("Please enter the day you were born: "))
birthday = datetime.date(year, month, day)
except ValueError as e:
print("error: %s" % (e,))
else:
break
If you are not allowed to use try/except then:
year = get_int("Please enter the year you were born: ",
datetime.MINYEAR, datetime.MAXYEAR)
month = get_int("Please enter the month you were born: ",
1, 12)
day = get_int("Please enter the day you were born: ",
1, number_of_days_in_month(year, month))
birthday = datetime.date(year, month, day)
Where get_int():
def get_int(prompt, minvalue, maxvalue):
"""Get an integer from user."""
while True:
s = input(prompt)
if s.strip().isdigit():
v = int(s)
if minvalue <= v <= maxvalue:
return v
print("error: the input is not an integer in range [%d, %d]" % (
minvalue, maxvalue))
And number_of_days_in_month():
# number of days in a month disregarding leap years
ndays = [0]*13
ndays[1::2] = [31]*len(ndays[1::2]) # odd months
ndays[::2] = [30]*len(ndays[::2]) # even months
ndays[2] = 28 # February
ndays[8] = 31 # August
# fill other months here ...
def number_of_days_in_month(year, month):
return ndays[month] + (month == 2 and isleap(year))
You can do this
>>> d=123456
>>> sum(int(c) for c in str(d))
21

Categories