Can't figure out a Python exercise with dictionaries - python

I have the following code:
shoppingList = ["banana","orange","apple"]
inventory = {"banana": 6,
"apple": 0,
"orange": 32,
"pear": 15
}
prices = {"banana": 4,
"apple": 2,
"orange": 1.5,
"pear": 3
}
def calculateBill(food):
total = 0
for k in food:
total += prices[k]
return total
calculateBill(shoppingList)
The exercise tells me to complete the function following these instructions:
Don't add the price of an article in your bill if it is not in your inventory.
After you buy an article, substract one from the inventory.
I don't know how to do it and I don't know if I have any other mistakes in my code.
If it isn't clear, the value in inventory is the stock of that item, and the value in "prices" is the price.

First of all, I don't see comida defined anywhere before its use. I'll assume that by comida, you mean food.
Here is a simple solution:
def calculateBill(food):
total = 0
for k in food:
if inventory.get(k, 0) > 0:
total += prices[k] # updates total
inventory[k] = inventory[k] - 1 # updates inventory
return total

You could do the following
def calculateBill(food):
total = 0
for k in food:
if k in inventory:
if inventory[k] > 0:
total += prices[k]
inventory[k] = inventory[k] - 1
else:
print 'There are no %s in stock' % k
else:
print 'dont stock %s' % k
return total
For 1)
if k in inventory:
Will check if the key is present in your inventory dict.
For 2)
inventory[k] = inventory[k] - 1
Will substract 1 from your inventory
One flaw in this code is that it does not check that the inventory count is above 0 before allowing to buy. So
if inventory[k] > 0:
Does this.

Here's a complete solution.
class Error(Exception):
"""Base class for Exceptions in this module"""
pass
class QtyError(Error):
"""Errors related to the quantity of food products ordered"""
pass
def calculateBill(food):
def buy_item(food_item, qty=1, inv_dict=None, prices_dict=None):
get_price = lambda item,price_dct: price_dct.get(item,9999999)
if inv_dict is None:
inv_dict = inventory
if prices_dict is None:
prices_dict = prices
if inv_dict.get(food_item, 0) >= qty:
inv_dict[food_item] -= qty
return sum(get_price(food_item, prices_dict) for _ in range(qty))
else:
raise QtyError("Cannot purchase item '{0}' of quantity {1}, inventory only contains {2} of '{0}'".format(food_item, qty, inv_dict.get(food_item,0)))
total = sum(buy_item(food_item, 1, inventory, prices) for food_item in food)
return total

Related

Settling Balance in Python

