Minimum coin change class giving wrong answer - python

Trying to [solve] the problem in leetcode (322):
You are given coins of different denominations and a total amount of
money amount. Write a function to compute 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.
I am stuck in this input: coins = [2] and target = 3
I wonder why it is returning 0? I debugged this but not able to figure out.
class Solution(object):
def coinChange(self, coins, amount):
"""
:type coins: List[int]
:type amount: int
:rtype: int
"""
def get_cost(coins, amount):
if amount == 0:
return 0
min_cost = float('inf')
for coin in coins:
if amount >= coin:
min_cost = min(min_cost, 1 + self.coinChange(coins, amount - coin))
return min_cost
cost = get_cost(coins, amount)
if cost == float('inf'):
return -1
return cost

Your logic is not correct, you want to do something like this: the minimum cost either contains the current coin or it does not. This would in pseudo code look like:
min_coins = current cost + min(cost without using this coin, cost using this coin)
so you should put the current cost in your state and also keep track of which coins you are allowed to use.

Related

How do you Multiply numbers in a loop in Python from a list of user inputs

I need to create something that can multiply values no matter how many values there are. My idea is to use a list and then get the sum of the list with the sum function or get the first value of the list and set it as the total and then multiply the rest of the list by that total. Does anyone have a way to do it?
Here was my original idea:
total = 0
while True:
number = float(input("Enter a number and I’ll keep multiplying until you enter the number 1: "))
if number == 1:
break
else:
total *= number
print(f"The total is: {total}")
however as you may have guessed it just automatically multiplies it to 0 which equals zero. I would also like the code to work for subtraction and division (Already got Addition working)
thanks!
Thanks to the comments I worked out that the way to do it is by changing the beginning total to a 1 when fixed it is this:
total = 1
while True:
number = float(input("Enter a number and I’ll keep multiplying until you enter the number 1: "))
if number == 1:
break
else:
total *= number
print(f"The total is: {total}")
Since you are multiplying, you must start with 1 cause anything multiplied by 0 is 0. And idk why you need sum()
total = 1
while True:
number = float(input("Enter a number and I’ll keep multiplying until you enter the number 1: "))
if number == 1:
print(f"The total is: {total}")
break
else:
total *= number

Having problem with adding iteration into recursion

I was trying to solve a dp problem (checking if given amount can be broken down with given coins with different values, assuming there are infinite number of coins available for each valued coins)
def istrue(coins, amount):
if (amount - coins[0] > 0):
holder = False
while (holder == False and len(coins) != 0):
holder = holder or istrue(coins, amount - coins[0])
if(len(coins) != 0):
coins.pop(0)
return holder
elif (amount - coins[0] < 0):
return False
else:
return True
And was not sure what would be an appropriate way of iterating through the given coins.
Currently, I am having trouble inside the while loop. (If the amount left to break down is bigger than current value of a coin, it moves onto the next coin) But the amount to be break down also goes back a step because I used pop..
Any hints for fixing this? example) coins: [7,3]. amount: 20. -> as it reaches 6 (20-7-7), the index for coins array moves on but also the amount gets backed up a step because I pop()ed it.
You can loop over your coins instead of doing a recursion:
def istrue(coins, amount):
coins.sort(reverse=True)
_, remainder = divmod(amount, coins[0])
coins.pop(0)
for coin in coins:
_, remainder = divmod(remainder, coin)
return not remainder

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]

Returning minimum of array with for loop iteration

I received this line of code that I'm having trouble understanding syntactically.
def coinsNeeded(coins, price, mincoinList):
return min([mincoinList[price-coin] for coin in coins if coin <= price]) + 1
What I know so far is that coins and mincoinList are both arrays of integers and that price is also an integer.
From my understanding, the min() function requires an iterable or two arguments, so I don't quite understand what values are being compared in the min() function.
min([mincoinList[price-coin] for coin in coins if coin <= price]) + 1
Let’s disect this line!
The core part of this is the following list comprehension:
[mincoinList[price-coin] for coin in coins if coin <= price]
List comprehensions are a way to create a list by looping over some sequence. In this case, we are creating a list with elements of the value mincoinList[price - coin] for each coin in the coins list if the value of coin is lower or equal to price.
So in other words, it selects those coins which are lower than the price, and then for each of those, it gets an element from mincoinList with the difference of the price and coin as the index.
Finally, that list is passed to min() which just returns the element from the list with the lowest value. That value is then incremented by one and returned from the function.
You could write this all in a very verbose multi-line code like this:
selectedCoins = []
for coin in coins:
if coin <= price:
selectedCoins.append(mincoinList[price - coin])
return min(selectedCoins) + 1
Your code:
def coinsNeeded(coins, price, mincoinList):
return min([mincoinList[price-coin] for coin in coins if coin <= price]) + 1
has a list comprehension which is equivalent to:
def coinsNeeded(coins, price, mincoinList):
minCoinNeeded = []
for coin in coins:
if coin <= price:
minCoinNeeded += mincoinList[price-coin]
return min(minCoinNeeded) + 1

Function statement() that outputs the sum of the deposit and the sum of the withdraw

I'm having trouble with this question:
Write a function statement() that takes as input a list of floating point numbers, with positive numbers representing deposits to and negative numbers representing withdrawals from a bank account. Your function should return a list of two floating point number; the first will be the sum of the deposits and the second will be the sum of the withdrawals
code I have:
import math
def statement (bank):
deposit = []
withdrawal = []
i = 0
for i in range(1, len(bank)):
if bank[i] >= 0:
deposit.append(bank[i])
elif bank[i] < 0:
withdrawal.append(bank[i])
print (sum(deposit, withdrawal))
statement([30.95, -15.67, 45.56, -55.00, 43.78])
The problem is that I can't add the float from a list. How can i do that? Thank you
This is what I think they were looking for based on the problem description
def statement(bank):
deposit = 0
withdrawal = 0
for transaction in bank:
if transaction > 0:
deposit += transaction
else:
withdrawal += transaction
return [deposit, withdrawal]
The list should have two elements. The first is the sum of all deposits, the second is the sum of all withdrawals.
>>> statement([30.95, -15.67, 45.56, -55.00, 43.78])
[120.29, -70.67]

Categories