Compute bill for a gem store - python

Below is my code to compute the bill for the gem store. I'm able to get correct prices for the right elements from the list but I'm not able to figure out how to multiply them with the required quantity (reqd_qty list) and calculate the total price.
Following is the complete problem description.
Tanishq Gems Store sells different varieties of gems to its customers.
Write a Python program to calculate the bill amount to be paid by a customer based on the list of gems and quantity purchased. If any gem required by the customer is not available in the store, then consider the total bill amount to be -1.
Assume that quantity required by the customer for any gem will always be greater than 0
def calculate_bill_amount(gems_list, price_list, reqd_gems,reqd_quantity):
bill_amount=0
#Write your logic here
for gem in gems_list:
for g in reqd_gems:
if g==gem:
index = gems_list.index(g)
price = price_list[index]
print(price)
return bill_amount
#List of gems available in the store
gems_list=["Emerald","Ivory","Jasper","Ruby","Garnet"]
#Price of gems available in the store. gems_list and price_list have one-to-
one correspondence
price_list=[1760,2119,1599,3920,3999]
#List of gems required by the customer
reqd_gems=["Ivory","Emerald","Garnet"]
#Quantity of gems required by the customer. reqd_gems and reqd_quantity have
one-to-one correspondence
reqd_quantity=[3,2,5]
bill_amount=calculate_bill_amount(gems_list, price_list, reqd_gems,
reqd_quantity)
print(bill_amount)
Current Output:
1760 # Ivory Price
2119 # Emerald Price
3999 # Garnet Price
0 # Bill amount

I suggest you read up on dictionaries, looping over lists to match a value in another list is very inefficient. https://docs.python.org/3/tutorial/datastructures.html#dictionaries
gems_list = ["Emerald", "Ivory", "Jasper", "Ruby", "Garnet"]
price_list = [1760, 2119, 1599, 3920, 3999]
reqd_gems = ["Ivory", "Emerald", "Garnet"]
reqd_quantity = [3, 2, 5]
quantity_dict = dict(zip(reqd_gems, reqd_quantity))
price_dict = dict(zip(gems_list, price_list))
print("Item", "Quantity", "Unit_price", "Total_price")
for k, v in quantity_dict.items():
print(k, v, price_dict[k], price_dict[k] * v)
print("Grand_total", sum([price_dict[k] * v for k, v in quantity_dict.items()]))

There are two main flaws with the logic of your program.
The first being is that you never update bill_amount, that is why your answer is being returned a 0.
Secondly, the price is not being multiplied by the required quantity.
Here is calculate_bill_amount() reworked:
def calculate_bill_amount(gems_list, price_list, reqd_gems,reqd_quantity):
bill_amount=0
#Write your logic here
x=0
for g in reqd_gems:
for gem in gems_list:
if g==gem:
index = gems_list.index(g)
price = price_list[index]
bill_amount += price * reqd_quantity[x]
print(bill_amount, price, reqd_quantity[x], x)
x+=1
return(bill_amount)
#Bill .M was also right in pointing out that you didn't account for the condition where the gem was not in the list

As was pointed out in an answer to you before you deleted this same question earlier: bill_amount should just be the sum of all of the prices you calculate along the way, so after your print(price) command, try adding bill_amount += price. This sets the value of bill_amount to its current value plus the new value of price. Though you're still not multiplying this price by its quantity.
Also, your code doesn't address the case of a gem not being in the availability list. So one way around this is to skip the calculation and return -1 if g is not in gems_list. You can use the command "if g not in gems_list:".
def calculate_bill_amount2(gems_list, price_list, reqd_gems,reqd_quantity):
bill_amount=0
#Write your logic here
for gem in gems_list:
for g in reqd_gems:
if g==gem:
index = gems_list.index(g)
no_of_gems = reqd_quantity[reqd_gems.index(g)]
price = price_list[index] * no_of_gems
print(price)
bill_amount += price
if g not in gems_list:
return -1
return bill_amount
Frankly, I'd just use dictionaries instead of lists, because you're doing a lot of unnecessary looping:
def calculate_bill_amount(gem_prices, reqd_gem_quantities):
bill_amount = 0
for gem in reqd_gem_quantities:
if gem in gem_prices:
price = gem_prices[gem] * reqd_gem_quantities[gem]
bill_amount += price
else:
return -1
return bill_amount
gem_prices = { "Emerald": 1760, "Ivory": 2119, "Jasper": 1599, "Ruby": 3920, "Garnet": 3999 }
reqd_gem_quantities = { "Ivory": 3, "Emerald": 2, "Garnet": 5 }
print(calculate_bill_amount(gem_prices, reqd_gem_quantities))

