leap year python script - python

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.

Related

Append based on another reference

Im allowed to use Numpy for the task.
I need to show the total sales in a month with two lists: dates and sales.
My approach is to make a list of all sales during a month by stripping the month off the date, creating a 2D matrix and adding the values that check for each month.
import numpy as np
dates = ["02/01/19", "03/02/19"]
sales = ["10.50", "12.20"]
month = [x.strip("0").split("/")[0] for x in dates]
monthsales = np.vstack((month, sales)).astype(np.float)
def monthlysales():
jan = []
for i in monthsales[0, 0:]:
if i == 1:
jan.append()
s = input("Pick month: ")
if s == "1":
print("Sales total for Jan is:", np.sum(jan), "USD")
else:
print("Not a valid month")
return
print(monthsales)
print(monthlysales())
The problem is that I dont know what to append so that it takes the second row of my matrix, which would complete the code
A solution keeping your logic:
Here I loop over the months (as you did, but here using enumerate), and look for when the month is equal to 1. Using enumerate allows us to know the column number of when the month equals 1 (id). Then it's just a matter of appending the sales (row 1) at the month we're interested in (id)
import numpy as np
dates = ["02/01/19", "03/02/19"]
sales = ["10.50", "12.20"]
month = [x.strip("0").split("/")[0] for x in dates]
monthsales = np.vstack((month, sales)).astype(np.float)
def monthlysales():
jan = []
# Loop over months with enumerate
for id, month in enumerate(monthsales[0]):
if month == 1:
# Append sales (row 1) at column id
jan.append(monthsales[1, id])
s = input("Pick month: ")
if s == "1":
print("Sales total for Jan is:", np.sum(jan), "USD")
else:
print("Not a valid month")
print(monthsales)
print(monthlysales())
Of course, since you're allowed to use numpy you could have avoided any looping altogether. Consider the following line:
monthsales[1, monthsales[0] == 1].sum()
This sums up the sales for all the January months in one line. No loops. For any reasonable amount of data this will be considerably quicker than the solution with enumerate.
Looking more like your initial solution you could have had:
def monthlysales():
s = int(input("Pick month: "))
if s >= 1 and s <= 12:
monies = monthsales[1, monthsales[0] == s].sum()
print("Sales total for month {} is {} USD".format(s, monies))
else:
print("Not a valid month")

Using numpy to calculate the day of of the week for a given dd/mm given the day of the Jan 1st

I am doing a past paper for exam revision and stuck on this question:
Write a python script to accept from the user the day of the week on which January 1st falls in a particular year, and then to print the day of the week for any other month and day of the month specified by the user. You may assume that year is not a leap year, that the user types the inputs as the first three letters of any word, and that the following code has previously been defined:
import numpy as np
months = np.array(['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'])
ndays = np.array([31,28,31,30,31,30,31,31,30,31,30,31])
days=np.array(['Mon','Tue','Wed','Thu','Fri','Sat','Sun'])
So I know how to take the input off the user by using the input command so I can create 3 variables:
user_Jan_1_day = input('Input the day of the week for Jan 1st: ')
user_month = input('Input the month: ')
user_day = input('Input the day of the month required: ')
So say the user said that Jan 1st was 'Sat', and they want the day of the week for 'Mar', '1' i.e. March 1st.
I know that I need to take 31 + 28 + 1. Find the sum = 60.
Take the modulus: 60%7 = 4, and then add four week days to 'Sat' to get 'Wed' as my answer, but how do I do it in Python?
I thought I could do this by using the index of the array so I used
a=np.where(months==user_month)
no_of_days = 0
for i in range (a):
no_of_days =+ ndays[i]
but I get an error: "'tuple' object cannot be interpreted as an integer"
Could someone show me how to do this?
Thank you!
Following pretty much your exact logic, you can do it like this, with no need to iterate (making sure to get int(input(...)) for user_day rather than the default string input):
user_Jan_1_day = input('Input the day of the week for Jan 1st: ')
user_month = input('Input the month: ')
user_day = int(input('Input the day of the month required: '))
m = np.where(months == user_month)[0][0]
d = np.where(days == user_Jan_1_day)[0][0]
# or, maybe more straightforward, since there is only one correct value:
# m = list(months).index(user_month)
# d = list(days).index(user_Jan_1_day)
result = days[(np.sum(ndays[:m]) + user_day + d) % 7]
For example:
>>> user_Jan_1_day = input('Input the day of the week for Jan 1st: ')
Input the day of the week for Jan 1st: Sat
>>> user_month = input('Input the month: ')
Input the month: Mar
>>> user_day = int(input('Input the day of the month required: '))
Input the day of the month required: 1
>>> m = np.where(months == user_month)[0][0]
>>> d = np.where(days == user_Jan_1_day)[0][0]
>>> result = days[(np.sum(ndays[:m]) + user_day + d) % 7]
>>> result
'Wed'
The range() function takes an integer. But a itself is not an integer. So try using range(a[0][0]):
for i in range(range(a[0][0])):
no_of_days += ndays[i]
no_of_days += int(user_day)
Also, your "=+" should be "+=" as shown here.
This gives you the desired date as the number of days into the calendar year. From there, you can use some modular arithmetic ("%") of that with the day for Jan 1st against your days array.

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.

Day of the week using Zeller's Congruence - Python 3

I just started studying Computer Science and I'm very new to python 3 and coding in general. Our first assignment is to calculate the day of the week using Zellers Congruence, and I have a few questions regarding the code that I have written.
year = int(input("Year: "))
while not int(year) in range(1583, 10000):
year = input("Out of allowed range 1583 - 9999. Please enter a valid
number: ")
month = int(input("Month: "))
while not int(month) in range(1, 13):
month = input("Out of allowed range 1 - 12. Please enter a valid number: ")
if month == 1 or month == 2:
month += 12
year -= 1
day = int(input("Day: "))
while not int(day) in range(1, 32):
day = input("Out of allowed range 1 - 31. Please enter a valid
number: ")
result = ( day + 13 * (month+1) // 5 + year + year // 4
- year// 100 + year // 400 ) % 7
weekday = {0: "Saturday",1: "Sunday", 2: "Monday",3: "Tuesday",4:
"Wednesday",5: "Thursday",6: "Friday"}
print("The day is " + weekday[int(result)] + ".")
First off, I'm supposed to make sure that the day range is related to the correct months. For example when the month input is 1, 3, 5, 7, 8, 10 or 12, the day interval should be 1 - 31. If the month input is 4, 6, 9, or 11 the day interval should be 1-30. And lastly I have to take leap years into account aswell. And I cant figure out how to write these requirements.
Also, all critique is welcome. I know that this is far from decent, so please let me know what I could do better!
Zeller's congruence handles the leap years correctly. If your problem is making sure the input date is a valid one, I believe the simplest approach will be creating a python datetime.date object using the user input.
import datetime
... # get user inputs
date = datetime.date(year, month, day)
If there is any invalid input, python will raise a meaningful exception. You don't need to do any validation yourself, just reading them as integers will be enough.

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