I'm attempting to create a menu-driven program where python will accept a collection of non-negative integers. It will calculate the mean and median and display the values on the screen. I want my first option to be "Add a number to the list/array", I want my second option to be "Display the mean", the third to be "Display the median", the fourth "Print the list/array to the screen", the fifth "Print the list/array in reverse order" and the last option "Quit". So far I have gotten:
def main():
myList = [ ]
addOne(myList)
choice = displayMenu()
while choice != '6':
if choice == '1':
addOne(myList)
elif choice == '2':
mean(myList)
elif choice == '3':
median(myList)
elif choice == '4':
print(myList)
elif choice == '5':
print(myList)
choice = displayMenu()
print ("\nThanks for playing!\n\n")
def displayMenu():
myChoice = '0'
while myChoice != '1' and myChoice != '2' \
and myChoice != '3' \
and myChoice != '4' and myChoice != '5':
print("""\n\nPlease choose
1. Add a number to the list/array
2. Display the mean
3. Display the median
4. Print the list/array to the screen
5. Print the list/array in reverse order
6. Quit
""")
myChoice = input("Enter option---> ")
if myChoice != '1' and myChoice != '2' and \
myChoice != '3' and myChoice != '4' and myChoice != '5':
print("Invalid option. Please select again.")
return myChoice
#This should make sure that the user puts in a correct input
def getNum():
num = -1
while num < 0:
num = int(input("\n\nEnter a non-negative integer: "))
if num < 0:
print("Invalid value. Please re-enter.")
return num
#This is to take care of number one on the list: Add number
def addOne(myList):
while True:
try:
num = (int(input("Give me a number:")))
num = int(num)
if num < 0:
raise exception
print("Thank you!")
break
except:
print("Invalid. Try again...")
myList.append(num)
#This should take care of the second on the list: Mean
def mean(myList):
myList = [ ]
listSum = sum(myList)
listLength = len(myList)
listMean = listSum / listLength
print("The mean is", listMean)
#This will take care of number three on the list: Median
def median(myList):
median = 0
sortedlist = sorted(myList)
lengthofthelist = len(sortedlist)
centerofthelist = lengthofthelist / 2
if len(sortedlist) % 2 ==0:
return sum(num[center - 1:center + 1]) / 2.0
else:
return num[center]
print("The mean is", centerofthelist)
#This will take care of the fourth thing on the list: Print the list (In order)
def sort(myList):
theList.sort(mylist)
print(myList)
#This will take care of the fifth thing on the list
def reversesort(myList):
theList.sort(reverse=True)
print(myList)
main()
After I run the program I can't get past creating the list.
Corrected code with minimum changes:
def main():
myList = []
choice = 1
while choice != 6:
if choice == 1:
option1(myList)
elif choice == 2:
option2(myList)
elif choice == 3:
option3(myList)
elif choice == 4:
option4(myList)
elif choice == 5:
option5(myList)
choice = displayMenu()
print ("\nThanks for playing!\n\n")
def displayMenu():
myChoice = 0
while myChoice not in [1, 2, 3, 4, 5]:
print("""\n\nPlease choose
1. Add a number to the list/array
2. Display the mean
3. Display the median
4. Print the list/array
5. Print the list/array in reverse order
6. Quit
""")
myChoice = int(input("Enter option---> "))
if myChoice not in [1, 2, 3, 4, 5]:
print("Invalid option. Please select again.")
return myChoice
# Option 1: Add a number to the list/array
def option1(myList):
num = -1
while num < 0:
num = int(input("\n\nEnter a non-negative integer: "))
if num < 0:
print("Invalid value. Please re-enter.")
myList.append(num)
# Option 2: Display the mean
def option2(myList):
print("The mean is ", sum(myList) / len(myList))
# Option 3: Display the median
def option3(myList):
sortedlist = sorted(myList)
if len(sortedlist) % 2:
median = myList[int(len(sortedlist) / 2)]
else:
center = int(len(sortedlist) / 2)
median = sum(myList[center-1:center+1]) / 2
print("The median is", median)
# Option 4: Print the list/array
def option4(myList):
print(sorted(myList))
# Option 5: Print the list/array in reverse order
def option5(myList):
print(sorted(myList, reverse=True))
main()
How I would do this:
The first part of the following code are a set of constants to customize the style of the menu. Then a set of functions representing each option are defined. The following 3 functions should not be modified, they generate the menu, display it and close the application. Then the main section starts, where you need to pass every option as an argument to setOptions(). The rest should not be modified either as it is the main loop.
# Menu formatting constants
MENU_HEADER = "Please choose an option:"
MENU_FORMAT = " * {:2}. {}"
MENU_QUIT_S = "Quit"
MENU_ASK_IN = "Enter option: "
MENU_INT_ER = "ERROR: Invalid integer. Please select again."
MENU_OPT_ER = "ERROR: Invalid option. Please select again."
END_MESSAGE = "Thanks for playing!"
# OPTIONS FUNCTIONS START HERE
def addElement(l):
""" Add a number to the list/array. """
n = -1
while n < 0:
try:
n = int(input("Enter a non-negative integer: "))
except ValueError:
print("It needs to be an integer.")
n = -1
else:
if n < 0:
print("It needs to be a non-negative integer.")
l.append(n)
def mean(l):
""" Calculate the mean. """
print("Mean: {:7.2}".format(sum(l) / len(l)))
def median(l):
""" Calculate the median. """
l = sorted(l)
p = int(len(l) / 2)
print("Median: {:7.2}".format(l[p] if len(l)%2 else sum(l[p-1:p+1])/2))
def oprint(l):
""" Print the list/array. """
print(sorted(l))
def rprint(l):
""" Print the list/array in reverse order. """
print(sorted(l, reverse=True))
# OPTIONS FUNCTIONS END HERE
def onQuit(l):
""" Function to execute when quitting the application. """
global quit
quit = True
print(END_MESSAGE)
def setOptions(*args):
""" Generates the menu and the options list. """
# Menu header and quit option (option 0)
menu = [MENU_HEADER]
options = [onQuit]
# Passed arguments represent texts and functions of additional options
for i, f in enumerate(args, start=1):
menu.append(MENU_FORMAT.format(i, f.__doc__.strip()))
options.append(f)
# We print the option 0 the last one
menu.append(MENU_FORMAT.format(0, MENU_QUIT_S))
# Returning both the menu and the options lists
return tuple(menu), tuple(options)
def displayMenu(menu):
""" Display the menu and get an option that is an int. """
while True:
for line in menu:
print(line)
try:
choice = int(input(MENU_ASK_IN))
except ValueError:
print(MENU_INT_ER)
else:
return choice
if __name__ == '__main__':
# Pass the option functions to the setOptions function as arguments
menu, options = setOptions(
addElement,
mean,
median,
oprint,
rprint
)
# Initiate the needed variables and start the loop
l = []
quit = False
while not quit:
c = displayMenu(menu)
try:
f = options[c]
except IndexError:
print(MENU_OPT_ER)
else:
f(l)
There is an indentation error inside your function addOne.
myList.append(num) is inside the while loop, and just before that you have a break, so the number is never appended to the list because we have left the loop already.
Related
I have a program that is for conversions of simple metrics. I'm a super noob to python and could use a little help.
def main():
use_menu()
if feet_inches():
def use_menu():
get_menu()
selection = int(input('Please make a menu selection:'))
if selection == 1:
feet_inches()
elif selection == 2:
yards_feet()
elif selection == 3:
miles_yards()
elif selection == 4:
miles_feet()
def get_menu():
print('1. Convert feet to inches')
print('2. Convert yards to feet')
print('3. Convert miles to yards')
print('4. Convert miles to feet')
print('5. Exit')
def feet_inches():
feet2inches = int(input('Enter the number of feet:'))
answer1 = feet2inches / 3
return answer1
def yards_feet():
yards2feet = int(input('Enter the number of yards:'))
answer2 = yards2feet * 3
return answer2
def miles_yards():
miles2yards = int(input('Enter the number of miles:'))
answer3 = miles2yards * 1760
return answer3
def miles_feet():
miles2feet = int(input('Enter the number of miles:'))
answer4 = miles2feet * 5280
return answer4
main()
How do I print the returned values in my main function? I keep getting unresolved reference when I try to set answer1 to a variable in the main function. I'm also struggling with how to write the if/elif for that. Just a little nudge in the right direction would be appreciated.
Line 3:
if feet_inches():
there is no conditional action underneath.
You could try something like this: Remove line 3 above.
def use_menu():
get_menu()
selection = int(input('Please make a menu selection:'))
if selection == 1:
fi = feet_inches()
print(fi)
elif selection == 2:
yf = yards_feet()
print(yf)
elif selection == 3:
my = miles_yards()
print(my)
elif selection == 4:
mf = miles_feet()
print(mf)
You can use return statements in the use_menu aswell. And then set the answer equal to what is returned by that function in the main function.
def main():
answer = use_menu()
print(answer)
def use_menu():
get_menu()
selection = int(input('Please make a menu selection:'))
if selection == 1:
return feet_inches()
elif selection == 2:
return yards_feet()
elif selection == 3:
return miles_yards()
elif selection == 4:
return miles_feet()
You could change your code as follows:
def main():
# First, retrieve function to be applied
func = use_menu()
if func is not None:
# Apply function - Could be done in one liner
res = func()
print(res)
def use_menu():
get_menu()
selection = int(input('Please make a menu selection:'))
if selection == 1:
return feet_inches
elif selection == 2:
return yards_feet
elif selection == 3:
return miles_yards
elif selection == 4:
return miles_feet
else:
return None
I am trying to increase the correct answer count by 1 every time the users answer is correct. However, when parsed into the display_result() function, the correct function displays "0 correct"
I haven't been able to get this working no matter how I try to wiggle around it, so any help is really appreciated.
code removed for academic integrity
If the user has answered 1 of 3 questions correctly, I expect the answer to be "You have answer 1 questions out of 3 correctly."
Currently, it would display you have answered 0 questions out of 3 correctly"
In menu_option() you never modify count, so it stays at 0. Two simple fixes. Change to:
count = check_solution(user_solution, real_solution, count)
return count
Or just
return check_solution(user_solution, real_solution, count)
One other thing I noticed: in get_user_input() you need to return the result of the recursive calls:
else:
print("Invalid input, please try again")
return get_user_input()
There are a number of problems:
you are doing correct = menu_option(option, correct) when instead you should be accumulating the correct scores like correct +=
in the menu_option you are never assigning to count, I presume it should be count = check_solution(...)
you shouldn't do return option for index == 5 because that will add to the correct.
Finally the code run as I expected(python3.6+ is required):
#!/usr/bin/env python3
import random
def get_user_input():
while True:
try:
index = int(input("Enter your choice: "))
if 0 < index < 6:
return index
except ValueError:
print("Invalid input, should be Integer.\n")
else:
print("Invalid input, please try again")
def get_user_solution(problem):
while True:
print("Enter your answer")
user_solution = input(f"{problem} = ")
try:
return float(user_solution)
except ValueError:
print("Invalid input, should be float\n")
def check_solution(user_solution, solution, count):
if user_solution == solution:
print("Correct.")
return count + 1
else:
print("Incorrect.")
return count
def menu_option(index, count):
first_num = random.randrange(1, 21)
second_num = random.randrange(1, 21)
if index == 1:
problem = f"{first_num} + {second_num}"
real_solution = first_num + second_num
print(real_solution)
user_solution = get_user_solution(problem)
return check_solution(user_solution, real_solution, count)
if index == 2:
problem = f"{first_num} - {second_num}"
real_solution = first_num - second_num
print(real_solution)
user_solution = get_user_solution(problem)
return check_solution(user_solution, real_solution, count)
if index == 3:
# blah blah blah, repeated code but removed for neatness
pass
if index == 5:
option = 5
return option
def display_result(total, correct):
if total == 0:
print("You answered 0 questions with 0 correct")
print("Your score is 0.0%")
else:
percentage = round(correct / total * 100, 2)
print(
f'You answered {total} questions with {correct} correct.\n'
f'Your score is {percentage}%'
)
def display_intro():
pass
def display_menu():
pass
def display_separator():
print('-'*20)
def main():
display_intro()
display_menu()
display_separator()
option = get_user_input()
total = 0
correct = 0
while option != 5:
total = total + 1
correct = menu_option(option, correct)
option = get_user_input()
print("Exit the quiz.")
display_separator()
display_result(total, correct)
if __name__ == "__main__":
main()
Whenever I run the display_data function (when there is data to be run after successfully answering at least one calculation_game question) I get an error that says:
"ValueError: to_rgba: Invalid rgba arg "o"
to_rgb: Invalid rgb arg "o"
could not convert string to float: 'o'"
When I run the code without the "o" to define the shape of the points it works fine and displays blue points. Only thing is that I want to be able to define shapes such as "o" and "v" because the plot will be showing data from multiple list when it is done. Any ideas?
NOTE:
There are missing functions below. I removed them here because they are not needed for the question.
import random
from random import randint
import time
import math
import matplotlib.pyplot as plt
# Number of problems for each practice/real round
practice_round = 0
real_round = 3
main_record = []
CALC_RECORD = []
# (1) Calculation Game ---------------------------------------------------------
'''Calculation game is a math game'''
def calculation():
response_time = None
# Determine the min and max calculation values
min_calculation_value = 1
max_calculation_value = 10
# Generate the problems
print('\nSolve the following problem:')
a = random.randint(min_calculation_value, max_calculation_value)
b = random.randint(min_calculation_value, max_calculation_value)
problem_type = random.randint(1,2)
if problem_type == 1:
answer = a * b
print(a, '*', b)
elif problem_type == 2:
answer = a % b
print(a, '%', b)
# Get the user's answer determine what to do if correct
start_time = time.time()
user_answer = input('\nEnter your answer: ')
end_time = time.time()
if user_answer == str(answer):
response_time = end_time - start_time
print('You are correct!')
elif user_answer != str(answer):
print('Oops, you are incorrect.')
# Return game id, start time, and response time
return("calculation", start_time, response_time)
def calculation_game():
record = []
# Generate two problems for a practice round
print("\nLet's begin with 2 practice problems.")
for i in range (practice_round):
print('\nPractice Problem', i + 1, 'of', practice_round)
calculation()
# Generate 10 problems for a real, recorded round
print("\nNow let's try it for real this time.")
for i in range (real_round):
print('\nProblem', i + 1, 'of', real_round)
# Append records for each iteration
record.append(calculation())
main_record.extend(record)
CALC_RECORD.extend(record)
return record
# (5) Display Data -------------------------------------------------------------
def display_data():
plt.ylabel('Time Per Question')
plt.xlabel('Round Played')
CALC_RECORD.sort(key=lambda record:record[1])
calc_time = [t[2] for t in CALC_RECORD if t[0] =='calculation' and t[2] != None]
alist=[i for i in range (len(calc_time))]
if len(calc_time) >0:
print (calc_time)
x = alist
y = calc_time
plt.scatter(x, y, c="bo")
plt.show(block=True)
main_menu()
# (6) Save Progress ------------------------------------------------------------
# (7) Load Data ----------------------------------------------------------------
# (8) Quit Game ----------------------------------------------------------------
def quit_game():
print('\nThank you for playing!')
# Main Menu --------------------------------------------------------------------
def menu():
print("\nEnter 1 to play 'Calculation'")
print("Enter 2 to play 'Binary Reader'")
print("Enter 3 to play 'Trifacto'")
print("Enter 4 to view your statistics")
print("Enter 5 to display data")
print("Enter 6 to save your progress")
print("Enter 7 to load data")
print("Enter 8 to quit the game")
def main_menu():
print('Welcome!')
user_input = ''
while user_input != '8':
menu()
user_input = input('\nWhat would you like to do? ')
if user_input == '1':
calculation_game()
if user_input == '2':
binary_reader_game()
if user_input == '3':
trifacto_game()
if user_input == '4':
display_statistics()
if user_input == '5':
display_data()
if user_input == '8':
quit_game()
main_menu()
Got it, just had to remove the c= part from plt.scatter(x, y, c="bo")
i've got the code working but I've written my code in python implementing a stack, it is pushing and popping following LIFO but when you view the list it prints it as:
1
2
3
showing the last item which is 3 at the bottom, how can I make it show the last item at the top like a proper stack?
my code is as follows:
stack_pointer = 0
stack =[]
max_length = 2
def view():
for x in range (len(stack)):
print(stack[x])
def push():
global stack_pointer
if len (stack)> max_length:
print("Maximum stack length reached!")
else:
stack_pointer = stack_pointer + 1
item = input("Please enter the item you wishto add to the stack: ")
stack.append(item)
def pop():
global stack_pointer
if len (stack)<= 0:
print ("stack is empty!")
else:
item = stack.pop
stack_pointer = stack_pointer - 1
print ("you just popped out: ", item)
while True:
print ("")
print("Python implementation of a stack")
print("********************************")
print("1. view Stack")
print("2. Push onto Stack")
print("3. Pop out of Stack")
print("********************************")
print("")
menu_choice = int (input("Please enter your menu choice: "))
print ("")
print ("")
if menu_choice == 1:
view()
elif menu_choice == 2:
push()
elif menu_choice == 3:
pop()
Try something like this:
def view():
print(list(reversed(stack)))
to create reversed copy of your list and print it out.
This should work: a start of the stack's length - 1 , a stop of -1, and step of -1; no new lists are created or any extra operations, only a modification of the range object parameters, thus it's efficient:
def view():
for x in range (len(stack) - 1, -1, -1):
print(stack[x]) # or print(stack[x], end=' ')
I've created a code that allows a user to view the average score of the values that are in the file. In Example the Text File would look like the following:
Text File For Class 1: it is similar for each text file ; 2 and 3. just different names and values
Matt 2
Sid 4
Jhon 3
Harry 6
There are 3 classes altogether in which the user is prompted to choose which class they want to preview.
Code:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
one = "1.txt"
two = "2.txt"
three = "3.txt"
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
Question
If i wanted to Keep Repeating the code above so that the user can keep using it until they want to exit. so, is it possible to put the code into a while loop and only stop the code if the user wants to, i.e the user is prompted if they want to choose another option and class.
NB: there will be other options such as alphabetical order however right now i only want to know how to do it for the average section.
Best thing you can do is to make a loop for user input and write a function for listing the file.
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
main_menu()
option = ""
options = ["1", "2", "3"]
one = "1.txt"
two = "2.txt"
three = "3.txt"
def read_text_file(file): # standalone function for viewing files to reduce duplicate code
file += ".txt"
with open(file) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
while True:
option = input("option [avg]: ").lower()
if option == "exit":
break # checks if user want to exit a program
else:
option_class = input("class: ")
if option == 'avg' and option_class in options:
read_text_file(option_class)
else:
print("nothing to show, asking again")
print("end of program")
As I mentioned in the comment section, you should leverage the power of functions here. By breaking down your components to manageable pieces, you actually afford yourself readability and flexibility. See code below, where I have two functions, one for averages and one for totals.
def get_class_average(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
return avg
except:
print "No file with that name found."
def get_class_total(class_number):
filename = "{0}.txt".format(class_number)
try:
with open(filename) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
return b
except:
print "No file with that name found."
def check_class_number(string_input):
try:
int(string_input)
return True
except ValueError:
return False
if __name__ == "__main__":
while True:
input_val = raw_input(
"Enter class number (enter 'exit' to quit program): ")
if input_val == 'exit':
break
if check_class_number(input_val): # If it's a valid class number.
method = raw_input("Enter method: ")
if method == 'avg':
avg = get_class_average(int(input_val))
print "The average of Class {0} is {1}".format(input_val, avg)
elif method == 'sum':
total = get_class_total(int(input_val))
print "The total of Class {0} is {1}".format(input_val, total)
else:
print "That is not a valid class number."
continue
Sample run:
The really fun part here is that you can even refactor get_class_average and get_class_total to be a single function that checks if the passed in method is avg or sum and returns the respective values from there (this is easily doable since you have practically the same lines of code for both functions, get_class_average just has an extra division involved).
Have fun.
Yes, you can just put your code within a while-loop and prompt the user for input:
def main_menu():
print ("\n Main Menu ")
print ("1.Average Score of class = 'avg'")
# End main_menu()
one = "1.txt"
two = "2.txt"
three = "3.txt"
keepGoing = True
while(keepGoing):
main_menu()
option = input("option [avg]: ")
option_class = input("class: ")
if option.lower() == 'avg' and option_class == '1':
with open(one) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '2':
with open(two) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
if option.lower() == 'avg' and option_class == '3':
with open(three) as f:
the_list = [int(l.strip().split()[-1]) for l in f]
b = sum(the_list)
length = len(the_list)
avg = float(b) / length if length else 0
print ("Average of Class is: ", avg)
# Prompt user for input on whether they want to continue or not:
while(True):
keepGoingStr = input("Would you like to continue? (Y/N)\n>>> ").lower()
if(keepGoingStr[0] == 'y'):
# Keep going
keepGoing = True
break
elif(keepGoingStr[0] == 'n')
# Stop
keepGoing = False
break
else:
print("Sorry, your input did not make sense.\nPlease enter either Y or N for yes or no.")
# end if
# end while - keep going input
# End While(keepGoing)
As mentioned in the comments, though, you should consider breaking up your code into functions.