def calculate_bill_amount(gems_list, price_list, reqd_gems,reqd_quantity):
bill_amount=0
#Write your logic here
j=0
for i in reqd_gems:
if i in gems_list:
index=gems_list.index(i)
bill_amount=bill_amount+reqd_quantity[j]*price_list[index]
j=j+1
else:
bill_amount=-1
break
if(bill_amount>30000):
bill_amount=bill_amount-(bill_amount*5/100)
return bill_amount

def calculate_bill_amount(gems_list, price_list, reqd_gems,reqd_quantity):
bill_amount=0
dict1={}
dict2={}
k=0
for i in reqd_gems:
dict2[i]=reqd_quantity[k]
k+=1
k=0
for i in gems_list:
dict1[i]=price_list[k]
k+=1
for i in dict2.keys():
gem=i
if gem in dict1.keys():
bill_amount+=dict1[gem]*dict2[gem]
else:
bill_amount=-1
break
if bill_amount>30000:
bill_amount=bill_amount-(bill_amount*5/100)
return bill_amount
*The above code works fine.. here i created two dictionary and mapped the correspondence..but i'm also new to programming so i don't know whether it is efficient or not *

Related

How do i make this repetitive code into a function?

how do i change this into a function?
if sell in ["Dividends","dividends"]:
for x in range(1,13):
TotalD=TotalD+int(dividends[x])
MeanD=TotalD/12
for yr,div in zip(year,dividends):
D=MeanD*1.2
D=str(D)
if div>D:
print(f"In Year {yr} the income in Dividends is (S$){div}.")
elif sell in ["Interests","interests"]:
for x in range(1,13):
TotalI=TotalI+int(interests[x])
MeanI=TotalI/12
I=MeanI*1.20
for yr,ints in zip(year,interests):
I=str(I)
if ints>I:
print(f"In Year {yr} the income in Interests is (S$){ints}.")
elif sell in ["Others","others"]:
for x in range(1,13):
TotalO=TotalO+int(othertypes[x])
MeanO=TotalO/12
for yr,ot in zip(year,othertypes):
O=MeanO*1.2
O=str(O)
if ot>O:
print(f"In Year {yr} the income in Other Types is (S$){ot}.")
I would do it this way:
lists = {"dividents": dividents, "interests": interests, "others": othertypes}
totals = {"dividents": TotalD, "interests": TotalI, "others": TotalO}
def total_and_mean(total, lst):
for x in range(1, 13):
total += int(lst[x])
return total, total / 12
def comparing(year, lst, mean, typ):
typ = typ.capitalize()
for yr, div in zip(year, lst):
D = mean * 1.2
D = str(D)
if div > "0":
print(f"In Year {yr} the income in {typ} is (S$){div}.")
def main_function(s):
s = s.lower()
this_list = lists[s]
this_total = totals[s]
total, mean = total_and_mean(this_total, this_list)
comparing(year, this_list, mean, s)
Create a dictionary with possible answers as keys and their lists as values. Do the same for totals.
Create a function which receives an answer. Make the answer lower letters.
Save list which is important for this answer into a variable. Do the same for total.
Create a function for total and mean calculations. Pass the list and the total to it.
5 . Create a function for comparing. Pass year, list, mean and answer to it.
Hint:
def function(names, types):
if sell in names:
for x in range(1,13):
Total=Total+int(types[x])
Mean=Total/12
for yr,div in zip(year, types):
M=Mean*1.2
M=str(M)
if div>M:
print(f"In Year {yr} the income in " + names[0] + "is (S$){div}.")
return True
return False

How to find which products have the best value in Python

