SORRY FOR THE MESSY AND INEFFICIENT CODE
Let me start with the basic rules for the code. A bag is stored under a mattress and each bag can only contain coins. Individually they can only contain a single type of coin. So the pennies bag cannot contain dimes or any other coin, only pennies.
Ok so, the Issue I have here is that when I deposit money it doesn't matter what "Bag" I deposit into, the coins automatically go to the Dime bag and I can't find where in the code this is happening. From my viewpoint, the code makes sense(Which it would to me but not the computer). I really think I just need a second set of eyes looking at it. I'm also not a python programmer which doesn't really help
import os
class Bags:
def __init__(self, nOC, n, v):
self.name = n
self.numOfCoins = nOC
self.value = v
self.SetBal()
# Setters
def SetBal(self):
self.amount = self.numOfCoins * self.value
def SetCoin(self, coin):
self.numOfCoins += coin
self.SetBal()
# Getters
def GetBal(self):
return self.amount
class Mattress:
def __init__(self):
self.pBag = Bags(0, "Pennies", 0.01)
self.dBag = Bags(0, "Dimes", 0.05)
self.nBag = Bags(0, "Nickles", 0.10)
self.qBag = Bags(0, "Quarters", 0.25)
self.boBag = Bags(0, "Bug-Out-Bag", 0.00)
# Setters
# Getters
def GetBalances(self):
pen = self.pBag.GetBal()
print("Balance of pennies : $%.2f. %d pennies" % (pen, self.pBag.numOfCoins))
print("Balance of dimes : $%.2f. %d dimes" % (self.dBag.GetBal(), self.dBag.numOfCoins))
print("Balance of nickles : $%.2f" % self.nBag.GetBal())
print("Balance of quarters: $%.2f" % self.qBag.GetBal())
total = self.pBag.GetBal() + self.qBag.GetBal() + self.dBag.GetBal() + self.nBag.GetBal()
print("Total : $%.2f" % total)
def main ():
# Check laod or what not for what you have to do and all that good stuff
userMain = Mattress()
mainLoop = True
menu = '''What would you like to do?
D. Deposit Money
W. Withdraw Money
T. Transfer Funds
S. Show Balances
E. Exit'''
diffBags = '''
P. Pennies
D. Dimes
N. Nickles
Q. Quarters
C. Cancel'''
while(mainLoop):
print(menu)
action = input("Select an option: ")
if action == 'D' or action == 'd' :
depositMenu = "What bag would you like to deposit into? " + diffBags
depLoop = True
while(depLoop):
print(depositMenu)
depAction = input("Select an option: ")
depAmt = "How much would you like to deposit? "
if depAction == 'P' or action == 'p':
while True:
try:
depCoin = int(input(depAmt))
if depCoin < 1:
print("Invalid. Please enter a positive number")
continue
break
except ValueError:
print("Invalid. Please enter a positive number")
userMain.pBag.SetCoin(depCoin)
depLoop = False
elif depAction == 'D' or action == 'd':
while True:
try:
depCoin = int(input(depAmt))
if depCoin < 1:
print("Invalid. Please enter a positive number")
continue
break
except ValueError:
print("Invalid. Please enter a positive number")
userMain.dBag.SetCoin(depCoin)
depLoop = False
elif depAction == 'N' or action == 'n':
while True:
try:
depCoin = int(input(depAmt))
if depCoin < 1:
print("Invalid. Please enter a positive number")
continue
break
except ValueError:
print("Invalid. Please enter a positive number")
userMain.nBag.SetCoin(depCoin)
depLoop = False
elif depAction == 'Q' or action == 'q':
while True:
try:
depCoin = int(input(depAmt))
if depCoin < 1:
print("Invalid. Please enter a positive number")
continue
break
except ValueError:
print("Invalid. Please enter a positive number")
userMain.qBag.SetCoin(depCoin)
depLoop = False
elif depAction == 'C' or action == 'c':
depLoop = False
elif action == 'W' or action == 'w':
print ("working on it")
elif action == 'T' or action == 't':
print ("working on it")
elif action == 'S' or action == action == 's':
userMain.GetBalances()
elif action == 'E' or action == 'e':
print("Have a great day")
mainLoop = False
else:
print ("Incorrect value")
if __name__ == "__main__":
main()
I found your problem.
Let me explain to you how I found your problem, so next time you can find it.
I added a line to your code
print("Q")
userMain.qBag.SetCoin(depCoin)
Given what your program was trying to do I expected that to be printed when I tried to add quarters. But it was never printed, indicating that something had gone before that point.
Next I added another line:
depAction = input("Select an option: ")
print("GOT", depAction)
Then I ran the program again, and it printed.
Now I know the problem is somewhere between the two print statements. Given that the program ends up adding it to the dimes, it makes it look like somehow we ended up running the dimes-adding code even though I had entered q. I look at the code which checked for entry into the dimes section and saw the problem.
I see the problem, but the for sake of a didactic exercise I think you should find it yourself.
Related
I don't understand why I can't connect the processSale method to the sellProduct method. I think that the classes and other methods don't need any change because I only followed the criterias that were given to me.
#candy machine
class CashRegister:
def __init__(self, cashOnHand = 500,):
if cashOnHand < 0:
self.cashOnHand = 500
else:
self.cashOnHand = cashOnHand
def currentBalance(self):
return self.cashOnHand
def acceptAmount(self, cashIn):
self.cashOnHand += cashIn
class Dispenser:
def __init__(self, numberOfItems = 50, productCost = 50):
if numberOfItems < 0:
self.numberOfItems = 50
else:
self.numberOfItems = numberOfItems
if productCost < 0:
self.productCost = 50
else:
self.productCost = productCost
def getCount(self):
return self.numberOfItems
def getProductCost(self):
return self.productCost
def makeSale(self):
self.numberOfItems -= 1
class MainProgram:
def showMenu(self):
global userInput
print("**** Welcome to Eros' Candy Shop ****")
print("To select an item enter")
print("""1 for Candy
2 for Chips
3 for Gum
4 for Cookies
0 to View Balance
9 to Exit""")
userInput = int(input("Enter your choice: "))
def sellProduct(self, useDispenser = Dispenser(), useRegister = CashRegister()):
try:
self.useDispenser = useDispenser
self.useRegister = useRegister
if self.useDispenser.getCount != 0:
print(f"It costs {self.useDispenser.getProductCost} cents")
cash = int(input("Please enter your payment: "))
change = cash - self.useDispenser.getProductCost
if change < 0:
print("Insufficient money!")
print(f"You need {self.useDispenser.getProductCost - cash} cents more")
return
else:
print(f"Your change is {change} cents")
self.useRegister.acceptAmount(self.useDispenser.getProductCost)
self.useDispenser.makeSale
return
elif self.useDispenser.getCount == 0:
print("The product you chose is sold out! Try the other itmes")
return
except ValueError:
print("You entered an incorrect value. Please use the numbers on the menu only")
def processSale(self):
Register = CashRegister()
Candy = Dispenser()
Chips = Dispenser()
Gum = Dispenser()
Cookies = Dispenser()
while True:
self.showMenu
if userInput == 1:
self.sellProduct(Candy, Register)
elif userInput == 2:
self.sellProduct(Chips, Register)
elif userInput == 3:
self.sellProduct(Gum, Register)
elif userInput == 4:
self.sellProduct(Cookies, Register)
elif userInput == 0:
print("Current Balance is" + str(Register.currentBalance))
elif userInput == 9:
break
mainProgram = MainProgram()
mainProgram.showMenu()
How do i use sellProduct method on userInput 1-4. I get confused when applying the properties of a class and how to connect them. Can you point out what mistakes I made and what other improvements I can do.
here are some points you can improve :
When you call your methods do not forget the parenthesis :
self.useDispenser.getCount()
self.useDispenser.getProductCost()
Create an infinite loop to continuously ask for input within showMenu and delete the one within processSale (for example):
def showMenu(self):
global userInput
userInput = 0
print("**** Welcome to Eros' Candy Shop ****")
while userInput != 9:
print("To select an item enter")
print(MENU)
userInput = int(input("Enter your choice: "))
if userInput < 9:
self.processSale()
But please update the whole program accordingly.
Hope it helps !
I've been attempting to code this program for the past half a month or so but I'm stumped and I need to make substantial progress soon to meet my deadline, any help/advice would be appreciated. Apologies for the bad formatting, thanks for any help you can provide.
def main():
choice = printMenu()
print(choice)
def menu():
print("NRAS Eligibility Calculator")
print("[1] Display Household Income Limits")
print("[2] Calculate Total Income")
print("[3] Calculate Eligibility")
print("[4]: Exit")
def choice = int(input("Enter your choice: "))
while choice !=0:
elif choice== 1:
print("$52,324")
elif choice== 2:
def add_num(a,b):
sum=a+b;
return sum;
num1=int(input("income from source 1: "))
num2=int(input("income from source 2 :"))
print("Your total income is",add_num(num1,num2))
elif choice== 3:
def add_num(a,b):
sum=a+b;
return sum;
num1=int(input("income from source 1: "))
num2=int(input("income from source 2 :"))
if sum <= "52,324"
print("You're eligible for NRAS!")
else
print ("Sadly, you're not eligible.")
elif choice== 4:
quit()
else:
print("Invalid option.")
print("Thank you for using this calculator.")
I have corrected most of the mistakes and the code works fine. I have also added comments to highlight the changes I made.
But there a lot of questionable things that were going on in this code. I suggest you to look into python syntax properly.
def add_num(a,b):
sum = a+b
return sum
def menu():
print("NRAS Eligibility Calculator")
print("[1] Display Household Income Limits")
print("[2] Calculate Total Income")
print("[3] Calculate Eligibility")
print("[4] Exit")
ch = int(input('Enter your choice : ')) # added a variable to read the choice.
return ch # then return this choice when this function is called.
def choice(choice):
while choice != 0:
if choice== 1: # changed the elif to if.
print("$52,324")
break # added a break due to infinite loop
elif choice == 2:
num1=int(input("income from source 1: "))
num2=int(input("income from source 2 :"))
print("Your total income is",add_num(num1,num2))
elif choice == 3:
num1=int(input("income from source 1: "))
num2=int(input("income from source 2 :"))
SUM = add_num(num1, num2) # calling the add_num function here.
if SUM <= 52324: # changed this to int type instead of a string.
print("You're eligible for NRAS!")
else:
print ("Sadly, you're not eligible.")
elif choice == 4:
quit()
else:
print("Invalid option.")
print("Thank you for using this calculator.")
def main():
ch = menu()
choice(ch)
if __name__ == "__main__": # this is how you call a main() in python.
main()
I'm working on a simple program that allows the user to bet some virtual currency on a coin toss. Everything works fine, except for when the user inputs something incorrectly. For example: if a question asks for y/n response and the user puts 'd' or something as the response, the program will use the except ValueError and rerun the function. However, when the function is rerun and the user finally inputs something correctly, it will result in a further error.
Error:
> AttributeError: 'NoneType' object has no attribute 'lower'
Code:
import time
import random
money = 5000
last_interest_time = time.time()
def interest():
global money, last_interest_time
if time.time() - last_interest_time > 5:
prev_money = money
money *= 0.1
last_interest_time = time.time()
print("You now have " + str(money) + " monies (+" + str(money - prev_money) + ") from interest")
def game():
global money, last_interest_time
print("You have " + str(money) + " monies.")
choice = get_choice("Want to bet on a coin toss?", 'y','n')
if choice.lower() == 'y':
print("That's great!")
choice = get_choice("What side do you want to bet on?", 'h', 't')
bet_amount = get_bet()
print('Flipping the coin...')
time.sleep(1)
side = random.choice(['h', 't'])
if side == 'h':
print("The coin landed heads!")
elif side == 't':
print('The coin landed tails!')
if side == choice:
print("You won and received " + str(bet_amount) + " monies!")
money += bet_amount
else:
print("You lost the bet and " + str(bet_amount) + " monies!")
money -= bet_amount
game()
elif choice.lower() == 'n':
input('Oh well. Just type something if you want to bet again. ')
game()
def get_choice(question, response_1, response_2):
choice = input(question+" ("+response_1+'/'+response_2+'): ')
if choice != response_1 and choice != response_2:
print('Input is invalid. Must be '+response_1+'/'+response_2)
get_choice(question, response_1, response_2)
else:
return choice
def get_bet():
bet_amount = input("What amount do you want to bet?: ")
try:
if int(bet_amount) > money:
print("You don't have enough money!")
get_bet()
else:
return int(bet_amount)
except ValueError:
print('Invalid input. Must be a number')
get_bet()
game()
Debugging tip:
Print choice every time so you can see why it's crashing! You can take the print statement out later.
What I found was this:
get_choice() returned None.
In get_choice, if the input is invalid, it doesn't actually return anything. Oh no! So you're returning None, and calling .lower() on None throws the exception.
Solution:
You are on the right track when you run get_choice a second time if the input is invalid. One small tweak: instead of just running get_choice, return get_choice.
There is a similar bug in get_bet(), just a heads up, and you can solve it the same way.
Overall, great game.
.lower() runs on strings only and defining a variable with input() makes it not register as a string. Instead try something like this.
def set_choice():
choice = input("Want to bet on a coin toss?", 'y','n')
def choice():
choice = set_choice()
return choice
choice = choice.lower()
How should I get the below loop to replay if the user types in an invalid response after being asked if they want to roll the dice again?
I can't get it to work without messing with the while loop. Here's what I have so far
# Ask the player if they want to play again
another_attempt = input("Roll dice again [y|n]?")
while another_attempt == 'y':
roll_guess = int(input("Please enter your guess for the roll: "))
if roll_guess == dicescore :
print("Well done! You guessed it!")
correct += 1
rounds +=1
if correct >= 4:
elif roll_guess % 2 == 0:
print("No sorry, it's", dicescore, "not", roll_guess)
incorrect += 1
rounds +=1
else:
print("No sorry, it's ", dicescore, " not ", roll_guess, \
". The score is always even.", sep='')
incorrect += 1
rounds +=1
another_attempt = input('Roll dice again [y|n]? ')
if another_attempt == 'n':
print("""Game Summary""")
else:
print("Please enter either 'y' or 'n'.")
I would suggest you do it with two while loops, and use functions to make the code logic more clear.
def play_round():
# Roll dice
# Compute score
# Display dice
# Get roll guess
def another_attempt():
while True:
answer = input("Roll dice again [y|n]?")
if answer == 'y':
return answer
elif answer == 'n':
return answer
else:
print("Please enter either 'y' or 'n'.")
def play_game():
while another_attempt() == 'y':
play_round()
# Print game summary
I have written the Python code below (actually it's my solution for an exercise from page 80 of "Teach yourself Python in 24 hours").
The idea is: there are 4 seats around the table, the waiter knows for how much each seat ordered, enters those 4 amounts and gets a total.
If the raw_input provided is not a number (but a string) my code kicks the person out. The goal, however, is to give an error message ("this entry is not valid") and ask for the input again - until it's numeric. However, I can't figure out how to ask the user for the raw input again - because I am already inside a loop.
Thanks a lot for your advice!
def is_numeric(value):
try:
input = float(value)
except ValueError:
return False
else:
return True
total = 0
for seat in range(1,5):
print 'Note the amount for seat', seat, 'and'
myinput = raw_input("enter it here ['q' to quit]: ")
if myinput == 'q':
break
elif is_numeric(myinput):
floatinput = float(myinput)
total = total + floatinput
else:
print 'I\'m sorry, but {} isn\'t valid. Please try again'.format(myinput)
break
if myinput == 'q':
print "Goodbye!"
else:
total = round(total, 2)
print "*****\nTotal: ${}".format(total)
print "Goodbye!"
Generally, when you don't know how many times you want to run your loop the solution is a while loop.
for seat in range(1,5):
my_input = raw_input("Enter: ")
while not(my_input == 'q' or isnumeric(my_input)):
my_input = raw_imput("Please re-enter value")
if my_input == 'q':
break
else:
total += float(my_input)
As Patrick Haugh and SilentLupin suggested, a while loop is probably the best way. Another way is recursion- ie, calling the same function over and over until you get a valid input:
def is_numeric(value):
try:
input = float(value)
except ValueError:
return False
else:
return True
def is_q(value):
return value == 'q'
def is_valid(value, validators):
return any(validator(input) for validator in validators)
def get_valid_input(msg, validators):
value = raw_input(msg)
if not is_valid(value, validators):
print 'I\'m sorry, but {} isn\'t valid. Please try again'.format(value)
value = get_valid_input(msg, validators)
return value
total = 0
for seat in range(1,5):
print 'Note the amount for seat', seat, 'and'
myinput = get_valid_input("enter it here ['q' to quit]: ", [is_q, is_numeric])
if myinput == 'q':
break
elif is_numeric(myinput):
floatinput = float(myinput)
total = total + floatinput
if myinput == 'q':
print "Goodbye!"
else:
total = round(total, 2)
print "*****\nTotal: ${}".format(total)
print "Goodbye!"
In the above code, get_valid_input calls itself over and over again until one of the supplied validators produces something truthy.
total = 0
for seat in range(1,5):
incorrectInput = True
while(incorrectInput):
print 'Note the amount for seat', seat, 'and'
myinput = raw_input("enter it here ['q' to quit]: ")
if myinput == 'q':
print 'Goodbye'
quit()
elif is_numeric(myinput):
floatinput = float(myinput)
total = total + floatinput
incorrectInput = False
else:
print 'I\'m sorry, but {} isn\'t valid. Please try again'.format(myinput)
total = round(total, 2)
print "*****\nTotal: ${}".format(total)
print "Goodbye!"