I'm an absolute beginner to Python and am tasked with creating a program that does a few things:
Inputs employee names into a list.
Inputs that employee's salary after inputting their name.
Totals the salaries in a list, (2 lists: names[] and salaries[]).
Finds the average salary after totaling.
Prints employees that earn within $5,000 of the average salary (Where I'm stuck).
Please see my code below:
# function to total the salaries entered into the "newSalary" variable and "salaries[]".
def totalSalaries(salaries):
total = 0
for i in salaries:
total += i
return total
# Finds the average salary after adding and dividing salaries in "salaries[]".
def averageSalaries(salaries):
l = len(salaries)
t = totalSalaries(salaries)
ave = t / l
return ave
# Start main
def main():
# Empty names list for "name" variable.
names = []
# Empty salaries list for "salary" and "newSalary" variables.
salaries = []
# Starts the loop to input names and salaries.
done = False
while not done:
name = input("Please enter the employee name or * to finish: ")
salary = float(input("Please enter the salary in thousands for " + name + ": "))
# Try/except to catch exceptions if a float isn't entered.
# The float entered then gets converted to thousands if it is a float.
try:
s = float(salary)
# Message to user if a float isn't entered.
except:
print("Please enter a valid float number.")
done = False
newSalary = salary * 1000
# Break in the loop, use * to finish inputting Names and Salaries.
if name == "*":
done = True
# Appends the names into name[] and salaries into salaries[] if * isn't entered.
# Restarts loop afterwards if * is not entered.
else:
names.append(name)
salaries.append(newSalary)
# STUCK HERE. Need to output Names + their salaries if it's $5,000 +- the total average salary.
for i in range(len(salaries)):
if newSalary is 5000 > ave < 5000:
print(name + ", " + str(newSalary))
# Quick prints just to check my numbers after finishing with *.
print(totalSalaries(salaries))
print(averageSalaries(salaries))
main()
Any info is greatly appreciated. I hope the rest of the functions and logic in this program makes sense.
Your haven't written your iterator correctly. With an array, you can just use for element in array: and the loop will iterate over array by putting each element in element. So your for loop becomes for salary in salaries.
Also, You need to split your condition in two and use additions and substractions. Your code should check if the salary is higher or equal to the average minus 5000 and if it is lower or equal to the average plus 5000. If you want to formalize this mathematically it would be:
Salary >= Average - 5000
and
Salary <= Average + 5000
So the condition at line becomes if salary >= (average - 5000) and salary <= (average + 5000)
Finally, you do not call averageSalaries before entering the loop, so the average salary haven't been computed yet. You should call the function and put the result in a variable before your for loop.
Related
I have a problem that I think is asking me to have a user enter a input into a array. I am having difficulties understanding this and any help would be appreciated.
The problem is as follows:
Design a program that lets the user enter the total rainfall for each of 12 months into an array. The program should calculate and display the total rainfall for the year, the average monthly rainfall, and the months with the highest and lowest amounts.
Here is what I have wrote so far:
def get_rainfall(a, b)
rain_array = []
rain_array.push(a => b)
puts rain_array
end
get_rainfall('january', 300)
Thanks for updating the question C_B.
I think the slight issue you're having here is between hashes and arrays.
Your current method results in the following:
#=> [{"january"=>300}, {"february"=>...}]
This happens because when you call rain_array.push(a => b), you're pushing a hash to the array each time in a => b.
It seems to me you'd be better suited storing the whole things as a hash, perhaps:
hash = {}
def get_rainfall(hash, key, value)
hash[key] = value
puts hash
end
get_rainfall(hash, 'january', 300)
# {"january"=>300}
get_rainfall(hash, 'february', 200)
#{"january"=>300, "february"=>200}
Hash you add more entries, they will be stored under the month as the key, with the rainfall as the value.
Alternatively, you could also push an array of arrays - to tweak your current method:
rain_array = []
def get_rainfall(array, a, b)
array.push([a, b])
puts array
end
get_rainfall(rain_array, 'january', 300)
# january
# 300
get_rainfall(rain_array, 'february', 200)
# january
# 300
# february
# 200
You'll notice I'm pulling the declaration of the array or hash to store the values outside of the method; without this, you'll lose access to it as soon as the method has run.
Hope that helps - happy to expand if you've any questions or queries. Let me know how you get on.
One more update based on a further comment about getting user input. Try the following to get you started:
hash = {}
def get_rainfall(hash, month)
puts "Please enter value for #{month}"
hash[month] = gets.chomp
puts hash
end
get_rainfall(hash, 'january')
I'll write my answer in simple script form to not over complicate what is being asked here.
The minimal approach is to not worry about month names for now and simply collect a list (array) of 12 values to do the calculations with.
rainfall = 1.upto(12).map do |month_nr|
# `print` and `puts` are practically the same with the only difference being
# that `puts` adds a newline character to the string if it doesn't have one
# output the question to the user
print "enter the rainfall for month #{month_nr}: "
# get the input from the user and convert it into an integer
gets.to_i # output the rainfall
end
puts "the total rainfall is: #{rainfall.sum}"
puts "the average rainfall is: #{rainfall.sum / rainfall.size}"
puts "the highest rainfall is: #{rainfall.max}"
puts "the lowest rainfall is: #{rainfall.min}"
If you care about month names you can do the following:
# create an array of all months
months = %w[January February March April May June July August September October November December]
# ask the user for each moth the amount of rainfall
rainfall = months.map do |month_name|
print "enter the rainfall for month #{month_name}: "
[month_name, gets.to_i] # output both the month name and the rainfall provided
end
# convert [['January', 123], ['February', 456], ...]
# to { 'January' => 123, 'February' => 456, ... }
rainfall = rainfall.to_h
puts "the total rainfall is: #{rainfall.values.sum}"
puts "the average rainfall is: #{rainfall.values.sum / rainfall.size}"
# search the key with the highest value
puts "the month with the highest rainfall is: #{rainfall.key(rainfall.values.max)}"
# search the key with the lowest value
puts "the month with the lowest rainfall is: #{rainfall.key(rainfall.values.min)}"
If anything is unclear have a look at the reference of the thing it is you have difficulty with. If it's still unclear ask away in the comments.
references:
String interpolation ("1 + 1 = #{1 + 1}")
Integer#upto
Enumerable#map
Kernel#print output to standard output without appending newline
Kernel#gets read from standard input
String#to_i
Kernel#puts output to standard output while appending a newline character (unless already present)
Array#sum
Array#size
Array#max
Array#min
%w array of strings
Array#to_h convert array to a hash
Hash#values
Hash#key
I don't understand why this code is not iterating properly?
income = 0
expenses = 10
profit = income - expenses
if profit <= 0:
income += 1
print(profit)
I would expect it to increment the income by one until 10, however it only runs once, outputting:
-10
Sincere thanks for answering something at the very, very bottom of the food chain.
You can use while loop as follows:
income = 0
expenses = 10
profit = income - expenses
while (profit <= 0):
income += 1
profit = income - expenses
print(income)
You print the difference profit which is indeed -10. Add a loop (while, for) to imcrement, if you have to, and then print income outside the loop.
Hi IF statement won't loop. It will execute the statements under it when the condition is satisfied.
Use While where it loops until the condition is satisfied.
I want to be able to randomly select 5 rows in C
Thanks.
Let's think aloud a bit.
If you just need to select 5 arbitrary numbers that happen to sum up to a number below a given N, you can cheat and select just the 5 smallest numbers; if they sum up to a number larger than N,choosing any other numbers won't help, too, and you register an error.
If you want your numbers to sum up quite close to N (the user asked 20 minutes, you try to offer something like 19 minutes and not 5), it becomes a knapsack problem, which is hard, but maybe various approximate ways to solve it could help.
If you just want to choose 5 random numbers that sum up to N, you can keep choosing 5 numbers (songs) randomly and check. You'll have to limit the number of tries done and/or time spent, and be ready to report a failure.
A somehow more efficient algorithm would keep a list of songs chosen so far, and the sum of their lengths s. It would try to add to it a random song with length ≤ N - s. If it failed after a few attempts, it would remove the longest song from the list and repeat. It must be ready to admit failure, too, based on the total number of attempts made and/or time spent.
I don't think a simple SQL query could efficiently solve this problem. You can approximately encode the algorithm above as a very complex SQL query, though. I'd rather encode it in Python, because local SQLite lookups are pretty fast, provided that your songs are indexed by length.
A possible solution is to only select songs for which the individual length is < 500. Then you keep as much of them as you can. If you have less than 5 or if the total time is < 500, then you iterate or recurse for find some songs for the unused time.
def createtimeplay(timee, tot = None, tot_time = 0):
if tot is None: tot= [] # at first call initialize the result list
# exclude previously selected songs from the search
qry = "SELECT * FROM songs WHERE length <= ?"
if len(tot) > 0:
qry += " and name not in (" + ','.join(['?'] * len(tot)) + ')'
qry += " ORDER BY RANDOM() LIMIT 5 "
curs = c.execute(qry, [timee] + [song[0] for song in tot])
cur = (curs.fetchall())
if len(cur) == 0: return tot # no song were found: we can return
# keep songs that fit in allowed time
cur_time = 0
for song in cur:
if cur_time + song[1] <= timee:
cur_time += song[1]
tot.append(song)
if (len(tot) == 5) return tot # never more than 5 songs
tot_time += cur_time # total songs time
if len(tot) != 5 and cur_time != timee: # if not all recurse
createtimeplay(timee - tot_time, tot, tot_time)
return tot
The trick is that we pass a list which is a modifiable object, so all recursive calls add songs to the same list.
You can then use:
>>> print(createtimeplay(500))
[('Song 18', 350, 'Country', 'z'), ('Song 4', 150, 'Pop', 'x')]
>>> print(createtimeplay(500))
[('Song 12', 200, 'Country', 'z'), ('Song 3', 100, 'Country', 'z'), ('Song 14', 200, 'Rap', 'y')]
>>> print(createtimeplay(500))
[('Song 5', 300, 'Rap', 'y'), ('Song 7', 200, 'Pop', 'x')]
>>>
But previous solution is very inefficient: it requires more than one query, when each query is a full table scan because of the order by random(), and uses recursion when it could easily be avoided. It would be both simpler and more efficient to only do a full table scan at sqlite level, shuffle the result in sqlite or Python, and then just scan once the full randomized list of songs, keeping a maximum number of 5 with a constraint of the total length.
Code is now much simpler:
def createtimeplay(tim, n, con):
songs = c.execute("""SELECT name, length, genre, artist
FROM songs
WHERE length < ? ORDER BY RANDOM()""", (tim,)).fetchall()
result = []
tot = 0
for song in songs:
if song[1] <= tim:
tim -= song[1]
result.append(song)
if len(result) == n or tim == 0: break
return result
In this code, I choosed to pass the maximum number and a cursor or a connection to the sqlite database as parameters.
I'm having a lot of trouble dealing with with a particular question in my critical thinking class.
The task is this:
Task
Develop an algorithm to prompt for and obtain maximum daily temperatures for a whole year. However, in order to consider leap years, your algorithm should first prompt the user for the number of days in this particular year. That is, your algorithm should expect 365 or 366 as the first input number followed by input temperature values.
In addition, for this particular year, your algorithm must also determine and display the average, maximum, and minimum of these temperatures values.
Here's an example of what needs to happen:
Prompt for number of days in a year
(let's say they enter 365)
Then prompt user for MAXIMUM daily tempretures for 365 days.
Take those 365 (individual) maximum tempretures, find the lowest value that will = Min_temp.
Take those 365 (individual) maximum tempretures, find the highest value that will = Max_temp.
Sum up all 365 invidual max tempretures and divide it by the number of days in the year (365) = Avg_temp.
Print Min_temp
Print Max_temp
Print Avg_temp
So far this is what I have:
1. Prompt operator to enter Number_Of_Days within year.
2. WHILE Number_Of_Days = 365 or 366 THEN
3. IF Number_Of_Days is = 365 THEN
4. Year = 365
5. ELSEIF Number_Of_Days = 366 THEN
6. Year = 366
7. ENDIF
8. ELSEWHILE Number_of_Days is NOT = 365 or 366 THEN
9. Print ‘ERROR: Please enter a number that is 365 or 366.’
10. Prompt operator to enter Number_Of_Days within year.
11. ENDWHILE
12. DOWHILE MaxDayTemp = 1 to Year
16. Prompt operator for MaxDailyTemp
15. ENDO
From here we're meant to get an average of all the maximum temps provided by the user, that's easily done by AVG_TEMP = Sum of Temps / Days in the year.
What I can't work out is how to take the values of each day and find the lowest and highest values that are provided.
I've been trying to work it out with an array but I'm totally confused by it.
Please help! :(
I think you are expecting something like this, tried to use your conversion. Format it as you want.
i=0;
tempsum=0;
tempmax=0;
tempmin=100;
currenttemp=0;
no_days=0;
// variables used to store values
do
(prompt user for number of days)
no_days = user input
while no_days!=365 or no_days!=366 // will loop until user enter 365 or 366
while i<no_days
do
(Prompt operator for MaxDailyTemp)
currenttemp = userinput
while (currenttemp value is invalid) // thinking in the same way as above
if currenttemp > tempmax
tempmax = currenttemp
else if currenttemp < tempmin
tempmin = currenttemp
tempsum = tempsum + currenttemp
i = i+1
end
display average temp. = tempsum/no_days
display max temp. = tempmax
display min temp. = tempmin
I don't know what syntax is required for your class but this
max = (1 st value)
min = (1 st value)
i = 2
WHILE i < year THEN
IF (i th value) > max THEN
max = (i th value)
ELSIF (i th value) < min THEN
min = (i th value)
i = i + 1
would get the min and max value.
import sgenrand
# program greeting
print("The purpose of this exercise is to enter a number of coin values")
print("that add up to a displayed target value.\n")
print("Enter coins values as 1-penny, 5-nickel, 10-dime,and 25-quarter.")
print("Hit return after the last entered coin value.")
print("--------------------")
#print("Enter coins that add up to 81 cents, one per line.")
total = 0
#prompt the user to start entering coin values that add up to 81
while True:
final_coin= sgenrand.randint(1,99)
print ("Enter coins that add up to", final_coin, "cents, on per line")
user_input = int(input("Enter first coin: "))
if user_input != 1 and user_input!=5 and user_input!=10 and user_input!=25:
print("invalid input")
total = total + user_input
while total != final_coin:
user_input = int(input("Enter next coin:"))
total = total + user_input
if user_input == input(" "):
break
if total > final_coin:
print("Sorry - total amount exceeds", (final_coin))
if total < final_coin:
print("Sorry - you only entered",(total))
if total== final_coin:
print("correct")
goagain= input("Try again (y/n)?:")
if goagain == "y":
if goagain == "n":
print("Thanks for playing ... goodbye!" )
I've been trying to create this loop, so it can repeat the whole program at the end when the user accepts/ if he accepts to do it again at the end.
I know you have to have a while statement around your whole program, but with my while true statement at the top, it only repeats the first part of my program and not the whole thing.
Well one thing you should be careful of is that you do not set the
total = 0
at the start of each loop. So when the user plays the game again. He will continue using his previous total. You should move total = 0 to the start of the loop
while True:
total = 0
Additionally, you need to deindent you first
while True
statement as it does not align properly with the rest of your code.
Finally, you need to allow the user to exit the while loop after he selects No for trying again.
if goagain == "n":
print("Thanks for playing ... goodbye!" )
break
This can be done by applying a break statement.