Python: What could I do differently to slim down my Python code? - python

Could I code differently to slim down the point of this Python source code? The point of the program is too get the users total amount and add it too the shipping cost. The shipping cost is determined by both country (Canada or USA) and price of product:
The shipping of a product that is $125.00 in Canada is $12.00.
input ('Please press "Enter" to begin')
while True:
print('This will calculate shipping cost and your grand total.')
totalAmount = int(float(input('Enter your total amount: ').replace(',', '').replace('$', '')))
Country = str(input('Type "Canada" for Canada and "USA" for USA: '))
usa = "USA"
canada = "Canada"
lessFifty = totalAmount <= 50
fiftyHundred = totalAmount >= 50.01 and totalAmount <= 100
hundredFifty = totalAmount >= 100.01 and totalAmount <= 150
twoHundred = totalAmount
if Country == "USA":
if lessFifty:
print('Your shipping is: $6.00')
print('Your grand total is: $',totalAmount + 6)
elif fiftyHundred:
print('Your shipping is: $8.00')
print('Your grand total is: $',totalAmount + 8)
elif hundredFifty:
print('Your shipping is: $10.00')
print('Your grand total is: $',totalAmount + 10)
elif twoHundred:
print('Your shipping is free!')
print('Your grand total is: $',totalAmount)
if Country == "Canada":
if lessFifty:
print('Your shipping is: $8.00')
print('Your grand total is: $',totalAmount + 8)
elif fiftyHundred:
print('Your shipping is: $10.00')
print('Your grand total is: $',totalAmount + 10)
elif hundredFifty:
print('Your shipping is: $12.00')
print('Your grand total is: $',totalAmount + 12)
elif twoHundred:
print('Your shipping is free!')
print('Your grand total is: $',totalAmount)
endProgram = input ('Do you want to restart the program?')
if endProgram in ('no', 'No', 'NO', 'false', 'False', 'FALSE'):
break

Here is the core to simplify your code. It prints shipping cost for $100.00 in USA
totalAmount = 100
chargeCode = (int(100*(totalAmount+0.001))-1)/5000 #0 -- <=50, 1 -- 50.01-100, etc
if chargeCode > 3: chargeCode = 3
shipping = {}
shipping[("USA", 0)] = 6
shipping[("USA", 1)] = 8
shipping[("USA", 2)] = 10
shipping[("USA", 3)] = 0
shipping[("Canada", 0)] = 8
shipping[("Canada", 1)] = 10
shipping[("Canada", 2)] = 12
shipping[("Canada", 3)] = 0
print shipping[("USA", chargeCode)]
totalAmount+0.001 is used to avoid fun with float point numbers:
int(100*(81.85)) == 8184
returns True on my system because float point 81.85 is a bit less than decimal 81.85.

Here's a basic strategy for the cost calculation:
import math
amount = int(totalAmount)
assert amount >= 0
shipping = {
'USA': [6, 8, 10],
'Canada': [8, 10, 12]
}
try:
surcharge = shipping[country][amount and (math.ceil(amount / 50.0) - 1)]
except IndexError:
surcharge = 0
total = amount + surcharge
The key notion here is that the the shipping cost ranges follow a fairly linear progression: [0-50], (50-100], (100-150], (150, inf)
Note that the first group is a little funny, as it includes the lower bound of 0 where the other groups don't include the lower bound (they are an open interval at the bottom). So going forward we'll consider the first group as the following: 0 or (0-50]
We want to transform the amount the user supplies into an index into the shipping cost lists [6, 8, 10] and [8, 10, 12]. The lists are of length 3, so the indexes are 0, 1 and 2. Notice that if we divide any number in the range (0, 150] by 50.0 (we add the .0 to 50 so we a get a real number back -- 1 / 50 == 0 but 1 / 50.0 == 0.02 -- for the next step) we get a number in the range (0 and 3].
Now realize that math.ceil will round a real number to the nearest whole number that is greater than or equal to itself -- ex. math.ceil(.001) == 1.0, math.ceil(1.5) == 2.0, math.ceil(2) == 2.0. So applying math.ceil to numbers in the range (0, 3] we will supply either 1.0, 2.0 or 3.0. Cast those numbers to int (int(2.0) == 2) and we get the values 1, 2 and 3. Subtract 1 from those values and we get the 0, 1, 2. Voila! Those numbers match the indexes into our shipping array.
You can express this transformation with the Python: int(math.ceil(amount / 50.0) - 1)
We are almost there. We've handled any amount in the range (0, 150]. But what if amount is 0. math.ceil(0) == 0.0 and 0.0 - 1 == -1.0 This will not index properly into our array. So we handle 0 separately by checking first if amount is equal to 0, and if it is, using 0 as our shipping array index instead of the applying our transformation to amount to determine the index. This can be accomplished using Python's short circuit and operator (the web should have plenty of information on this) in the following expression: amount and int(math.ceil(amount / 50.0) - 1)
Note that any value above 150 will reduce to an index greater than 2 and applying that index against the shipping array will result in an IndexError. But any value greater than 150 has free shipping so we can catch the IndexError and apply a surcharge of 0:
try:
surcharge = shipping[country][amount and int(math.ceil(amount / 50.0) - 1)]
except IndexError:
surcharge = 0
And we're done!

