Why isnt the indexing in this python script working? - python

I'm writing this script for an assignment so I'd appriciate being talked through it rather than simply being handed an answer. Basically I'm trying to convert feet to meters, meters to feet, and provide a sum of the total converted distance in both at the end. Without the [] indexes, It was working perfectly. The new part I've only just added and am struggling with is the [] indexes, and to be honest I'm having a hell of a time groking how they work. Anyways heres the code:
MAX = 256
switch = ""
feet = [0.0] * MAX
meters = [0.0] * MAX
feetpermeter = 3.28084
metersperfoot = 0.3048
sum_meters = 0
sum_feet = 0
def main():
selector()
def selector():
while True:
print("Is your measurement in meters or feet?")
switch = input("Or would you like to quit?")
if (switch == "feet" or switch == "Feet"):
ftm()
elif (switch == "meters" or switch == "Meters"):
mtf()
elif (switch == "quit" or switch == "Quit"):
end()
else:
print("Sorry, that wasn't one of the options.")
print("Lets try that again")
def mtf():
try:
meters[sum_meters] = float(input("Enter the number of meters. "))
feet[sum_feet] = meters * feetpermeter
print("That is", feet, "feet.")
main()
except:
print("Sorry, I didn't quite get that, lets try again.")
mtf()
def ftm():
try:
feet[sum_feet] = float(input("Enter the number of feet. "))
meters[sum_meters] = feet * metersperfoot
print("That is", meters, "meters.")
main()
except:
print("Sorry, I didn't quite get that, lets try again.")
ftm()
def end():
while True:
switch2 = input("Are you sure you want to quit(y/n)?")
if (switch2 == "y" or switch2 == "Y"):
print("you converted a total of ", sum(feet), "feet")
print("And", sum(meters), "meters.")
print("Bye!")
exit()
elif (switch2 == "n" or switch2 == "N"):
print("Ok, let's try that again.")
main()
else:
print("Sorry, that wasn't one of the options.")
print("Lets try that again")
main()
I did try having sum_feet + 1 and sum_meters + 1 after each result but that hadnt worked either.

You are not using the indexing in a proper way. For instance , look at the comments on your existing code:
def mtf():
try:
# Error 1. You stored all the inputs to index 0, as sum_meters is 0 always and its not incremented
# So, all the inputs are not recorded, only last one gets in index 0
meters[sum_meters] = float(input("Enter the number of meters. "))
# Error 2: You multiplied the whole list against the conversion parameter.
# Instead, you should multiply the value at current index
feet[sum_feet] = meters * feetpermeter
# This will print the whole list. Again use the current index here
print("That is", feet, "feet.")
main()
except:
print("Sorry, I didn't quite get that, lets try again.")
mtf()
A fixed version of your function will be like:
def mtf():
try:
# For modifying global variables in a function scope
global sum_meters
global sum_feet
meters[sum_meters] = float(input("Enter the number of meters. "))
feet[sum_feet] = meters[sum_meters] * feetpermeter
print(f"That is {feet[sum_feet]} feet.")
sum_meters += 1
sum_feet += 1
main()
except:
print("Sorry, I didn't quite get that, lets try again.")
mtf()
This fixes stands true for your other functions as well.
I also thought to give you another piece of advice, that you can use a good object oriented approach for such problems, which makes it simpler to implement. You can learn a lot about that, then you will feel more confident.
As an example, see the below code - which does almost same, but in a more crisp way.
class Converter:
FEET_PER_METER = 3.28084
METERS_PER_FOOT = 0.3048
def __init__(self):
self.feet_store = []
self.meter_store = []
self.curr_index = 0
self.menu_handlers = {
"feet": self.feet_to_meter,
"meters": self.meter_to_feet,
"quit": self.summary
}
def run_selection(self, selected):
#
selected = str.lower(selected)
if selected in self.menu_handlers:
# call the relevant function
return self.menu_handlers.get(selected)()
return False
def meter_to_feet(self):
meters_in = float(input("Enter the number of meters."))
to_feet = meters_in * self.FEET_PER_METER
self.meter_store.append(meters_in)
self.feet_store.append(to_feet)
print(f"In Feet : {to_feet}")
return to_feet
def feet_to_meter(self):
feet_in = float(input("Enter the number of feet."))
to_meters = feet_in * self.METERS_PER_FOOT
self.feet_store.append(feet_in)
self.meter_store.append(to_meters)
print(f"In Meters : {to_meters}")
return to_meters
def summary(self):
confirm = input("Are you sure you want to quit(y/n)?")
if confirm in ["y", "Y"]:
print("you converted a total of ", sum(self.feet_store), "feet")
print("And", sum(self.meter_store), "meters.")
print("Bye!")
exit()
else:
return False
def main():
converter = Converter()
while True:
choice = input("Is your measurement in meters or feet (meters/feet/quit)?")
converter.run_selection(choice)
I hope this gives you better insights.

