How to improve this


#1



It is an age calculator, which works fine (well sometimes) and it also passed, but is there a way to reduce its size and make it work more often with the stuff i have learned up to this point?


print "Welcome to the Age Calculator"

m = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
t = []
Year = int(raw_input("In what year were you born? (numbers only)"))
Month = raw_input("In what month were you born? (captitalize first letter)")
Day = int(raw_input("In what day were you born? (numbers only)"))

current_year = int(raw_input("What is the current year? (numbers only)"))
current_month = raw_input("What month are we in? (capitalize first letter)")
current_day = int(raw_input("What is the current Day? (numbers only)"))

if current_month == "January":
    t.append(m[1])
    t.append(m[2])
    t.append(m[3])
    t.append(m[4])
    t.append(m[5])
    t.append(m[6])
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "February":
    t.append(m[2])
    t.append(m[3])
    t.append(m[4])
    t.append(m[5])
    t.append(m[6])
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "March":
    t.append(m[3])
    t.append(m[4])
    t.append(m[5])
    t.append(m[6])
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "April":
    t.append(m[4])
    t.append(m[5])
    t.append(m[6])
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "May":
    t.append(m[5])
    t.append(m[6])
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "June":
    t.append(m[6])
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "July":
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "August":
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "Spetember":
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])
elif current_month == "October":
    t.append(m[10])
    t.append(m[11])
elif current_month == "November":
    t.append(m[11])







def age(x, Month, z):

    a = current_year - x
    if Month == current_month and z > current_day:
        a-=1
        print "You are ", a,"Years old."
    elif Month == current_month or Month == t[0] or Month == t[1] or Month == t[2] or Month == t[3] or Month == t[4] or Month == t[5] or Month == t[6] or Month == t[7] or Month == t[8] or Month == t[9] or Month == t[10] or Month == t[11]:
        a-=1
        print "You are ", a, "years old."
    else:
        print "You are ", a, "years old."
    
            
            
    for i in range(1):
        i = raw_input("is this correct? (yes or no)")
        if i == "yes":
            print "I'm always right!"
        elif i == "no":
            print "Impossible! Trust me, I'm way smarter than you!"
        else:
            print "Wow are you too scared to admit how awesome I am?"
    

age(Year, Month, Day)


#2

this:

if current_month == "January":
    t.append(m[1])
    t.append(m[2])
    t.append(m[3])
    t.append(m[4])
    t.append(m[5])
    t.append(m[6])
    t.append(m[7])
    t.append(m[8])
    t.append(m[9])
    t.append(m[10])
    t.append(m[11])

is not very efficient. I don't know what you learned so far, but i would recommend to use .index() to get the month from m list and then use a loop + range to append all the values to t

don't forgot to start range at index + 1 given lists are zero index based

also, i would just convert the user input to lowercase (.lower()) so that what the user inputs is case-insensitive.


#3

Thanks. This helped a lot.


#4

This is the trickiest bit of programming, designing an efficient solution to solve the problem (calculating someones age)

@mariotheastronomer, also you should get the current date and time from datetime module.

from  datetime import datetime
print datetime.now().date

see if you can figure out a more efficient way. After you are done, post an updated version of your code, see if we can improve the program even more

you can also get the day:

print datetime.now().day

same for month and year


#5

Right off the hop we're going to chase the complexity away, then work backwards to a useful algorithm, at least that is the goal. Let's start with the question, "how old are you?"

>>> from datetime import date
>>> from datetime import timedelta
>>> today = date.today()
>>> weegillis = date(1998, 1, 25)
>>> int((today - weegillis).days / 365)    # timedelta object expressed
19
>>>

Now the work begins to roll out an algo that will give us the same thing.


Looking at your code...

We can define t with all the necessary elements without direct addressing or .append.

>>> m = [
	"January", "February", "March", "April", "May", "June",
	"July", "August", "September", "October", "November", "December"
	]
>>> t = m[m.index('January') + 1:]
>>> t
['February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
>>>

Note we didn't even need to initialize t as an empty list.


#6

In the function age you are calling t and cureent_year without passing them to the function.

Another way to do this is with a dictionary. Take the first three letters of the month (helps prevent typos throwing the script and allows for abbreviations) as they key and returning the relevant month number as the value. Then with the raw input you just limit to the first three and even check is it is a digit already. If it is then you don't need to call the dictionary. With a number rather than a string we can use operators to find out of the months has passed or not.

Of course, you could just force the user to input a number from 1 to 12 to begin with and save the overhead of everything else. On top of that, rather than getting the user to input the year, month and day separately you could get them to enter it once as DD/MM/YYYY or whatever format you want.

months = {"jan": 1, "feb": 2, "mar": 3, "apr": 4,
          "may": 5, "jun": 6, "jul": 7, "aug": 8,
          "sep": 9, "oct": 10, "nov": 11, "dec": 12}

Year = int(raw_input("In what year were you born? (numbers only)"))
Month = raw_input("In what month were you born?").lower()
Day = int(raw_input("In what day were you born? (numbers only)"))

if not Month.isdigit():
    Month = months(Month[:3]]
else:
    Month = int(Month)

current_year = int(raw_input("What is the current year? (numbers only)"))
current_month = raw_input("What month are we in?").lower()[:3]
current_day = int(raw_input("What is the current Day? (numbers only)")) 

if not current_month.isdigit():
    current_month = months[current_month[:3]]
else:
    current_month = int(current_month)

def age(months, birthYear, birthMonth, birthDay, currentYear, currenyMonth, currentDay):
    if birthMonth < currenyMonth or   birthMonth == currenyMonth and birthDay <= currentDay:
        print currentYear - birthYear
    else :
        print currentYear - birthYear - 1

#7

I meant to ask earlier, is this a lesson in the Python track? Don't remember doing this one. If it is, please post a link and I'll move this thread into the correct forum, as applies.


#8

If the input is not a number, an exception will be raised. The check will not be reached.


#9

The check is for the month variables, not the year variables.


#10

That it is. I'm only pointing out that if either the year or day are not numbers, an exception will be raised in any event. That check will not be reached. MInd if we are in a perfect world scenario, as so much beginner code is assumed to be...


#11

As you say validation of input was ignored. This was to demonstrate the implementation of a dictionary doing the same thing.

The isdigit check was to stop the potential for a KeyError that would occur if the number was put in as free choice is technically given and this potential error was introduced by the dictionary. Also, the other two explicitly ask for a number so shouldn't be surprising to a user if a non-number throws an error. As you say, it still assumes perfect world as it allows anything beyond 1-12 and no checks on any values entered are done.


#12

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.