index element creates not needed input - python

I want to make a code that would propose a customer one or more of products to add to his shop list if he has total cart less than available budget (for example, he bought products for 120 dollars, and program should ask him if he want to add one or a couple of products (for example for 20 and 30 dollars) in list so budget gets close to 150 dollars limit)
My problem here is that somehow i += 1 creates an unwanted input() process which i cannot explain
I am a newbie in Python so maybe someone can propose the solving of problem or even better version of my code, i'll be greatful for every help!
https://ibb.co/vJwhMw0 link for image here
inp = 'bar'
product_list = ['bar', 'bread', 'milk', 'coconut']
product_price = [10, 24, 30, 25]
indx = product_list.index(inp)
price = product_price[indx]
budget = 150
total = 120
proposal_list = ''
i = 0
while total < budget:
if (product_price[i] + total) <= budget:
total += product_price[i]
proposal_list += product_list[i]
i = i + 1
print (f'You can also add: {proposal_list}')

There is some problems with your code. No unwanted input() is created it's just that your while loop is infinite because i never changes because the condition is never true at some point.
while total < budget:
if i >= len(product_price):
break
elif (product_price[i] + total) <= budget:
total += product_price[i]
proposal_list += product_list[i]
i += 1

You code got inside infinite loop right after this line:
while total < budget:
Once the code inside this line is executed
if (product_price[i] + total) <= budget:
total become equal 130. Condition total < budget is still true but condition
if (product_price[i] + total) <= budget:
is not.
You need to exit the while loop. You can't do it until you update total.

Related

Issue in the top down approach to the Coin Change (Similar to the 0-1 backpack problem)

I am now working on the Leetcode 322. Coin Change, the question is as following:
You are given an integer array coins representing coins of different
denominations and an integer amount representing a total amount of
money.
Return the fewest number of coins that you need to make up that
amount. If that amount of money cannot be made up by any combination
of the coins, return -1.
You may assume that you have an infinite number of each kind of coin.
Example 1:
Input: coins = [1,2,5], amount = 11 Output: 3 Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3 Output: -1
Example 3:
Input: coins = [1], amount = 0 Output: 0
Example 4:
Input: coins = [1], amount = 1 Output: 1
Example 5:
Input: coins = [1], amount = 2 Output: 2
I tried to solve it via the top-down DP with memorization. I set a parameter in the helper function to remember the count.
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
c = set(coins)
dp = [0] * (amount + 1)
def helper(a, count):
if a == 0:
return count
# if a in c:
# return 1 + count
if dp[a] != 0:
return dp[a]
res = math.inf
for coin in c:
if a - coin >= 0 and helper(a-coin, count+1) != -1:
res = min(res, helper(a-coin, count+1))
dp[a] = res if res < math.inf else -1
return dp[a]
return helper(amount, 0)
But it won't pass the case as:
[1,2,5]
100
The result supposes to be 20, but I got 92.
I tried to figure it out the whole afternoon, but not sure where I did wrong. I hope you can give me some suggestion where I went wrong.
Thanks in advance for your help.
!!! THIS IS A COMPLETE SOLUTION !!!
Ok, so here is my solution to this problem (idea explained below):
def solve(lst, amount):
lst = sorted(lst, key=lambda x: x, reverse=True)
cases = []
for seq in [lst[i:] for i in range(len(lst))]:
current_amount = 0
count = 0
for item in seq:
while True:
if current_amount + item == amount:
count += 1
current_amount += item
break
elif current_amount + item > amount:
break
elif current_amount < amount:
count += 1
current_amount += item
if current_amount == amount:
break
if current_amount == amount:
cases.append(count)
if cases:
return min(cases)
return -1
print(solve([1, 2, 5], 100))
print(solve([1, 5, 7, 9], 12))
# 20
# 2
Explanation:
!!! MAIN IDEA
First You have to start with the largest number in the list because it takes the least amount of additions to come the closest or completely become the final amount.
!!!
EDIT
As suggested by #nitinkumarp in comments, previous version (can check edits but why?) failed in some cases as mentioned in the comment, a workaround for that issue is to check all sequences in order, still using the greedy approach but slicing the original list shorter and shorter so that it can also check the correct solution which is 7 + 5, which is 2 coins.
So first thing to do is sort the list from the largest to the smallest number as shown with .sort() function.
Then for each number in that list (for loop starts with the first item in the list so the largest number) put them in a while True loop so that they keep adding to the total until condition is met:
There are 3 conditions:
current amount (from all the additions) plus the current item in the list equals the final amount, in that case increase the count by one and add the current item to total and then break out of the loop
if the current amount + current item in list are bigger than the final amount just break out (this makes sure that no more of such number are added)
the one that will get used the most is the one that checks if the current amount is smaller than the final one, but it is important that they are elif statements because in that case if one statement turns out to be true it doesn't check the rest which is not needed in this case because otherwise it would turn out to be true even if You couldn't add more to the current amount to not exceed the final amount.
this if statement is outside of the while True loop and checks if the final amount is matched when a number 'breaks out' of the while True loop, this is to prevent continuous checking even tho the result would be already achieved.
Then the result get evaluated and if the current amount doesn't match the final print -1 else print the count
This is my solution.
The main idea is to make use of the max value element in the list as much as possible and when it becomes dysfunctional, it is about to remove it from the list and use the new max value element.
class Solution:
def coinChange(self, coins, amount):
result = []
new_amount = amount
while len(coins) > 0:
while new_amount >= max(coins):
new_amount -= max(coins)
result.append(max(coins))
coins.remove(max(coins))
if len(result) == 0:
return 0
if sum(result) != amount:
return -1
return len(result)
Let's test the results;
coins = [2, 5, 4, 1]
amount = 10
s = Solution()
print(s.coinChange(coins=coins, amount=amount))
Output: 2
Because it produced a result list like this; [5, 5]