Just wanted to know let's say
Person 1: Paid 66USD
Person 2: Paid 0USD
Person 3: Paid 33USD
How do I program it in a way that it sends a table that tells person 2 has to pay 33USD TO person 1 to settle an equal balance amongst all members?
print('How many people in total')
people_num = int(input())
#Get the name list of everyone
name_list = []
for num in range(0,people_num):
print("What are their names?")
name_list.append(input())
print(name_list)
#get the amount everyone paid
amount = []
for name in name_list:
print("How much did " + name + " pay?")
amount.append(float(input()))
total_amount = sum(amount)
print(total_amount)
#create empty dictionary to calculate how much one person has to pay or receive
owe = []
for x in amount:
owe.append(round(x - (total_amount/people_num),2))
info = {}
for name, amt_owe in zip(name_list,owe):
info[name] = amt_owe
print(info)```
Here is a solution
def find_transactions(info):
for i in info.keys():
# find a negative balance : user A
if info[i] < 0:
for j in info.keys():
# find a positive balance : user B
if info[j] > 0 and i != j:
# user A will pay user B
x = abs(info[i])
if x > info[j]:
x = abs(info[j])
# change values of balances of user A and B
info[j] = info[j]-x
info[i] = info[i]+x
print(f"{i} pay {x} to {j}")
return info
Let's try with different values
people_num = 3
name_list = ["a", "b", "c"]
amount = [66, 0, 33]
in : info = {'a': 33.0, 'b': -33.0, 'c': 0.0}
out :
b pay 33.0 to a
info = {'a': 0.0, 'b': 0.0, 'c': 0.0}
amount = [66, 33, 33]
in : info = {'a': 22.0, 'b': -11.0, 'c': -11.0}
out :
b pay 11.0 to a
c pay 11.0 to a
info = {'a': 0.0, 'b': 0.0, 'c': 0.0}
The simple solution to this would be to count person's balance iterating through a list.
def process_transaction(from_user, to_user, amount):
if from_user['balance'] >= amount:
to_user['balance'] += amount
from_user['balance'] -= amount
print("Transaction success")
else:
print("Transaction failed")
bob = {"balance":100}
alice = {"balance":50}
process_transaction(bob, alice, 50)
print(bob)
print(alice)
does this help you ?
def info():
return {_name: _amount for _name, _amount in zip(name_list, amount)}
def equal_balances(_info):
# Make the transaction between sender and receiver
def transaction(payment_amount):
# print(f"balance before payment: {sender}: {round(_info[sender])}, {receiver}: {round(_info[receiver])}")
_info[receiver] += payment_amount
_info[sender] -= payment_amount
print(f"{sender} pay {round(payment_amount, 2)} to {receiver}")
# print(f"balance after payment: {sender}: {round(_info[sender])}, {receiver}: {round(_info[receiver])}")
medium_amount = total_amount / people_num # get medium amount
# get hwo pay hwo
print(f'The medium amount is: {round(medium_amount, 2)}')
for sender in _info:
if _info[sender] > medium_amount:
for receiver in _info:
if _info[sender] > medium_amount > _info[receiver]:
receiver_need = medium_amount - _info[receiver]
if _info[sender] - receiver_need < medium_amount:
transaction(_info[sender] - medium_amount)
elif _info[sender] >= receiver_need:
transaction(receiver_need)
elif _info[sender] - receiver_need == medium_amount:
transaction(_info[sender] - medium_amount)
return _info
people_num = int(input('How many people in total? '))
# Get the name list of everyone
name_list = []
for num in range(0, people_num):
name_list.append(input('What are their names? '))
print(name_list)
# get the amount everyone paid
amount = []
for name in name_list:
amount.append(float(input(f'How much did {name} pay? ')))
total_amount = sum(amount)
print(total_amount)
people_info = info()
print(people_info)
people_info = equal_balances(people_info)
print(people_info)

Get sum of goals scored by each team

I am analyzing a football games dataset and I want to answer a question - how many goals each team has scored and lost.
My dataset:
date home_team away_team home_score away_score
1873-03-08 England Scotland 0 1
1873-03-09 Scotland England 1 0
... ... ... ... ...
The function takes in 2 parameters - start year and end year
I've tried to have an empty list at a start, while iterating through the whole set add the name of the country and append the goals they've scored but since there are many different teams my list is not correct.
def total_goals(start, end):
x = 0
goals_scored = 0
goals_scored_list = []
goals_lost = 0
goals_lost_list = []
complete_list = []
for item in range(len(data['home_team'])):
date = int(data['date'][x][:4])
if date >= start:
if date <= end:
if int(data['home_score'][x]) > int(data['away_score'][x]):
goals_scored_list.append(data['home_team'])
goals_scored_list.append(data['home_score'])
x += 1
else:
x += 1
return goals_scored_list
My desired output would be a list which would contain a list for each unique team, that list would have country name, goals scored and goals lost:
[['England',1,1],['Scotland',0,2],[...]]
I assume I would need to create a list for each unique country, maybe using something like
if country not in data['home_team']:
goals_scored_list.append(data['home_team'][x]
But I believe there is a more sophisticated way to achieve my goal.
I believe this should work:
class Team:
def __init__(self,name):
self.name = name
self.wins = 0
self.losses = 0
def addEl(self,pos,score):
try:
score = int(score)
except Exception as e:
print e
if pos:
self.wins += score
else:
self.loss += score
def total_goals(start,end):
d = {}
for i in range(len(data)):
date = int(data['date'][i])
if date >= start and date <= end: #make sure it's in the params
pos = int(data['home_score'][i]) > int(data['away_score'][i]) #true if home wins, false otherwise
if data['home_team'][i] in d: #check if home_team already exists
d[data['home_team']].addEl(pos,data['home_score'][i]) #add score to wins/losses
else:
d[data['home_team'][i]] = Team(data['home_score'][i])
d[data['home_team'][i]].addEl(pos,data['home_score'][i])
if data['away_team'][i] in d:
d[data['away_team']].addEl(not(pos),data['away_score'][i])
else:
d[data['away_team'][i]] = Team(data['away_score'][i])
d[data['away_team'][i]].addEl(not(pos),data['away_score'][i])
return d
Using a custom class has the advantage of letting you add more characteristics like how many games were won/lost, additional statistics etc.etc.

updating a return value within a function

The issue i am having is getting the value of a returned item to update from different functions within a main function.
I have tried syntax to see if that changed anything, but I am not sure what needs to happen to get (in this case: the count and total).
I have also tried setting the functions = count, total but that returned an error.
def main():
terminate = False
print("Welcome to the self-checkout system at Wake-Mart.")
count, total = scan_prices()
print('')
disc = discount(count, total)
print('')
promo = promotion(count, total)
balance = total
def scan_prices():
total = 0
count = 0
prices = float(input("Enter the price of the first item:"))
while prices > 0:
count +=1
total = total + prices
print("Number of items:", count, "Total:", total)
prices = float(input("Eneter the price of the next item [or 0 to stop]:"))
while prices < 0:
print("Price cannot be negative.")
prices = float(input("Eneter the price of the next item [or 0 to stop]:"))
if prices > 0:
count +=1
total = total + prices
print("Number of items:", count, "Total:", total)
prices = float(input("Eneter the price of the next item [or 0 to stop]:"))
continue
return count, total
def discount(count, total):
if count >= 10:
print("You've got a 10% discount for buying 10 items or more.")
total = total * .9
print("Number of items:", count, "Total:", total)
return total
def promotion(count, total):
if total >= 50:
card = input(print("Do you want to buy a $50 gift card for $40 [y/n]:"))
if card == 'Y' or 'y':
print("Thank you for buying a giftcard.")
count +=1
total = (total * .9) + 40
print("Number if items:", count, "Total:", total)
else:
print("Thank for your purchases.")
print("Number if items:", count, "Total:", (total * .9))
return count, total
main()
I am just wanting the total and count to be updated as I move from one function execution to the next within the main function.
It looks like your main should take the return of one function and pass it to the next:
def main():
terminate = False
print("Welcome to the self-checkout system at Wake-Mart.")
count, total = scan_prices()
print('')
total = discount(count, total)
print('')
count, total = promotion(count, total)
balance = total

How to modify the value for a key in a dictionary?

So I'm trying to create a program that can take an order, retrieve it from stock and output the cost. When I do so I get a price of all the items chosen in stock. Any help?
import time
def compute_bill(component):
total = 0
for item in component:
total += prices[item_p]
return total
def localTime():
localtime = time.asctime(time.localtime(time.time()))
return localtime
stock = {
"I7": 2,
"Keyboard": 3,
"Mouse": 2,
"GPU": 4
}
prices = {
"I7": 250,
"Keyboard": 15,
"Mouse": 12,
"GPU": 350
}
item_p = ''
item_p = input("Please input the item you would like: ")
quantity = int(input("Please input the quantity you would like: "))
if item_p in stock:
print("X ordered a ", item_p,"at", localTime()," Which comes to a total of £", compute_bill(item_p))
else:
print("Error")
Example Output:
Please input the item you would like: Keyboard
X ordered a Keyboard at Fri Feb 9 17:16:09 2018 Which comes to a total of £ 120
I'd replace:
def compute_bill(component):
total = 0
for item in component:
total += prices[item_p]
return total
with:
def update_stock(component):
global stock
stock[component] -= quantity
def compute_bill(component):
update_stock(component)
return quantity * prices[component]
Your compute_bill function should be implemented simply like this:
def compute_bill():
return prices[item_p] * quantity

Why can't I print the result from within the function?

I'm working through the beginner's Python course in CodeAcademy. This is part of one of the exercises, where you're "checking out" at a grocery store, but I wanted to the code to print the final bill/"total" rather than just returning "total". I don't understand why it's not printing. I have tried putting it at the end, after the iteration, and, as here, within the recursion (before returning the total) to see if it'll print after each step. When I run this code, nothing displays.
shopping_list = ["banana", "orange", "apple"]
stock = {
"banana": 6,
"apple": 0,
"orange": 32,
"pear": 15
}
prices = {
"banana": 4,
"apple": 2,
"orange": 1.5,
"pear": 3
}
food = shopping_list
def compute_bill(food):
total = 0
for item in food:
if stock[item]>0:
total += prices[item]
stock[item] -=1
print total
return total
Edit:
These also aren't giving me a readout:
def compute_bill(food):
total = 0
for item in food:
if stock[item]>0:
total += prices[item]
stock[item] -=1
print "Total is $",total #tried 0-5 indentations, same blank result
Yet
def compute_bill(food):
total = 0
for item in food:
if stock[item]>0:
total += prices[item]
stock[item] -=1
print "Total is $",total #tried 0-5 indentations, same blank result
return total
print compute_bill(food)
Returns
Total is $ 5.5
5.5
While - I did find a solution...
def compute_bill(food):
total = 0
for item in food:
if stock[item]>0:
total += prices[item]
stock[item] -=1
return total
print "Total is $",compute_bill(food)
Returns
Total is $ 5.5
...but I'm confused as to why I can't just print the variable total, which should have been updated. And why it works there, but not as a feed in the function. This is just a question from an exercise, but I'm having trouble figuring out why it's doing this.
In your first example,
shopping_list = ["banana", "orange", "apple"]
stock = {
"banana": 6,
"apple": 0,
"orange": 32,
"pear": 15
}
prices = {
"banana": 4,
"apple": 2,
"orange": 1.5,
"pear": 3
}
food = shopping_list
def compute_bill(food):
total = 0
for item in food:
if stock[item]>0:
total += prices[item]
stock[item] -=1
print total
return total
You define a function def compute_bill. You never call that function. The function is executed iff it's called, e.g. compute_bill(["banana"])
I'm not sure I quite understood the problem, but you said
but I'm confused as to why I can't just print the variable total, which should have been updated.
If you try to print total from outside the function it will not work, since the total variable is only declared within the function. When you return total you allow the rest of your code to get the data from outside your function, which is why print computeBill(food) does work.
Edit, also if you want to print the total at each iteration, your code:
def compute_bill(food):
total = 0
for item in food:
if stock[item]>0:
total += prices[item]
stock[item] -=1
print "Total is $",total
Should definitely have this indentation, which means you'll print every time you iterate in the for loop (if you leave it as it was, it'll only print after the for).
The print statement is the part of your function compute_bill(..), it won't be executed until and unless you call the function compute_bill(..).
def compute_bill(food):
total = 0
for item in food:
if stock[item]>0:
total += prices[item]
stock[item] -=1
print "Total is $",total #this works
compute_bill(food) # call the function it has the print statement

Categories

Resources