I am currently creating a code/application that will help shoppers determine which products to purchase, by calculating the best value. The best value of a product is calculated by finding the $/g, which is found by dividing the cost of the product by the mass of the product.
My problem is, that if there are multiple products that have the same best value, then it will only show one of the products that have the best value. Is there a way so that it will display ALL of the products with the best value? Thank you kindly in advance.
Here's my code so far:
def best_cost():
while True:
num_of_products = int(input('How many products are there? '))
if num_of_products < 1:
print(f'Enter valid number for number of products')
else:
print(f'Finding best value out of {num_of_products} products')
all_prices = []
for i in range(1, num_of_products+1):
cost = float(input(f'Enter cost of product {i} $'))
mass = float(input(f'Enter mass of product {i} in grams:'))
print(f'Product {i} at ${cost / mass} per gram')
price = cost/mass
all_prices.append(price)
for prod in all_prices:
if prod == min(all_prices):
best_prod = all_prices.index(prod)+1
return print(f'Best product is Product {best_prod}')
best_cost()
The reason is because you return from the print statement, so you only ever get one item. You can instead build a list and return a list of items. You should also use something like math.isclose for comparing floating point values. Otherwise you can get some hard to track down errors.
You will also want to track the last index that you found a value for so you can find the next available item in the list.
from math import isclose
def best_cost():
while True:
num_of_products = int(input('How many products are there? '))
if num_of_products < 1:
print(f'Enter valid number for number of products')
else:
print(f'Finding best value out of {num_of_products} products')
all_prices = []
for i in range(1, num_of_products+1):
cost = float(input(f'Enter cost of product {i} $'))
mass = float(input(f'Enter mass of product {i} in grams:'))
print(f'Product {i} at ${cost / mass} per gram')
price = cost/mass
all_prices.append(price)
min_price = min(all_prices) # You only need to do the min check once
best_prods = [] # Create a list to store the results in
for i, prod in enumerate(all_prices, 1):
if isclose(prod, min_price):
best_prods.append(i)
print(f'Best product(s) are: {best_prods}')
best_cost()
Your code works, but when you return the whole operation stops.
If you are not using the return value, you can not return and it will print all the new products
best_prod = all_prices.index(prod)+1
print(f'Best product is Product {best_prod}')
or if you want to return a list of all the best products, keep track of them with a list:
best_products = []
...
for prod in all_prices:
if prod == min(all_prices):
best_prod = all_prices.index(prod)+1
best_products.append(best_prod)
print(f'Best product is Product {best_prod}')
return best_products

Iteration of two list in loop with if else statement (python)

I have two list(oil_price and price, both the same length) and want it to iterate through both loops and go through the if-else statements. The code only goes does the first row. Can anyone help?
for x in oil_price:
for y in price:
if float(x) <= 60:
cost = y * qty
if cost > funds:
return funds, stocks
else:
cash_balance = float(funds - cost)
stocks += qty
return cash_balance, stocks
elif float(x) > 60:
sale = qty * y
if qty > stocks:
return funds, stocks
else:
cash_balance = float(funds + sale)
stocks_owned = stocks - qty
return cash_balance, stocks_owned
To add to Błotosmętek's answer (use of a return statement exits the function after the first iteration of the loop) , you could use a list of lists (2D-list/array, if you will) to store the intermediate results, then use continue to go to the next step of the loop. This way, you calculate the results for all combinations of oil_price and price.
So, it could look something like this:
results = []
for x in oil_price:
for y in price:
if float(x) <= 60:
cost = y * qty
if cost > funds:
results.append([funds, stocks])
continue
else:
cash_balance = float(funds - cost)
stocks += qty
results.append([cash_balance, stocks])
continue
elif float(x) > 60:
sale = qty * y
if qty > stocks:
results.append([funds, stocks])
continue
else:
cash_balance = float(funds + sale)
stocks_owned = stocks - qty
results.append([cash_balance, stocks_owned])
continue
I'm sure this could look a lot prettier, but it should work nonetheless.

Product Process Order

I want to make a simple process order like :
You filled an order for 1 antacid for a total of $5.33
You filled an order for 3 sour bites for a total of $6.99
My code is:
total = 0
def process_order(x_list):
for x in len(x_list):
print(f"You filled an order for{x[1]} {x[0]} for a total of {x[1]* x[2]}")
x = [("oranges", 4, 3.22),("gummy bears",1,1.99),("sour bites", 3, 2.33), ("antacid", 1, 5.33)]
while(len(x)>0):
process_order(x)
print("Total price: ${:.2f}".format(total))
But I got error
TypeError: 'int' object is not iterable
As far as I understood, this seems like the code you want:
total = 0
def process_order(x_list):
global total
for x in x_list:
print(f"You filled an order for {x[1]} {x[0]} for a total of {x[1]* x[2]}")
total = total + x[1] * x[2]
return
x = [("oranges", 4, 3.22),("gummy bears",1,1.99),("sour bites", 3, 2.33), ("antacid", 1, 5.33)]
process_order(x)
print("Total price: ${:.2f}".format(total))
Output:
You filled an order for 4 oranges for a total of 12.88
You filled an order for 1 gummy bears for a total of 1.99
You filled an order for 3 sour bites for a total of 6.99
You filled an order for 1 antacid for a total of 5.33
Total price: $27.19
You need to define total as a global variable to get a overall total of the prices. Also, you can iterate through the list in python, as for list_element in list. If you want to make a function, it needs return statement at the end. In this case, what you have to do is to add each prices to global variable, and print out the process for each items, there's no need to return something.
You code is can be simplified with the same concepts minus the use of a defined function. First thing to address, is your while len(x) > 0 needs something to decrease the len(x) to end the loop. For this we can use .pop(). This will remove the item at index , we will use 0, and assign that to a variable z. From here we can use your print statement unchanged, I used other formatting for preference. And then we can add the total of each person to our running total.
x = [("oranges", 4, 3.22),("gummy bears",1,1.99),("sour bites", 3, 2.33), ("antacid", 1, 5.33)]
total = 0
while len(x) > 0:
z = x.pop(0)
print('You filled and order for {} {} for a total of {}'.format(z[1], z[0], z[1] * z[2]))
total += z[1] * z[2]
print("Total price: {:.2f}".format(total))
You filled and order for 4 oranges for a total of 12.88
You filled and order for 1 gummy bears for a total of 1.99
You filled and order for 3 sour bites for a total of 6.99
You filled and order for 1 antacid for a total of 5.33
Total price: 27.19
Function name process_order gives an idea, that only one order has been processed. so it's not a good idea to process many orders there at once. Moreso, if you return an order total from this function, you can sum over it afterwards to have total: total = sum(map(process_order, orders)). This will save you a lot of time to improve your functions while line with counting total still be the same.
The sample code below:
def process_order(order):
"""Process an order.
Order is a tuple and contains 3 fields: name, quantity and price.
"""
name, quantity, price = order
total_price = price * quantity
print(f"You filled an order for {]} {} for a total of {.2f}".format(
quantity, name, total_price))
return total_price
orders = [
("oranges", 4, 3.22), ("gummy bears", 1, 1.99),
("sour bites", 3, 2.33), ("antacid", 1, 5.33)]
total = sum(map(process_order, orders)) # can be rewritten with for loop
print("Total price: ${:.2f}".format(total))