So theres two problems with what you've tried to do here, in the lines:
meters[sum_meters] = float(input("Enter the number of meters. "))
feet[sum_feet] = meters * feetpermeter
meters * feetpermeter is multiplying an array by a number, you need to do meters[sum_meters] to get the number you want. Secondly as you said, you need to increment sum_meters each time, but because you're inside a function you will need to declare the variable as a global before you change it. Also since sum_meters and sum_feet are always going to be equal, you can just use a single variable to keep track of this:
def mtf():
try:
global index
meters[index] = float(input("Enter the number of meters. "))
feet[index] = meters[index] * feetpermeter
index += 1
print("That is", feet, "feet.")
main()
except:
print("Sorry, I didn't quite get that, lets try again.")
mtf()
def ftm():
try:
global index
feet[index] = float(input("Enter the number of feet. "))
meters[index] = feet * metersperfoot
index += 1
print("That is", meters, "meters.")
main()
except:
print("Sorry, I didn't quite get that, lets try again.")
ftm()
I would also go a little further and say that the use of lists is unnecessary for this problem, you could simply have two numbers, total_meters and total_feet and add the values as you go. This would take less memory and also remove the arbitrary limit of 256 goes that has been imposed. So I would do:
import sys
MAX = 256
switch = ""
total_feet = 0
total_meters = 0
feetpermeter = 3.28084
metersperfoot = 0.3048
sum_meters = 0
sum_feet = 0
index = 0
def main():
selector()
def selector():
while True:
print("Is your measurement in meters or feet?")
switch = input("Or would you like to quit?")
if switch == "feet" or switch == "Feet":
ftm()
elif switch == "meters" or switch == "Meters":
mtf()
elif switch == "quit" or switch == "Quit":
end()
sys.exit(0)
else:
print("Sorry, that wasn't one of the options.")
print("Lets try that again")
def mtf():
try:
global total_feet
global total_meters
meters = float(input("Enter the number of meters. "))
feet = meters * feetpermeter
total_meters += meters
total_feet += feet
print("That is", feet, "feet.")
main()
except Exception as e:
print(e)
print("Sorry, I didn't quite get that, lets try again.")
mtf()
def ftm():
try:
global total_feet
global total_meters
feet = float(input("Enter the number of feet. "))
meters = feet * metersperfoot
total_meters += meters
total_feet += feet
print("That is", meters, "meters.")
main()
except Exception as e:
print(e)
print("Sorry, I didn't quite get that, lets try again.")
ftm()
def end():
while True:
switch2 = input("Are you sure you want to quit(y/n)?")
if switch2 == "y" or switch2 == "Y":
print("you converted a total of ", total_feet, "feet")
print("And", total_meters, "meters.")
print("Bye!")
exit()
elif switch2 == "n" or switch2 == "N":
print("Ok, let's try that again.")
main()
else:
print("Sorry, that wasn't one of the options.")
print("Lets try that again")
main()

Related

Why isn't the int changing the str value to int in the try statement?