Beginner Python exercise

I'm having trouble solving problem 2 from this page
Here
Here's my code:
#Problem set 1 b
out_bal = float(raw_input("Enter the outstanding balance on your credit card: "))
ann_interest = float(raw_input("Enter the annual interest rate as a decimal: "))
min_pmnt = 10
months = 1
prev_bal = out_bal
month_interest = ann_interest / 12.0
updated_bal = prev_bal * (1 + month_interest) - min_pmnt
while out_bal > 0:
for i in range(1,13):
out_bal = updated_bal
prev_bal = out_bal
months += 1
if out_bal <= 0:
break
else:
min_pmnt = min_pmnt + 10
months = 0
print out_bal
print "RESULT"
print "Monthly payment to pay off debt in 1 year: $", min_pmnt
print "Number of months needed: ", months
print "Balance: ", round(out_bal, 2)
I want to take 1200 and .18 for the first two inputs, respectively. However when I do this the program gets caught in my while loop and keeps printing 1208.00.
When I read the code to myself it seems like it should be working. But I think I'm not using the prev_bal variable correctly.
Also, it's performing the math the way I expect it to the first time it goes through the loop but then it seems like it's not adding 10 to min_pmnt and going through the loop again. It seems like it's just using 10 over and over.
How can I write this so it does actually add 10 and perform the loop again?
Thanks!
Your problem is that updated_bal isn't changing, yet you are setting out_bal to it each time you iterate, and then conditioning the loop on out_bal becoming reduced in value.
It looks to me like you are thinking that updated_bal changes on each loop iteration, based on its component parts. In order for that to work, you would need to instead use a function that calculates an updated balance each time around.

Python - get while loop to run a certain amount of times

