I am following "Fluent Python" to learn Function and Design Pattern:
In chapter 6 example-code/strategy.py
def bulk_item_promo(order):
"""10% discount for each LineItem with 20 or more units"""
discount = 0
for item in order.cart:
if item.quantity >= 20:
discount += item.total() * .1 #augmented += ?
return discount
I am very confused about:
discount += item.total() * .1
I assume it overhead complicated, because it's just
discount = item.total() * .1
However, the author prefer to state it like
discount = 0*1 + 0*2 + 0*3 + item.total() * .1
to increase it complexity artificially.
What's the key points I missed? could you please provide any hints?
The code discount += item.total() * .1 is equivalent to:
discount = discount + (item.total() * 0.1)
I've added the parentheses for clarity, but they are not necessary as multiplication has precedence over addition.
Your function calculates an absolute discount by aggregating discounts for all items with quantity greater than 20. The discount equates to 10% of the undiscounted cost of in-scope items.
The same function can also be written with sum and a generator expression:
def bulk_item_promo(order):
"""10% discount for each LineItem with 20 or more units"""
return sum(item.total() * 0.1 for item in order.cart if item.quantity >= 20)
Suppose there are 3 items in the order. Call them a, b, and c. Say that each one had more than 20 units. Say that a.total() == b.total() == c.total() == 100. In the case of:
discount = item.total() * .1
discount will be 10. So you would get 10 off the entire 300. But that isn't really what you want, you want 10 off of each a.total(), b.total() and c.total(), so you want 30. This why you use += instead as it aggregates over each (qualified) item.
Every item in the basket can have a discount. To calculate the total discount, you need to add up the individual discounts for all items that have an discount, and that is what the code does. Calling the variable "total_discount" instead of "discount" might have been better.
left += right
means: Calculate the value "right", then add it to the variable left. discount_total += (formula for item discount) means calculate the item discount according to the formula, and add it to the discount_total. In your case
discount_total += item.total() * 0.1
means: Calculate the discount for this item by calculating its total and multiplying by 0.1 (which is the same as taking ten percent). Then add the discount for this item to the discount total.
Related
I'm attempting to take a starting balance and increase the value by 5% each month. I then want to feed this new balance back into the equation for the next month. I've attempted to do this using a while loop but it doesn't seem to be feeding the new balance back in.
I'm using 60 months (5 years) for the equation but this can be altered
counter = 1
balance = 1000
balance_interest = balance * .05
while counter <= 60:
new_monthly_balance = (balance + balance_interest)*(counter/counter)
print(new_monthly_balance)
balance = new_monthly_balance
counter += 1
You never change balance_interest in the loop.
What do you intend to do with *(counter/counter)? This merely multiplies by 1.0, which is a no-op.
while counter <= 60:
balance *= 1.05
print(balance)
counter += 1
Better yet, since you know how many times you want to iterate, use a for:
for month in range(60):
balance *= 1.05
print(balance)
BTW, just what sort of finance has a constant 5% monthly increase???
So if
balance = int(100)
balance *= 0.05
since balance is mutable should'nt that equal to 105? instead i just get 5.
and if i add another line of code such as
balance = int(100)
balance *= 0.05
balance *= 0.05
the output would be 0.25, essentially my variable is not carrying over and im just multiplying the end outcome to 5%
if i add
balance= int(100)
balance *= 0.05 + balance
i get 10005
I thought += or *= function could be used for an equation that would take a variable, do the equation then carry over the variable + the outcome as the new variable.
How do i do that for a multi step equation.
balance = int(100)
balance *= 0.05
is the same as
balance = int(100)
balance = balance * 0.05
Wouldn't you say that that's 5, not 105?
A *= B is just a shorthand for A = A * B.
Your third example is the same as:
balance= int(100)
balance = balance * (0.05 + balance)
Again, you're getting what I would think you'd expect from this code.
BTW, you don't need the int(). 100 by itself is a literal value of type 'int'. So the most concise way to state your first code block is:
balance = 100 * .05
Sorry for saying this but you have to first under the python or any programming language basics.
'+' is addition sigh
'*' is multiplication sign
A = 2 + 3
gives 5 as answer, and
A = 2 * 3 will give 6 as answer.
Secondly, '+=' , '*=' are shorthand where the operation's first value is the same space where you want to save the result.
like
A = 5
and want to add 3 in this same 'A'
A = A + 3 or can also be written as A += 3,
similarly for multiplication
A = 100
A = 100 * 0.05 can also be written as A *= 0.05
it will give A as 5
So, good luck.
This is that piece of code I wrote:
#This is the first ever piece of code I/'m Writing here
#This calculates the value after applying GST
#Example: here we are applying on a smartphone costing 10000
Cost = input('Enter the MRP of device here ')
Tax = 0.12
Discount = 0.05
Cost = Cost + Cost * float(Tax)
Total = Cost + Cost * float(Discount)
print(Total)
Whenever I try to execute the code it gives an exception after input:
TypeError: can't multiply sequence by non-int of type 'float'
There's a few weird parts here I'll try to break them down. The first is the one you are actually asking about which is caused by input returning a string, so you are effectively doing something like this. I'm going to lowercase the variable names to match python style
cost = "2.50"
tax = 0.12
#...
cost * tax # multiplying str and float
Fix this by wrapping the call to input with a call to float to convert the str
cost = float(input('Enter the MRP of device here '))
tax = 0.12
discount = 0.5
next you have these extra calls float(tax) and float(discount). Since both of these are floats already, you don't need this.
There is also a shorthand syntax for x = x + y which is x += y with these two things in mind, you can adjust your calculation lines:
cost += cost * tax
cost += cost * discount
print(cost)
raw input is as string,cast it into float
Cost = input('Enter the MRP of device here ')
Cost=float(Cost)
Tax = 0.12
Discount = 0.05
Cost = Cost + Cost * float(Tax)
Total = Cost + Cost * float(Discount)
print(Total)
I'm struggling with a problem that calculates the minimum fixed monthly payment needed in order pay off a credit card balance within 12 months. By a fixed monthly payment, I mean a single number which does not change each month, but instead is a constant amount, multiple of 10 and the same for all months, that will be paid each month. ( it is possible for the balance to become negative using this payment scheme, which is OK)
So as input I have
original_balance = 3329
annualInterestRate = 0.2
From this I'm calculating the followings :
after_12_months_interest = original_balance
monthlyInterestRate = round(annualInterestRate/12.0,2)
monthly_payment = 10
total_paid = 0
for i in range(0,12):
after_12_months_interest = after_12_months_interest + (annualInterestRate/12.0)*after_12_months_interest
while total_paid < after_12_months_interest:
new_balance = 0
unpaid_balance = original_balance - monthly_payment
total_paid = 0
for i in range(0, 13):
total_paid = total_paid + monthly_payment
if total_paid < after_12_months_interest:
monthly_payment = monthly_payment + 10
print "Lowest Payment: ", monthly_payment
My problem I have is that I end up having a monthly_payment just a little more than I should have it. In this case the return for the monthly_payment is 320 instead of 310. For all use cases I've tried the monthly_payment it's slightly more than it should be.
Anyone can give me a hint or an idea on what I'm doing wrong please. Thank you
Mandatory one-liner
from itertools import count
print(next(payment for payment in count(0, 10)
if sum(payment*(1+monthly)**i for i in range(12)) > original_balance*(1+annual)))
What this does:
next takes the first element of an iterator.
count tries values from 0 to infinity (only each time next is called, and only until a value is returned)
sum(payment*(1+monthly)**i for i in range(12)) That's the combined value of the payments. Each payment is worth itself plus all the saved interests (the earlier you repay, the less interest you'll owe later)
original_balance*(1+annual) is indeed the total value if nothing is repayed.
Alternative
print(next(payment for payment in count(0, 10)
if reduce(lambda x,_:(x - payment)*(1+monthly), range(12), original_balance) <= 0))
This one computes the combined remainder of the debt by reduceing the original_balance 12 times.
In python: how do I divide an int received by a user from a list while every time it runs in the for loop I need to divide the value I received from the round before in the next round?
This is my code:
a = input('price: ')
b = input('cash paid: ')
coin_bills = [100, 50, 20, 10, 5, 1, 0.5]
if b >= a:
for i in coin_bills:
hef = b - a
print (hef / i), '*', i
else:
print 'pay up!'
Example: a=370 b=500 ---> b-a=130
Now in the loop I will receive (when i=100) 1, and (when i=50) I will receive 2 but I want in the second round (when i=50) to divide 30 (130[=b-a]- 100[=answer of round 1*i]) by 50.
What do I need to change in the code?
Thanks!
You just need to subtract the amount of change you give back at each step from the total amount of change you're returning. It's much easier to see if you change your variable names to something meaningful:
price= int(raw_input('price: ')) # Use int(raw_input()) for safety.
paid= int(raw_input('cash paid: '))
coin_bills=[100,50,20,10,5,1,0.5]
if paid >= price:
change = paid - price
for i in coin_bills:
# Use // to force integer division - not needed in Py2, but good practice
# This means you can't give change in a size less than the smallest coin!
print (change // i),'*',i
change -= (change // i) * i # Subtract what you returned from the total change.
else:
print 'pay up!'
You could also clear up the output a bit by only printing the coins/bills that you actually return. Then the inner loop might look something like this:
for i in coin_bills:
coins_or_bills_returned = change // i
if coins_or_bills_returned: # Only print if there's something worth saying.
print coins_or_bills_returned,'*',i
change -= coins_or_bills_returned * i
OK, I'm assuming that you're trying to calculate change for a transaction using a number of types of bills.
The problem is that you need to keep a running tally of how much change you have left to pay out. I used num_curr_bill to calculate how many of the current bill type you're paying out, and your hef I changed to remaining_change (so it would mean something to me) for the remaining change to pay.
a= input('price: ')
b= input('cash paid: ')
coin_bills=[100,50,20,10,5,1,0.5]
if b>=a:
# Calculate total change to pay out, ONCE (so not in the loop)
remaining_change = b-a
for i in coin_bills:
# Find the number of the current bill to pay out
num_curr_bill = remaining_change/i
# Subtract how much you paid out with the current bill from the remaining change
remaining_change -= num_curr_bill * i
# Print the result for the current bill.
print num_curr_bill,'*',i
else:
print 'pay up!'
So, for a price of 120 and cash paid 175, the output is:
price: 120
cash paid: 175
0 * 100
1 * 50
0 * 20
0 * 10
1 * 5
0 * 1
0.0 * 0.5
One bill for 50 and one for 5 add up to 55, the correct change.
Edit: I'd go more sparingly on the comments in my own code, but I added them here for explanation so that you could more clearly see what my thought process was.
Edit 2: I would consider removing the 0.5 in coin_bills and replacing 1 with 1.0, since any fractional amounts will wind up being fractions of 0.5 anyway.