Context: Continuing with my self-learn of Python, I recently completed a textbook exercise that asked for a program that allowed the user to define 'x' number of years and to be able to input, for every month in 'x', a value for rainfall.
Issue: Below is my code, which works 'ok', however the latest exercise demands I 'expand' my code to present the numerically largest and smallest user input rainfall value, in a print statement.
Disclosure: I have looked on S.O to try finding the solution to my question, but nothing seems to be close enough to my challenge, to help me.
What I've tried: I have tried using max() and min() however I keep getting a TypeError: 'int' object is not iterable when I type the code print(max(monthlyRainfall) or print(min(monthlyRainfall)
def yearsToTrack():
userYearsTracking = int(input("How many years do you want to track: "))
return userYearsTracking
def calculationAlgorithm(userYearsTracking):
totalMonths = 0
totalRainfall = 0
for currentYear in range (1, userYearsTracking +1):
for currentMonth in range (1, 13):
monthlyRainfall = int(input("Inches of rainfall for month " + format(currentMonth, "d",) + " | year " +
format(currentYear, "d",)+": "))
totalMonths += 1
totalRainfall += monthlyRainfall
averageRainfall = totalRainfall / totalMonths
print("Total months: " + str(totalMonths))
print("Total rain:", format(totalRainfall), "(inch)")
print("Total average rainfall:", round(averageRainfall,2), "(inch)")
def main():
userYearsTracking = yearsToTrack()
calculationAlgorithm(userYearsTracking)
main()
Is anyone able to offer some 'pointers' as to where I am going wrong?
You can use sys.maxsize and 0 to intilize variables for tracking the minimum and maximum rainfall values that realistically the user will never enter above above or below respectively.
However for the second case just to make sure you can also add a simple check to ensure the user does not enter a negative rainfall amount:
def calculationAlgorithm(userYearsTracking):
totalMonths = 0
totalRainfall = 0
maxRainfall = 0
minRainfall = sys.maxsize
for currentYear in range (1, userYearsTracking +1):
for currentMonth in range (1, 13):
monthlyRainfall = int(input("Inches of rainfall for month " + format(currentMonth, "d",) + " | year " +
format(currentYear, "d",)+": "))
if monthlyRainfall < 0:
print("Error invalid rainfall entered")
sys.exit()
if monthlyRainfall > maxRainfall:
maxRainfall = monthlyRainfall
if monthlyRainfall < minRainfall:
minRainfall = monthlyRainfall
totalMonths += 1
totalRainfall += monthlyRainfall
averageRainfall = totalRainfall / totalMonths
print("Total months: " + str(totalMonths))
print("Total rain:", format(totalRainfall), "(inch)")
print("Total average rainfall:", round(averageRainfall,2), "(inch)")
print("Largest input rainfall: " + str(maxRainfall))
print("Smallest input rainfall: " + str(minRainfall))
Try out the full program with above changes here.
Example Usage:
How many years do you want to track: 1
Inches of rainfall for month 1 | year 1: 2
Inches of rainfall for month 2 | year 1: 2
Inches of rainfall for month 3 | year 1: 2
Inches of rainfall for month 4 | year 1: 2
Inches of rainfall for month 5 | year 1: 4
Inches of rainfall for month 6 | year 1: 1
Inches of rainfall for month 7 | year 1: 2
Inches of rainfall for month 8 | year 1: 2
Inches of rainfall for month 9 | year 1: 2
Inches of rainfall for month 10 | year 1: 2
Inches of rainfall for month 11 | year 1: 2
Inches of rainfall for month 12 | year 1: 2
Total months: 12
Total rain: 25 (inch)
Total average rainfall: 2.08 (inch)
Largest input rainfall: 4
Smallest input rainfall: 1
N.B. I have only used camelCase in naming the new variables as that is the style you are using. I would recommend changing all the names of the variables in your program to snake_case as that is the convention in python.
Python's built-in min() and max() functions expect iterable object like list, set, etc. I think you are putting only one integer which is not so correct (how can you pick min or max number when only 1 number given - obviously it is bot min and max).
One way of doing this would be:
declare list var:
rainfallList = []
Then when you get monthlyRainfall, you should add this code:
rainfallList.append(monthlyRainfall)
After all for loops you can use min(rainfallList) and/or max(rainfallList)
So your final code should be:
def yearsToTrack():
userYearsTracking = int(input("How many years do you want to track: "))
return userYearsTracking
def calculationAlgorithm(userYearsTracking):
totalMonths = 0
totalRainfall = 0
rainfallList = []
for currentYear in range (1, userYearsTracking +1):
for currentMonth in range (1, 13):
monthlyRainfall = int(input("Inches of rainfall for month " + format(currentMonth, "d",) + " | year " +
format(currentYear, "d",)+": "))
totalMonths += 1
rainfallList.append(monthlyRainfall)
totalRainfall += monthlyRainfall
averageRainfall = totalRainfall / totalMonths
print("Total months: " + str(totalMonths))
print("Total rain:", format(totalRainfall), "(inch)")
print("Total average rainfall:", round(averageRainfall,2), "(inch)")
print("Min rain:", format(min(rainfallList)), "(inch)")
print("Max rain:", format(max(rainfallList)), "(inch)")
def main():
userYearsTracking = yearsToTrack()
calculationAlgorithm(userYearsTracking)
main()
Related
I don't know how to triple the amount.
1st month's payment 1 dollar.
2nd month's payment 2 dollars. (doubled the amount)
3rd month's payment 6 dollars. (triple it every other months)
4th month's payment 12 dollars. (double the amount)
5th month's payment 36 dollars. (triple it every other month)
6th month's payment 72 dollars. (double the amount)
7th month's payment 216 dollars. (triple it every other month)
and so on ...
I'm using the for and if statements.
base = 1
payments = int(input("For how many months did they say you will receive payments? "))
for i in range(0, payments):
if i % 2 > 0:
base *= 3
else:
base *= 2
month = "Month " + str(i + 1) + ":" + str(base)
print(month)
for month 1 I get $2 and I expect to get $1
You could use modulus operator and on every odd entry, triple the amount.
base = 1
payments = 5
print("Month 1: %s" % base)
for i in range(2, payments):
if i % 2 == 1:
base *= 3
else:
base *= 2
print("Month %s: %s" % (i+1, base))
You can use a list of numbers to be multiplied for (2 and 3), while the installments are less than the input. The logic is to alternate between the two numbers of the list, while the condition is true:
base = 1
payments = input("For how many months did they say you will receive payments? ")
x = 1
multiplyList = [2, 3]
print(f'Month {x}: $ {base}')
while x <= int(payments):
i = 0
for number in multiplyList:
base = (base * multiplyList[i])
print(f'Month {x}: $ {base}')
i = i + 1
x = x + 1
# output:
# Month 1: $ 1
# Month 1: $ 2
# Month 2: $ 6
# Month 3: $ 12
# Month 4: $ 36
# Month 5: $ 72
# Month 6: $ 216
# Month 7: $ 432
# Month 8: $ 1296
# Month 9: $ 2592
# Month 10: $ 7776
EDIT: OP has edited the question to incorporate new attempts and
change the problem statement, so this is out of date.
As mentioned in other answers, your approach has a few drawbacks which make it non-ideal as a solution.
That being said, here is where the code went wrong:
Starting with a condensed version of your original:
base = 1
payments = 10
for i in range(payments):
month = "Month " + str(i + 1) + ":" + str(base)
base *= 2
if i in range(2, payments, 3):
base *= 3
print(month)
you need to end up here:
base = 1
payments = 10
for i in range(payments):
month = "Month " + str(i + 1) + ":" + str(base)
if i in range(1, payments, 3):
base *= 3
else:
base *= 2
print(month)
The changes needed are:
Using range(2, ...) instead of range(1, ...). This is because the way that you print and calculate you end up determining the new base during the previous month.
Moving *= 2 into an else: statement so you don't multiply by 6
This works:
base = 1
payments = int(input("For how many months did they say you will receive payments? "))
month = "Month " + str(1) + ":" + str(base)
print(month)
for i in range(1, payments):
if i % 2 > 0:
base *= 2
else:
base *= 3
month = "Month " + str(i + 1) + ":" + str(base)
print(month)
Because you were enetering straight into the for loop, it meant that you were doubling the first month. However if you print the first amount before the loop, start the loop at two, and swap the modulo statements around, it works.
This solution has only one print() statement to print month and amount, but it has an if == 0 in the loop
you could get rid of the if statement within the loop but had to add one more print line before the loop.
if you don't want to print intermediate results then you can start the range from 1, get ird of the if i == 0 and print the result after having left the for loop.
base = 1
payments = int(input("For how many months did they say you will receive payments? "))
print(base)
for i in range(0, payments):
if i == 0:
pass
elif i % 2 > 0:
base *= 2
else:
base *= 3
msg = "Month " + str(i + 1) + ":" + str(base)
print(msg)
My assignment is to calculate how much money a person would get if his salary started at 1 cent per day and doubled every day.
days = int(input("How many days will you work for pennies a day?"))
total_amount = ((2 ** (days - 1)) / 100)
print("Days Worked | Amount Earned That Day")
for num in range(days):
total_amount = format((2 ** (num) / 100), ',.2f')
print(num + 1, "|", "$", total_amount)
If I enter 15 for days, I can see the salary on each day, but I need the total amount earned over the 15 days.
I need the total amount earned over the 15 days
As a standard for loop example you want summation over each iteration. To achieve this, you initialize variable (total_accumulated in this case) with 0 and then add to this variable each intermediate result from each iteration, after loop is complete you print out final accumulated result like so (minimal editing of your original code):
days = int(input("How many days will you work for pennies a day?"))
total_amount = ((2 ** (days - 1)) / 100)
total_accumulated = 0
print("Days Worked | Amount Earned That Day")
for num in range(days):
current_pay = (2 ** (num) / 100)
total_accumulated += current_pay
total_amount = format(current_pay, ',.2f')
print(num + 1, "|", "$", total_amount)
print("Total accumulated:", str(total_accumulated))
As noted in comment to your question by #NiVeR this can be calculated directly, and this answer is aimed only at example with loops since this looks like classic case of exercise.
Keep track of today salary and previous day salary. previous to calculate today salary and today salary to calculate total
init_sal = .01
total = 0
today_sal = 0
days = int(input("How many days will you work for pennies a day?"))
for x in range(1, days+1):
if x == 1:
today_sal = init_sal
prev_sal = today_sal
else:
today_sal = prev_sal * 2
prev_sal = today_sal
total += today_sal
print ('$', today_sal)
print (total)
Having an issue with a certain part of the code (I am new to coding and have tried looking through StackOverflow for help):
def totalRainfall (rainfall):
totalRain = 0
month = 0
while month < len(rainfall):
totalRain = rainfall[month] + totalRain
month += 1
return totalRain
TypeError: Can't convert 'int' object to str implicitly
I've tried multiple ways of changing the code to make it a string explicitly as it still giving me various issues.
I'm also having a hard time enhancing the code to sort the array in ascending order and displays the values it contains.
The full code is here:
def main ():
rainfall = rainInput ()
totalRain = totalRainfall (rainfall)
average_Rainfall = averageRainfall (totalRain)
highestMonth, highestMonthly = highestMonthNumber (rainfall)
lowestMonth, lowestMonthly = lowestMonthNumber (rainfall)
print #this is for spacing output
print ('The total rainfall for the year was: ' +str(totalRain) + ' inche(s)')
print #this is for spacing output
print ('The average rainfall for the year was: ' +str(average_Rainfall) +\
' inche(s)')
print #this is for spacing in output
print ('The highest amount of rain was', highestMonthly, 'in' , highestMonth)
print #this is for spacing in output
print ('The lowest amount of rain was', lowestMonthly, 'in' , lowestMonth)
def rainInput ():
rainfall = ['January','Febuary','March','April','May','June','July','August'\
,'September','October','November','December']
month = 0
while month < len(rainfall):
rainfall[month] = input ('Please enter the amount for month ' + str\
(month + 1) + ': ')
month += 1
return rainfall
def totalRainfall (rainfall):
totalRain = 0
month = 0
while month < len(rainfall):
totalRain = rainfall[month] + totalRain
month += 1
return totalRain
def averageRainfall (totalRain):
average_Rainfall = totalRain / 12
return average_Rainfall
def highestMonthNumber (rainfall):
month = ['January','Febuary','March','April','May','June','July','August'\
,'September','October','November','December']
highestMonthly = 0
for m, n in enumerate(rainfall):
if n > highestMonthly:
highestMonthly = n
highestMonth = m
return month[highestMonth], highestMonthly
def lowestMonthNumber (rainfall):
month = ['January','Febuary','March','April','May','June','July','August'\
,'September','October','November','December']
lowestMonthly = 0
for m, n in enumerate(rainfall):
if n < lowestMonthly:
lowestMonthly = n
lowestMonth = m
return month[lowestMonth], lowestMonthly
main()
You have stored strings in your array rainfall, you need to convert them to ints before adding.
def totalRainfall (rainfall):
totalRain = 0
month = 0
while month < len(rainfall):
totalRain = int(rainfall[month]) + totalRain
month += 1
return totalRain
If you want the total rainfall as the sum of the numbers per month, simply use sum() on the list of ints. But as your error suggests, you have a list of strings, which you explicitly have to convert.
Something along the lines of
def totalRainfall (rainfall):
return sum([int(x) for x in rainfall])
The problem with your list being strings will continue to be problematic for you, so as a quick fix, I suggest you change this line
rainfall[month] = input ('Please enter the amount for month ' + str\
(month + 1) + ': ')
to
rainfall[month] = int(input('Please enter the amount for month ' + str\
(month + 1) + ': '))
That way your list contains only numbers and all your other comparisons will work.
You should also add this initialization in your lowestMonthNumber function to avoid UnboundLocalError: local variable 'lowestMonth' referenced before assignment:
lowestMonth = 0
Notice, that by initializing lowestMonthly to 0, you will most likely never get a correct result, since it is highly unlikely that any month has less rainfall.
I have been doing these for hours! please help! New to python
example 1990 for input year
and 2000 for end year.
basically i want the output to be
the years are 1992 1996 2000
there are 3 counts
I thought of converting them to a list and using len() but i do not know how
#inputs
year = int(raw_input("Input year: "))
endyear = int(raw_input("Input end year:"))
print "The number of leap years are "
counter = 0
for x in range(year,endyear+1):
if x % 4 == 0 and (x % 100 != 0 or x % 400 == 0):
counter +=1
print x
print counter
heres the current result :(
The number of leap years are
1900
0
1901
0
1902
0
1903
0
The problem was when needed year occur, the break stopped your loop.
year = int(raw_input("Input year: "))
end_year = int(raw_input("Input end year:"))
print "The number of leap years are "
counter = 0
temp = []
for x in range(year, end_year+1):
if x % 4 == 0 and (x % 100 != 0 or x % 400 == 0):
counter +=1
temp.append(x)
print('the years are {}'.format(temp))
print('there are {} counts'.format(counter))
You also might want to remove brackets in "the years are []", you can do that with
print('the years are ', ' '.join(map(str, temp)))
You can use the calendar.isleap to count the number of leap years between given years.
from calendar import isleap
year = int(raw_input("Input year: "))
endyear = int(raw_input("Input end year:"))
print "The number of leap years are "
counter = 0
years = []
for x in range(year,endyear+1):
if isleap(x):
counter +=1
print x
print counter
you can do it in a shorter way:
from calendar import isleap
years = [ str(x) for x in range(year,endyear+1) if isleap(x)]
print "the years are ", ''.join(elem + " " for elem in years)
print "there are ", len(years), "counts"
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