I am trying to get a while loop to function dur amount of times, however when I run it it just sits there, I assume calculating, seemingly forever. It is a simple script that shouldn't take very long to run, so I assume I have messed up the while loop.
Here is the code:
#Compound interest calculator
print "Enter amounts without $, years or %"
loan = input("How many dollars is your loan? ")
dur = input("How many years is your loan for? ")
per = input("What percent is the interest on your loan? ")
percent = per / 100
count = 0
#First calculation of amount
first = loan * percent
count = count + 1
#Continued calculation occurs until count is equal to the duration set by the user
while count <= dur:
out = first * percent
#Prints output
output = out + loan
print str(output)
There are a number of problems with your code.
percent will always be 0, because you are using integer division. Try percent = per / 100.0 instead.
As others have noted, you have to increase count to end the loop.
Without changing either first nor percent in the loop, the calculated value of out will be the same in each iteration of the loop. Try first = first * percent instead.
Finally, you do not need the loop at all. Just do this:
output = loan * (1 + per/100.)**dur
You need to increment count in the while loop, otherwise the stop condition (count <= dur) will never happen.
while count <= dur:
# do something
count += 1
If you know in advance the number of times you want to do something you could also use:
for i in xrange(dur): # use range if python3
# do something
Also note that your code has another problem: you're not really calculating compund interest. At every step you recalculate first * percent instead of adding percent to the previous interest. You should do:
# First calculation of amount
out = loan * percent
count = count + 1
while count <= dur:
out *= (1.0 + percent)
count += 1
count never changes within the loop. Do this
while count <= dur:
out = first * percent
count += 1

Simple Python loop counter issue