while True:
printing("Welcome to The Cheapest Dealer Ship\n", 0.025)
printing("What car would you like\n")
printing(
"""
(1) Standard $50
(2) SUV $60
(3) Minivan $80
""", 0.025)
ans = input(">>")
try:
int(ans)
except:
pass
if ans == 1:
Total += 50
Car = "Standard"
Car_cost = 50
break
elif ans == 2:
Total += 60
Car = "SUV"
Car_cost = 60
break
elif ans == 3:
Total += 80
Car = "Minivan"
Car_cost = 80
break
else:
printing("Please chose a valid option")
time.sleep(1)
replit.clear()
So basically this is a school code excersize but I can't quite figure why it will return with an else statement even if you answer 1,2 or 3. Not sure why int isn't working or what I'm doing wrong.
Either change your this line
int(ans)
To:-
ans = int(ans)
Or, you can directly take an integer as a input.
Change these lines of code
ans = input(">>")
try:
int(ans)
except:
pass
To this,
while True:
ans = (input(">>"))
if ans.isnumric():
while True:
if ans=="3" or ans=="2" or ans=="1"
break
else:
print("Please select any one (1\2\3)")
break
else:
print("Please enter only numbers.")
ans = int(ans)
After this you will have no need to use try and except statements and you will have less chances of getting errors.

Simplifying user-input foolproofing, Python

I have the following code to make sure that a user enters a float in python:
while True:
try:
some_variable = int(input("Input Prompt: "))
break
except ValueError:
print("Please enter a whole number (in digits)")
The code works fine, but I have a program that needs many of these, and I was wondering if there is a way to simplify it.
ie I wouldn't have to use:
while True:
try:
some_variable = int(input("Input Prompt: "))
break
except ValueError:
print("Please enter a whole number (in digits)")
For every user input. I'd really appreciate any help I can get.
Perhaps you can use https://github.com/asweigart/pyinputplus to specify what ranges or inputs are valid?
Ok, I did some research on Thierry Lathuille's suggestion. I used functions to simplify the code. Below is the simplified code for everyone's use:
def int_input(prompt):
while True:
try:
variable_name = int(input(prompt))
return variable_name
except ValueError:
print("Please enter a whole number (in digits)")
def float_input(prompt):
while True:
try:
variable_name = float(input(prompt))
return variable_name
except ValueError:
print("Please enter a number (in digits)")
def yes_input(prompt):
while True:
variable_name = input(prompt).lower()
if variable_name in ["y", "yes"]:
return "yes"
elif variable_name in ["n", "no"]:
return "no"
else:
print("""Please enter either "yes" or "no": """)
while True:
print("Volume of a right circular cone")
print("Insert the radius and height of the cone below:")
one_third = 1 / 3
radius = float_input("Radius: ")
height = float_input("Perpendicular Height: ")
pi_confirm = yes_input("""The value of π is 22/7, "yes" or "no": """)
if pi_confirm == "yes":
pi = 22/7
if pi_confirm == "no":
pi = float_input("Type the value of pi, for eg ➡ 3.141592653589: ")
volume = one_third * pi * radius ** 2 * height
accuracy = int_input("How many decimal places do you want your answer to?: ")
print(f"""{volume:.{accuracy}f}""")
new_question = yes_input("""New question? "yes" or "no": """)
if new_question == "no":
break
Again thanks for your help.
Also if anyone has any more suggestions for the code I'd really appreciate it if you leave a comment.

How can I get two variables to hold the amount of higher than and lower than guesses?