Related

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))

How to turn money (in pence) to its individual coins?

My task was to
'Write a function selectCoins that asks the user to enter an amount of money
(in pence) and then outputs the number of coins of each denomination (from £2 down
to 1p) that should be used to make up that amount exactly (using the least possible
number of coins). For example, if the input is 292, then the function should report:
1 × £2, 0 × £1, 1 × 50p, 2 × 20p, 0 × 10p, 0 × 5p, 1 × 2p, 0 × 1p. (Hint: use integer
division and remainder).'
def selectCoins():
twopound = 200
onepound = 100
fiftyp = 50
twentyp = 20
tenp = 10
fivep = 5
twop = 2
onep = 1
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
g = 0
h = 0
money = int(input('Enter how much money you have in pence'))
while True:
if money >= twopound:
money = money - twopound
a = a + 1
elif money >= onepound:
money = money - onepound
b = b + 1
elif money >= fiftyp:
money = money - fiftyp
c = c + 1
elif money >= twentyp:
money = money - twentyp
d = d + 1
elif money >= tenp:
money = money - tenp
e = e + 1
elif money >= fivep:
money = money - fivep
f = f + 1
elif money >= twop:
money = money - twop
g = g + 1
elif money >= onep:
money = money - onep
h = h + 1
else:
money = 0
break
print(a,b,c,d,e,f,g,h)
I am new to programming so when I run this code it just inputs
'1 0 0 0 0 0 0 0' when I type 292 instead of what it should output.
Since you're new to coding, you should start writing the procedure you'd follow on paper, and then find out which tools you can use to automate this process.
Important
Read the full answer in order!
Don't fall for the temptation of reading the code right away.
The solutions I provide are hidden, but you can read them hovering your mouse over them or clicking on them (if you're using StackExchange mobile app, touch the "spoiler" link in each block).
The algorithm
What I'd do is:
Assume I have bins with coins, each bin labeled with the coin denomination.
The bins are sorted from the largest to the lowest denomination, and I always pick as much coins as I need from the highest denomination bin before moving to the next bin.
Write in a piece of paper the value for which I need to calculate the number of coins of each denomination I need.
Start with the first bin (the one holding the highest denomination).
Pick as many coins I need from that bin, in such a way that I don't "overshoot" the amount written on the piece of paper (notice that this number can be zero).
This can be done with an integer division; for example, if your value is 700 and the bin has denomination 200, you calculate the integer division 700 ÷ 200 = 3 (plus a remainder of 100)
Calculate the total amount of the coins I've picked.
Strike the value calculated in step 5 and write the remainder as a "new" value.
Since you've already calculated the integer division in step 4, you can calculate the remainder. You can also consider that there's a "Modulo" operator in most programming languages that will give you the remainder of an integer division right away. Using the above example, 700 mod 200 = 100, which reads "700 modulo 200 is 100", or "The remainder of the integer division 700 ÷ 200 is 100".
Move on to the next bin of coins.
Repeat from step 4 until I use all the bins or the value is zero.
Example
Suppose I start with a value of 292 and I have bins with the following denominations (already sorted from highest to lowest denominations):
| 200 | 100 | 50 | 20 | 10 | 5 | 2 | 1 |
+------+------+------+------+------+------+------+------+
| I | II | III | IV | V | VI | VII | VIII |
So, let's see what happens if I apply the algorithm above:
Write the value: 292
Start with the first bin (denomination: 200)
Pick 1 coin from the bin
The total amount picked from the bin is 200
The remainder is 92
Strike the previous value
The new value is 92
Move to the next bin (denomination: 100)
Pick 0 coins from the bin
The total amount picked from the bin is 0
The remainder is 92
Strike the previous value
The new value is 92
Move to the next bin (denomination: 50)
Pick 1 coin from the bin
The total amount picked from the bin is 50
The remainder is 42
Move to the next bin (denomination: 20)
Pick 2 coins from the bin
The total amount picked from the bin is 20
The remainder is 2
Move to the next bin (denomination: 10)
Pick 0 coins from the bin
The total amount picked from the bin is 0
The remainder is 2
Move to the next bin (denomination: 10)
Pick 0 coin from the bin
The total amount picked from the bin is 0
The remainder is 2
Move to the next bin (denomination: 5)
Pick 0 coin from the bin
The total amount picked from the bin is 0
The remainder is 2
Move to the next bin (denomination: 2)
Pick 1 coin from the bin
The total amount picked from the bin is 2
The remainder is 0
Done
Implementing this in Python
Python is an amazingly clear language, and makes this sort of tasks easy. So let's try to translate our algorithm to Python.
The toolbox
Assuming you're using Python 3.x, you'll need to know some operators:
The integer division operator (//): If you divide with just a single slash, you'll get the "real division" (e.g. 3 / 2 == 1.5), but if you use a double slash, you'll get the "integer division (e.g. 3 // 2 = 1)
The modulo operator (%): As explained above, this operator returns the remainder of a division (e.g. 7 % 4 == 3)
Used together, these operators will give you what you need on each step:
292 // 200 == 2
292 % 200 == 92
92 // 100 == 0
92 % 100 == 92
...
One useful characteristic of Python is that you can perform a "multiple assignment": You can assign multiple values to multiple variables in one single step:
# Initialize the value:
value = 292
# Initialize the denomination:
denomination = 200
# Calculate the amount of coins needed for the specified denomination
# and get the remainder (overwriting the value), in one single step:
coins, value = value // denomination, value % denomination
# ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
# | The remainder
# The number of coins
# (using integer division)
With this knowledge, we can write the solution:
Correcting your code
Remember: Read all of the above before revealing the solutions below.
def selectCoins():
twopound = 200
onepound = 100
fiftyp = 50
twentyp = 20
tenp = 10
fivep = 5
twop = 2
onep = 1
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
g = 0
h = 0
money = int(input('Enter how much money you have in pence')) # Example: 292
# Calculate the number of coins needed and the remainder
# The remainder will "overwrite" the value previously held in the "money" variable
a, money = money // twopound, money % twopound # a = 1, money = 92
b, money = money // onepound, money % onepound # b = 0, money = 92
c, money = money // fiftyp, money % fiftyp # c = 1, money = 42
d, money = money // twentyp, money % twentyp # d = 2, money = 2
e, money = money // tenp, money % tenp # e = 0, money = 2
f, money = money // fivep, money % fivep # f = 0, money = 2
g, money = money // twop, money % twop # g = 1, money = 0
e, money = money // onep, money % onep # e = 0, money = 0
print(a,b,c,d,e,f,g,h)
This solution uses both integer division and remainder to perform the calculations.
Let's do it the right way: with a loop
Let's face it: the above code is verbose. There must be a better way... and there is! Use a loop.
Consider the algorithm: you repeat the steps jumping from one bin to the next and getting the number of coins you need and the remainder. This can be written in a loop.
So, let's add a list to our toolbox:
denominations = [200, 100, 50, 20, 10, 5, 2, 1]
And let's store the results of each step in a second list:
coins = [] # We'll use the '.append()' method to add elements to this list
So, starting in the first "bin":
n, money = money // denominations[0] , money % denominations[0]
coins.append(n)
Let's put this in a loop:
def select_coins_v2():
denominations = [200, 100, 50, 20, 10, 5, 2, 1]
coins = []
money = int(input('Enter how much money you have in pence'))
for i in range(len(denominations)):
n, money = money // denominations[i], money % denominations[i]
coins.append(n)
print(coins)
And that's it!
Another improvement: get the denomination only once and use it twice
Notice that the code above still has an issue: you read denominations twice. It would be nice if the denomination value could be read only once.
Of course, there is a way:
def select_coins_v3():
denominations = [200, 100, 50, 20, 10, 5, 2, 1]
coins = []
money = int(input('Enter how much money you have in pence'))
for d in denominations: # 'd' will hold the value of the denomination
n, money = money // d, money % d
coins.append(n)
print(coins)
As a friend of mine says: "Fast, precise and concise; not slow, difuse and confusing"
TL;DR
In Python 3.x, the "integer division" operator is // and the remainder (modulo) operator is %.
You can perform multiple assignement in a single line of code:
a, b = 1, 2
You can store the denominations in a list:
denominations = [200, 100, 50, 20, 10, 5, 2, 1]
You can read from the denominations list and get both the integer division and the remainder in a single step:
n, money = money // denominations[0], money % denominations[0]
You can write a loop that does all of the above:
for d in denominations: n, money = money // d, money % d
Bonus: Use a dictionary
What if I want to print both the denominations and the number of coins of each denomination I used? You can traverse both lists with a loop, but you can also keep it simple by using a dictionary:
def select_coins_v4():
denominations = [200, 100, 50, 20, 10, 5, 2, 1]
coins = []
money = int(input('Enter how much money you have in pence'))
for d in denominations: # 'd' will hold the value of the denomination
n, money = money // d, money % d
coins.append(n)
number_of_coins = dict(zip(denominations, coins))
print(number_of_coins)
Python offers a great deal of flexibility. Feel free to try different ways of getting what you need... and choose the easier one.
Hope this helps.
the cool thing about using real denominations is that the greedy solution will always find the optimal solution ... this stops holding true with weird denominations... but these problems are always easiest if you break them into parts
def get_one_change(amt_due):
# find how many of the largest denomination that you can use is
# ie for 60 = 1x50p is the count and number of largest
# for 4 = 4x1p ; 21 = 2x10p ; etc
return pence,count # ie 50,1 would be 1 50p coin
once you have this you just need to repeatedly call it and adjust your result until you have no change due
def get_change(amount_due):
changes_due = [] # to keep track
while amount_due:
pence,qty_of_coin = get_one_change(amount_due)
changes_due.append({"coin":pence,"qty":qty_of_coin})
amount_due = amount_due - (pence*qty_of_coin)
return changes_due
now you can just call your get_change method with your users input

How can I improve the time complexity of this algorithm for finding the max stock price?

I am currently passing the sample tests and 2 of the other 10 cases so 4 out of 12. However, I don't make it through all of the data. I am getting a Terminated due to timeout error which means that my solution isn't fast enough.
def stockmax(prices):
total = 0
for index, price in enumerate(prices):
if index < len(prices) - 1:
section = max(prices[index+1:])
if prices[index] < section:
total += section - prices[index]
return total
I tried to do everything in only one loop. But how exactly can speed this type of question up. I also tried to cut some lines of the code but it is equally as inefficient.
def stockmax(prices):
total = 0
for index, price in enumerate(prices):
if index < len(prices) - 1 and prices[index] < max(prices[index+1:]):
total += max(prices[index+1:]) - prices[index]
return total
Though it passes the same amount of test cases.
I also tried to use heapq but it passes the same test cases and fails due to time.
def stockmax(prices):
total = 0
for index, price in enumerate(prices):
if index < len(prices) - 1:
section = heapq.nlargest(1,prices[index+1:])[0]
if prices[index] < section:
total += section - prices[index]
return total
https://www.hackerrank.com/challenges/stockmax/topics/dynamic-programming-basics
for details on the problem.
https://hr-testcases-us-east-1.s3.amazonaws.com/330/input09.txt?AWSAccessKeyId=AKIAJ4WZFDFQTZRGO3QA&Expires=1538902058&Signature=3%2FnfZzPO8XKRNyGG0Yu9qJIptgk%3D&response-content-type=text%2Fplain
for a link of some test cases but will expire after a while.
Problem
Your algorithms have become so good at predicting the market that you now know what the share price of Wooden Orange Toothpicks Inc. (WOT) will be for the next number of days.
Each day, you can either buy one share of WOT, sell any number of shares of WOT that you own, or not make any transaction at all. What is the maximum profit you can obtain with an optimum trading strategy?
For example, if you know that prices for the next two days are prices = [1,2], you should buy one share day one, and sell it day two for a profit of 1. If they are instead prices = [2,1], no profit can be made so you don't buy or sell stock those days.
Function Description
Complete the stockmax function in the editor below. It must return an integer that represents the maximum profit achievable.
stockmax has the following parameter(s):
prices: an array of integers that represent predicted daily stock prices
Input Format
The first line contains the number of test cases t.
Each of the next t pairs of lines contain:
The first line contains an integer n, the number of predicted prices for WOT.
The next line contains n space-separated integers prices [i], each a predicted stock price for day i.
Constraints
1 <= t <= 10
1 <= n <= 50000
1 <= prices [i] <= 100000
Output Format
Output lines, each containing the maximum profit which can be obtained for the corresponding test case.
Sample Input
3
3
5 3 2
3
1 2 100
4
1 3 1 2
Sample Output
0
197
3
Explanation
For the first case, you cannot obtain any profit because the share price never rises.
For the second case, you can buy one share on the first two days and sell both of them on the third day.
For the third case, you can buy one share on day 1, sell one on day 2, buy one share on day 3, and sell one share on day 4.
Clearly, for any price we can buy, we would want to sell it at the highest price. Fortunately, we are given that highest price. So, iterating backwards, we know the highest future price seen at any point we visit in our travel "back in time."
Python code:
def stockmax(prices):
n = len(prices)
highest = prices[n - 1]
m = [0] * n
# Travel back in time,
# deciding whether to buy or not
for i in xrange(n - 2, -1, -1):
# The most profit buying stock at this point
# is what we may have made the next day
# (which is stored in m[i + 1])
# and what we could make if we bought today
m[i] = m[i + 1] + max(
# buy
highest - prices[i],
# don't buy
0
)
# Update the highest "future price"
highest = max(highest, prices[i])
return m[0]
If you can use Numpy, then something similar to the below should be rather quick (I believe it's the same idea as the answer from #גלעד ברקן).
import numpy as np
with open('.../input09.txt') as fd:
numtests = int(fd.readline().strip())
counter = 0
numvals = 0
vals = None
steps = None
for line in fd:
if (counter % 2 == 0) :
numvals = int(line.strip())
else:
vals = np.fromstring(line, dtype=int, sep=' ', count=numvals)
assert len(vals) == numvals
cum_max = np.maximum.accumulate(vals[::-1])
np.roll(cum_max, -1)
cum_max[len(cum_max) - 1] = 0
delta = (cum_max - vals)
print('#', counter + 1, 'sum:', np.sum(delta * (delta > 0)))
counter += 1
it runs almost instantly on tests from the input09.txt.
Here is my solution written in ruby.
The solution obtained perfect score.
def solution(a)
gain = 0
i = a.count - 1
min = false
mi = false
while i > 0
s = a.delete_at(i)
unless min
mi = a.index(a.min)
min = a[mi]
end
g = s - min
gain = g if g > gain
i -= 1
min = false if i == mi
end
gain
end

Figuring out money change in python

I have an assignment where I have to prompt the user for cost of a product and amount paid, I have to output change in pennies, dimes, quarters, $1, $5, $20, $50, and $100, for example: The cost of the item is $19.99 and the client pays with a $50 bill. The change to be provided is 1 $20 bill, one $10 bill, and one penny.
I am confused how to get an output like that though, any help would be greatly appreciated, heres what I have so far
cost = float(input('Cost: '))
amount_paid = float(input('Amount paid: '))
penny = 0.01
dime = 0.10
quarter = 0.25
dollar_1 = 1.00
dollar_5 = 5.00
dollar_10 = 10.00
dollar_20 = 20.00
dollar_50 = 50.00
dollar_100 = 100.00
change = cost - amount_paid
if amount_paid < cost:
print('Error')
I dont know what to do next
A common misstep here is to use floats. You should instead convert everything to the smallest whole unit (a cent) and use integer math. Floating point math is...fuzzy.
currencies = {"penny": 1,
"nickel": 5,
"dime": 10,
"quarter": 25,
"dollar": 1_00,
"five": 5_00,
"ten": 10_00,
"twenty": 20_00,
"fifty": 50_00,
"hundred": 100_00}
# never seen that numeric notation before? It's safe to embed underscores
# in numerical literals! It's often used for large numbers in place of
# commas, but it makes sense here in place of a period.
Then you should only need to define a dictionary for the result, and use divmod to find how many of the denomination can fit in the amount left due.
change_due = {}
for denomination, amt in reversed(currencies.items()):
if amt < amt_due:
d, m = divmod(amt_due, amt)
change_due[denomination] = d
amt_due = m
welcome to stackoverflow! I wrote the code for you and this is how it works. Basically it sees each currency and uses integer division // to see how many integers can fit in. It then subtracts that amount from the remaining change and the process continues. Please ask if you don't understand something, or if you think there is an error.
Code:
cost = float(input('Cost: '))
amount_paid = float(input('Amount paid: '))
penny = 0.01
dime = 0.10
quarter = 0.25
dollar_1 = 1.00
dollar_5 = 5.00
dollar_10 = 10.00
dollar_20 = 20.00
dollar_50 = 50.00
dollar_100 = 100.00
changeTypes = {dollar_100:0,dollar_50:0,dollar_20:0,dollar_10:0,dollar_5:0,dollar_1:0,quarter:0,dime:0,penny:0}
change = amount_paid-cost
if amount_paid < cost:
print('Error: InsufficientFunds')
for changeType in changeTypes:
numAmount = max(0,change//changeType)
change-=numAmount*changeType
changeTypes[changeType] = int(numAmount)
print(changeTypes)
P.S you should make this a function, it shouldn't be too hard.
You could do this good with dictionaries, but without using still there are many ways to go about this, options are endless, heres one idea
def get_bills(change, value):
if change//value > 0:
bills = change//value
change -= bills * value
return bills, change
else:
return 0, change
cost = float(input('Cost: '))
paid = float(input('Amount Paid: '))
while paid < cost:
paid = float(input('Amount Paid: '))
change = paid - cost
hundreds, change, = get_bills(change, 100)
fifties, change, = get_bills(change, 50)
twenties, change = get_bills(change, 20)
tens, change = get_bills(change, 10)
fives, change = get_bills(change, 5)
ones, change = get_bills(change, 1)
quarters, change = get_bills(change, .25)
dimes, change = get_bills(change, .1)
nickels, change = get_bills(change, .05)
pennies = round(change * 100)
print(f"Hundreds: {hundreds}, Fifties: {fifties}, Twenties: {twenties}," +
f" Tens: {tens}, Fives: {fives}, Ones: {ones}, Quarters: {quarters}," +
f" Dimes: {dimes}, Nickels: {nickels}, Pennies: " +
f"{pennies}")
bill = float(input())
paid = float(input())
Available = {100.0:0,50.0:0,20.0:0,10.0:0,5.0:0,1.0:0,0.25:0,0.10:0,0.01:0}
due = paid-bill
for change in sorted(Available,reverse = True):
amt= max(0,due//change)
due-=amt*change
Available[change] = int(amt)
print(Available)
I know this is a late response but maybe it can help someone.
Below is a code for doing exactly what you want. The program iterates through the notes available from largest to smallest and calculates how many times the current note may be used to deduct from the remaining change to be given.
Finally returning a list containing the notes used to reach the sum required.
# Available notes for change
notes = [500, 200, 100, 50, 20, 10]
def change_notes(change, notes):
notes_out = []
for note in notes:
print(f"current note is {note}")
sleep(1)
while change > 0 and note <= change:
if change - note >= 0:
change -= note
notes_out.append(note)
print(f"change is {change}")
sleep(1)
if change == 0:
break
return notes_out

What is an efficient way to calculate cost constrained by thresholds

I want to calculate cost of water expense of households constrained by certain thresholds:
Basically the thresholds are as follows:
for the first 0-10 m3 it will cost $10
for the subsequent 11-20 m3 it will cost $20
for the subsequent 21-30 m3 it will cost $30
for the subsequent >30 m3 it will cost $40
For example, if a household uses 40 m3 of water, it will be charged:
(10*10) + (10*20) + (10*30) + (10*40) = $1000
if a household uses 23 m3 of water, it will be charged:
(10*10) + (10*20) + (3*30) = $390
The only way I can think of is using if-conditionals. And I don't think that's the best way to calculate this.
You could also use a dictionary:
dic = {0:(0,10), 1:(100,20), 2:(300,30), 3:(600,40)}
Then you only need once an if-statement.
def costs(vol):
interval = vol/10 # vol must be positive int
if interval in dic:
price = dic[interval]
return price[0] + price[1]*(vol-price[1] + 10)
else:
return dic[3][0] + dic[3][1]*(vol-dic[3][1] + 10)
You can use the fact that the cost function is piecewise linear. Thus, you have to find out at which interval you are and use this as the key to your dictionary, where you save the cost at the beginning of each interval aswell as the increase of cost.
First define a list which will hold these limits in (difference in volume, price) format:
lst = [(10, 10), (10, 20), (10, 30), (None, 40)]
Note that the order matters. Here None stands for "no limit". And now the function:
def get_money(volume):
if volume <= 0:
return 0
total = 0
for diff, price in lst:
if volume == 0:
break
if diff is None:
total += volume * price
volume = 0
elif volume > diff:
total += diff * price
volume -= diff
else:
total += volume * price
volume = 0
return total
BTW: There is no way to solve this without using if. :)

Categories

Resources