Ok, I am trying to make a simple program to kinda test how well i am learning things, I have come to a point where it is getting very large as I want the program to store data in sections (Day1,Day2....ect) so i tried to assign it to read the current Day count (Num_Days = ) but it doesnt seem to like this. I made a small test loop to try and test out if i could do this and have gotten stuck even though the logic looks good to me. I tried to do some searches but as i dont know what I am trying to do is even called I havent gotten very far. What I want to do is have the loop read the Num_Days and give the Days() the count and assign it to that day through 'n'.
Num_Days = 0
Total = 0
Data = 0
Day1 = 0
Day2 = 0
Day3 = 0
def Start_Work(x):
while Num_Days < 3:
Num_Days += 1
print "This is Day:",Num_Days
n = Num_Days
Total = +20
Day(n) += Total
else:
print "failed"
x = str('start')
I also made a dpaste on it as it is easier for me to look at it that way then in the full black: http://dpaste.com/1398446/
In order to clear up apparently where I lost some people with thinking that I am just trying to make a single loop that sits by its self I am going to put up what I am trying to use this for. This program is functioning the way I have wanted it to, the problem being that if i wanted o make it bigger it would get to be very long.
NumDays = 0
TotalOut = 0
Day1Tot = 0
Day1_RepsCnt = 0
Day4 = 0
def Work_Out(x):
while x == 1: ##crunches
NumDays = 0
TotalOut = 0
Day1Tot = 0
Day1_RepsCnt = 0
Day1_WghtCnt = 0
Day4 = 0
while NumDays < 3:
Day1_Wght = float(raw_input("How much weight did you use?"))
Day1_Reps = float(raw_input("How many reps did you do?"))
Day1_Sets = float(raw_input("How many sets were done?"))
Day1 = Day1_Wght * Day1_Reps * Day1_Sets
NumDays += 1
print "Day:",NumDays
print "Your total output is:",Day1
Day1_RepsCnt += Day1_Reps
Day1_WghtCnt += Day1_Wght
Day1Tot += Day1
TotalOut += Day1
if NumDays == 3:
print "Your total output for 3 days is:",TotalOut
print "Lets increase the Weight to",(Day1_Wght + 10)
print "Increase the Weight for days 4-6"
while NumDays >= 3 and NumDays <6:
Day4_Wght = float(raw_input("How much weight did you use?"))
if Day4_Wght <= (Day1_WghtCnt/3):
print "You need to increase your total output, add 10 pounds."
break
Day4_Reps = float(raw_input("How many reps did you do?"))
Day4_Sets = float(raw_input("How many sets were done?"))
Day4 += Day4_Wght * Day4_Reps * Day4_Sets
NumDays += 1
print "Day:",NumDays
if Day4_Wght <= (Day1_WghtCnt/3):
print "Re-enter totals once you have added the additional weight."
else :
print "Your total output was:",Day4
while x == 2: ##Benching
NumDays = 0
TotalOut = 0
Day1Tot = 0
Day1_RepsCnt = 0
Day4 = 0
while NumDays < 3:
Day1_Wght = float(raw_input("How much weight did you use?"))
Day1_Reps = float(raw_input("How many reps did you do?"))
Day1_Sets = float(raw_input("How many sets were done?"))
Day1 = Day1_Wght * Day1_Reps * Day1_Sets
NumDays += 1
print "Day:",NumDays
print "Your total output is:",Day1
Day1_RepsCnt += Day1_Reps
Day1Tot += Day1
TotalOut += Day1
if NumDays == 3:
print "Your total output for 3 days is:",TotalOut
print "Lets increase the Reps to",(Day1_Reps + 10)
print "Increase reps for days 4-6"
while NumDays >= 3 and NumDays <6:
Day4_Wght = float(raw_input("How much weight did you use?"))
Day4_Reps = float(raw_input("How many reps did you do?"))
if Day4_Reps <= (Day1_RepsCnt/3):
print "You need to increase your total output, do 10 more Reps."
break
Day4_Sets = float(raw_input("How many sets were done?"))
Day4 += Day4_Wght * Day4_Reps * Day4_Sets
NumDays += 1
print "Day:",NumDays
if Day4_Reps <= (Day1_RepsCnt/3):
print "Re-enter totals once you have completed the additional reps."
else :
print "Your total output was:",Day4
print "Available work outs in this version: crunches, benching"
Input = raw_input("What type of Work Out did you do?")
if Input.lower() == str('crunches'):
Work_Out(1)
if Input.lower() == str('benching'):
Work_Out(2)
else:
print "Failed"
And yes I understand that this needs to be cleaned up, but I have other ideas of what i want to throw in there and things i want to rearrange, but right now its just trying to figure out how I can break this into weekly cycles, and break each week into daily cycles, so i started with trying to get through one week and figure out that it would be very difficult just trying to get past 2 days so i broke it into 2 parts instead of 6 days. Any advise is welcome.
welcome to Python!
One of the beauties of Python is that the vast majority of Python programmers try to do things in the most "Pythonic" way when possible, so the first step I am going to take is to rename your variables and such according to PEP-8 standards. In other words, class names would be capitalized camelcase, but standard variables should be lowercase underscore-separated.
Second, if you ever find yourself naming variables with numbers like day1, day2, day3 etc, stop yourself and realize how unmaintainable that would be if you ever had to extend your program to work with 100 days (or 1,000, or 10,000, you get the point). Instead, you can just use a list called days and add as many as you need to it according to some configuration variable (e.g. total_days). For example:
total_days = 3
days = []
for _ in range(total_days):
days.append(0)
Or, use a list comprehension to be more Pythonic:
total_days = 3
days = [0 for _ in range(total_days)]
With these implementations all you'd have to do to add more days is to change the value of total_days. With all this in mind, let's try to reproduce your program:
# method definition
def start_workouts(total_days, init_workout, workout_increase):
workouts = [(init_workout + day * workout_increase) for day in range(total_days)]
return workouts
# method execution (3 days, starting at 100, increasing 20 each day)
my_workouts = start_workouts(3, 100, 20)
# my_workouts == [100, 120, 140]
# my_workouts[0] is "Day1"
# my_workouts[1] is "Day2"
# my_workouts[2] is "Day3"
So notice we moved some variable declarations to be passed in as arguments to your method. This way you can easily change the criteria for your workouts depending upon various circumstances that you might decide later. Also, we reduced all the calculations down to be part of a single list comprehension! (Isn't Python awesome?)
I hope I understood what you were trying to do correctly and that this helps you out. Let me know if you have any questions.
Might not be the best idea to set Days explicitly, as #blakev says, just use a list.
Num_Days = 0
Total = 0
Data = 0
Days = []
def Start_Work():
while Num_Days < 3:
Num_Days += 1
print "This is Day:",Num_Days
Total += 20
Days[Num_Days] = Total
else:
print "failed"
Start_Work() # call the function
You should get output that looks like
[20, 40, 60]
Your code does not look as correct Python code. Below are correction:
#-------------------
#while (condition):
# #commands
#-------------------
#for i in xrange(3):
# #commands
#-------------------
#Examples:
Num_Days = 0
Total = 0
Day = [0,0,0]
while Num_Days<3:
Num_Days += 1
print "This is Day:",Num_Days
Total += 20
Day[Num_Days-1] += Total
print Day
>>>
This is Day: 1
This is Day: 2
This is Day: 3
[20, 40, 60]
or better use:
Total = 0
Day = [0,0,0]
n = 3
for i in xrange(n):
print "This is Day:",i+1
Total += 20
Day[i] += Total
print Day
>>>
This is Day: 1
This is Day: 2
This is Day: 3
[20, 40, 60]

Writing python code to calculate a Geometric progression

Im new to programming and python. I need help with coding a geometric progression thats supposed to calculate the progression 1,2,4,8,16... Heres what I have so far:
def work_calc (days_worked, n):
temp=int(1)
if days_worked<2:
print (1)
else:
while temp <= days_worked:
pay1 = (temp**2)
pay = int(0)
pay += pay1
temp +=1
print ('your pay for ',temp-1,'is', pay1)
main()
Right now it gives me this output: 1, 4, 9, 16, 25
i need : 1,2,4,8,16,32...
im writing code that basically should do this:
Example:
Enter a number: 5
your value 1 is: 1
your value 2 is : 2
your value 3 is : 4
your value 4 is : 8
your value 5 is : 16
your total is: 31
Thanks in advance for your help and guidance!
P.S: Im like a dumb blonde sometimes(mostly) when it comes to programming, so thanks for your patience..
As I said, looks like you need powers of 2:
def work_calc (days_worked, n):
for temp in range(days_worked):
print ('your pay for ', temp + 1, 'is', 2 ** temp)
if you want to print strings (not tuples as you're doing now):
def work_calc (days_worked):
for temp in range(days_worked):
print 'your pay for {} is {}'.format(temp + 1, 2 ** temp)
>>> work_calc(5)
your pay for 1 is 1
your pay for 2 is 2
your pay for 3 is 4
your pay for 4 is 8
your pay for 5 is 16
Just to note - your code is calculating squares of temp, not powers of 2 that's why is not working
I understand this is probably overkill for what you are looking to do and you've been given great advice in the other answers in how to solve your problem but to introduce some other features of python here are some other approaches:
List comprehension:
def work_calc(days):
powers_of_two = [2**x for x in range(days)]
for i, n in enumerate(powers_of_two):
print('your pay for {} is {}'.format(i+1,n))
print('your total is {}'.format(sum(powers_of_two)))
This is compact and neat but would hold the whole list of 2^n in memory, for small n this is not a problem but for large could be expensive. Generator expressions are very similar to list comprehensions but defer calculation until iterated over.
def work_calc(days):
powers_of_two = (2**x for x in range(days))
total = 0
for i, n in enumerate(powers_of_two):
total += n
print('your pay for {} is {}'.format(i+1,n))
print('your total is {}'.format(total))
Had to move the total to a rolling calculation and it still calculates 2**n each time, a generator function would avoid power calculation:
import itertools
def powers_of_two():
n = 1
while True:
yield n
n *= 2
def work_calc(days):
total = 0
for i, n in enumerate(itertools.islice(powers_of_two(), days)):
total += n
print('your pay for {} is {}'.format(i+1,n))
print('your total is {}'.format(total))
As I said overkill, but hopefully introduces some of the other features of python.
Is this a homework question? (insufficient rep to comment)
In the sequence 1,2,4,8,16,32 each term is double the previous term.
So, you can keep a record of the previous term and double it to get the next one.
As others have mentioned, this is the same as as calculating 2^n (not, as I previously stated, n^2) , where n is the number of terms.
print ('your pay for 1 is' 1)
prevpay = 1
while temp <= days_worked:
pay1 = prevpay*2
pay = int(0)
pay += pay1
temp +=1
prevpay = pay1
print ('your pay for ',temp-1,'is', pay1)
That is all too complicated. Try always to keep things as simple as possible and especially, keep your code readable:
def main():
i = int(input("how many times should I double the value? "))
j = int(input("which value do you want to be doubled? "))
double_value(i,j)
def double_value(times,value):
for i in range(times):
i += 1
value = value + value
print(f"{i} --- {value:,}")
main()
Hope I could help.

Categories