I am creating a game in which the computer selects a random number 1-10
Then the user guesses the number until they get it right.
The trouble I am having is that when the users enter the wrong answer the variables high or low should be updated, but it just continues looping until the user does enter the right answer. Which causes high and low to always be at 0.
Any ideas? I know there is probably something wrong with the way I am looping?
Any pushes in the right direction would be great!
# module to generate the random number
import random
def randomNum():
selection = random.randint(0,9)
return selection
# get the users choices
def userGuess():
correct = True
while correct:
try:
userPick = int(input('Please enter a guess 1-10: '))
if userPick < 1 or userPick >10:
raise ValueError
except ValueError:
print('Please only enter a valid number 1 - 10')
continue
return userPick
# define main so we can play the game
def main():
correctNum = randomNum()
guess = userGuess()
high = 0
low = 0
if guess != correctNum:
print('uhoh try again!')
guess=userGuess()
elif guess > correctNum:
print('That guess is too high!')
high = high + 1
elif guess < correctNum:
print('That guess is too low')
low = low + 1
else:
print('You win!')
# the outcome of the game:
print('Guesses too high:', high)
print('Guesses too low:',low)
print('Thank you for playing!')
main()
Try modifying your main function :
def main():
correctNum = randomNum()
guess = userGuess()
high = low = 0 # nifty way to assign the same integer to multiple variables
while guess != correctNum: # repeat until guess is correct
if guess > correctNum:
print('That guess is too high!')
high = high + 1
else:
print('That guess is too low')
low = low + 1
print('Try again!')
guess=userGuess()
print('You win!')
# the outcome of the game:
print('Guesses too high:', high)
print('Guesses too low:',low)
print('Thank you for playing!')
Also, be careful with random.randint(0,9) : this will give a number between 0-9 (including 0 and 9, but never 10)!
You want to be doing random.randint(1, 10)
# module to generate the random number
import random
def get1to10():
selection = random.randint(1,10)
return selection
# get the users choices
def userGuess():
correct = True
while correct:
try:
userPick = int(input('Please enter a guess 1-10: '))
if userPick < 1 or userPick >10:
raise ValueError
except ValueError:
print('Please only enter a valid number 1 - 10')
continue
return userPick
# define main so we can play the game
def main():
correctNum = get1to10()
guess = 0
high = 0
low = 0
# use a while loop to collect user input until their answer is right
while guess != correctNum:
guess = userGuess()
# use if statements to evaluate if it is < or >
if guess > correctNum:
print('This is too high!')
high = high + 1
continue
# use continue to keep going through the loop if these are true
elif guess < correctNum:
print('this is too low!')
low = low + 1
continue
else:
break
# the outcome of the game:
print('----------------------')
print('Guesses too high:', high)
print('Guesses too low:',low)
print('The correct answer was:', '*',correctNum,'*', sep = '' )
print('Thank you for playing!')
print('---------------------')
main()
I found this solution to work well for what I needed!
Thank you everyone who answered this post!
You can try using a dictionary:
guesses = {'Higher': [],
'Lower': [],
'Correct': False,
} # A Dictionary variable
def add_guess(number, correct_number):
if number > correct_number:
guesses['Higher'].append(number)
elif number < correct_number:
guesses['Lower'].append(number)
else:
guesses['Correct'] = True
return guesses
add_guess(number=5, correct_number=3) # Higher
add_guess(10, 3) # Higher
add_guess(2, 3) # Lower
# Correct is False, and higher has the numbers (10, 5) while lower has the numbers (2)
print(guesses)
add_guess(3, 3) # Correct should now be True
print(guesses)
This, of course, isn't the entire code but should point you in the right direction. There is a ton of resources on python dictionaries online.

How to get my random number guessing game to loop again upon user input and how to create an error trap?

So this is my random number guessing program I made. It asks the user to input two numbers as the bound, one high and one low, then the program will choose a number between those two. The user then has to try and guess the number chosen by the program. 1) How do I get it to ask the user if they would like to play again and upon inputting 'yes' the program starts over, and inputting 'no' the program ends? 2) How do I create an error trap that tells the user "Hey you didn't enter a number!" and ends the program?
def main(): # Main Module
print("Game Over.")
def introduction():
print("Let's play the 'COLD, COLD, HOT!' game.")
print("Here's how it works. You're going to choose two numbers: one small, one big. Once you do that, I'll choose a random number in between those two.")
print("The goal of this game is to guess the number I'm thinking of. If you guess right, then you're HOT ON THE MONEY. If you keep guessing wrong, than you're ICE COLD. Ready? Then let's play!")
small = int(input("Enter your smaller number: "))
large = int(input("Enter your bigger number: "))
print("\n")
return small, large
def game(answer):
c = int(input('Input the number of guesses you want: '))
counter = 1 # Set the value of the counter outside loop.
while counter <= c:
guess = int(input("Input your guess(number) and press the 'Enter' key: "))
if answer > guess:
print("Your guess is too small; you're ICE COLD!")
counter = counter + 1
elif answer < guess:
print("Your guess is too large; you're still ICE COLD!")
counter = counter + 1
elif answer == guess:
print("Your guess is just right; you're HOT ON THE MONEY!")
counter = c + 0.5
if (answer == guess) and (counter < c + 1):
print("You were burning hot this round!")
else:
print("Wow, you were frozen solid this time around.", "The number I \
was thinking of was: " , answer)
def Mystery_Number(a,b):
import random
Mystery_Number = random.randint(a,b) # Random integer from Python
return Mystery_Number # This function returns a random number
A,B = introduction()
number = Mystery_Number(A,B) # Calling Mystery_Number
game(number) # Number is the argument for the game function
main()
You'd first have to make game return something if they guess right:
def game(answer):
guess = int(input("Please put in your number, then press enter:\n"))
if answer > guess:
print("Too big")
return False
if answer < guess:
print("Too small")
return False
elif answer == guess:
print("Your guess is just right")
return True
Then, you'd update the 'main' function, so that it incorporates the new 'game' function:
def main():
c = int(input("How many guesses would you like?\n"))
for i in range(c):
answer = int(input("Your guess: "))
is_right = game(answer)
if is_right: break
if is_right: return True
else: return False
Then, you'd add a run_game function to run main more than once at a time:
def run_game():
introduction()
not_done = False
while not_done:
game()
again = input('If you would like to play again, please type any character')
not_done = bool(again)
Finally, for error catching, you'd do something like this:
try:
x = int(input())
except:
print('That was not a number')
import sys
sys.exit(0)