Python - Retrieving an element from a tuple from a list

I am a beginner in Python and am struggling on retrieving an element out of a tuple from a list. What I am trying to do is to get the value of a fruit and multiply it by the quantity needed. An example below will show you what I mean. I can not figure out how to get the second element in the tuple.
##Cost of [('apples', 2.0), ('pears', 3.0), ('limes', 4.0)] is 12.25
fruitPrices = {'apples':2.00, 'oranges': 1.50, 'pears': 1.75,'limes':0.75,
'strawberries':1.00}
def buyLotsOfFruit(orderList):
## orderList: List of (fruit, numPounds) tuples
## Returns cost of order
totalCost = 0.0
for fruit,price in fruitPrices.items():
if fruit not in fruitPrices:
print 'not here!'
else:
totalCost = totalCost +fruitPrices[fruitPrices.index(fruit)].key() * price
return totalCost
It is mostly in my else statement that I can not get it working. All help is greatly appreciated!
Why are you looping over the dictionary? Loop over your list instead, and add to totalCost accordingly.
for fruit, n in orderList:
if fruit in fruitPrices:
totalCost += fruitPrices[fruit] * n
else:
print fruit, 'not here!'
You can simplify all this and do something like
sum(fruitPrices.get(fruit, 0) * n for fruit, n in orderList)
Note that fruitPrices.get(fruit, 0) will return fruitPrices[fruit] if fruit is in fruitPrices and 0 otherwise.
fruitPrices = {'apples':2.00, 'oranges': 1.50, 'pears': 1.75,'limes':0.75,
'strawberries':1.00}
def buyLotsOfFruit(orderList):
## orderList: List of (fruit, numPounds) tuples
## Returns cost of order
totalCost = 0.0
for fruit,price in fruitPrices.items():
if fruit not in fruitPrices:
print 'not here!'
else:
#totalCost = totalCost +fruitPrices[fruitPrices.index(fruit)].key() * price
totalCost = totalCost +fruitPrices[fruit] * price
return totalCost
Could get this down to one line, but I dont think it will help. You are looping over the prices dictionary, but should be looping over the orderList, and then looking up the fruit in the dictionary.
def buyLotsOfFruit(orderList):
totalCost = 0.0
for fruit, quantity in orderList:
if fruit not in fruitPrices:
print 'not here!'
else:
totalCost = totalCost +fruitPrices[fruit]* quantiy
return totalCost
NOTE:
You can put this entire function into a one-liner like this:
buyLotsOfFruit = lambda ol: sum(fruitPrices[f] * p for f, p in ol if f in fruitPrices)
Or this other way:
def buyLotsOfFruit(orderList):
## orderList: List of (fruit, numPounds) tuples
## Returns cost of order
totalCost = 0.0
for fruit, pounds in orderList:
if fruit not in fruitPrices:
print 'not here!'
else:
totalCost += fruitPrices[fruit] * pounds
return totalCost
To retrieve a key from a dictionary all you need is this: dictionary[key]
and it returns the value

Categories

Resources