There's an issue somewhere in my Python code.. I can't find where it's at

I don't know what's wrong with it.. I run it and I'm able to input a number but then it stops working. It says, "TypeError: play_game() missing 1 required positional argument: 'limit.' But I'm not sure what's missing there??
#!/usr/bin/env python3
import random
def display_title():
print("Guess the number!")
print()
def get_limit():
limit = int(input("Enter the upper limit for the range of numbers: "))
return limit
def play_game(limit):
number = random.randint(1, limit)
print("I'm thinking of a number from 1 to " + str(limit) + "\n")
while True:
guess = int(input("Your guess: "))
if guess < number:
print("Too low.")
count += 1
elif guess >= number:
print("Too high.")
count += 1
elif guess == number:
print("You guessed it in " + str(count) + " tries.\n")
return
def main():
display_title()
again = "y"
while again.lower() == "y":
limit = get_limit()
play_game()
again = input("Play again? (y/n): ")
print()
print("Bye!")
# if started as the main module, call the main function
if __name__ == "__main__":
main()
You have defined your play_game function to take limit as a parameter, but when you call this function in your main loop, you don't supply a value in the brackets of play_game().
You could either try adding that limit value that you've specified by calling it like
play_game(25)
Or, based on your code, since you're asking the user to provide a limit, call it like:
play_game(limit)
Or, if you want to be able to call play_game() without setting a limit, then change your play_game definition line to something like:
def play_game(limit=25):
Which will set a default value of 25 whenever that function is called without supplying the limit value.
Yes, play_game() needs the parameter limit. I've done a quick check on your code, and there is some additional problem
the count variable isn't initialized
you calculate the random number in every step
guess > number should be used instead of guess >= number
Here is the fixed code, it works for me. I hope it will be usefull:
import random
count = 0
number = -1
def display_title():
print("Guess the number!")
print()
def get_limit():
limit = int(input("Enter the upper limit for the range of numbers: "))
return limit
def play_game(limit):
global number, count
if number == -1:
number = random.randint(1, limit)
print("I'm thinking of a number from 1 to " + str(limit) + "\n")
while True:
guess = int(input("Your guess: "))
if guess < number:
print("Too low.")
count += 1
elif guess > number:
print("Too high.")
count += 1
elif guess == number:
print("You guessed it in " + str(count) + " tries.\n")
return
display_title()
again = "y"
while again.lower() == "y":
limit = get_limit()
play_game(limit)
again = input("Play again? (y/n): ")
print()
print("Bye!")
In your main you are calling playgame() without providing a limit as an argument.
Your main should look something like
def main():
display_title()
again = "y"
while again.lower() == "y":
limit = get_limit()
play_game(10)
again = input("Play again? (y/n): ")
print()
print("Bye!")

Categories