python function exact change won't work - python

My assignment is:
where the input target_amount is a single non-negative integer value and the input L is a list of positive integer values. Then, exact_change should return either True or False: it should return True if it’s possible to create target_amount by adding up some-or-all of the values in L. It should return False if it’s not possible to create target_amount by adding up some-or-all of the values in L.
For example, L could represent the coins you have in your pocket and target_amount could represent the price of an item – in this case, exact_change would tell you whether or not you can pay for the item exactly.
Here are a few examples of exact_change in action. Notice that you can always make change for the target value of 0, and you can never make change for a negative target value: these are two, but not all, of the base cases!
The function I wrote is:
def exact_change( target_amount, L ):
if target_amount > sum(L):
return False
elif target_amount == 0:
return True
elif target_amount < 0:
return False
elif target_amount > 0 and L==[]:
return False
elif target_amount == L:
return True
else:
loseit = exact_change(target_amount, L[1:])
useit = exact_change(target_amount, L[0])
return loseit or useit'
And the outcame has to be:
>>> exact_change( 42, [25, 1, 25, 10, 5, 1] )
True
>>> exact_change( 42, [25, 1, 25, 10, 5] )
False
>>> exact_change( 42, [23, 1, 23, 100] )
False
>>> exact_change( 42, [23, 17, 2, 100] )
True
>>> exact_change( 42, [25, 16, 2, 15] )
True # needs to be able to "skip" the 16...
>>> exact_change( 0, [4, 5, 6] )
True
>>> exact_change( -47, [4, 5, 6] )
False
>>> exact_change( 0, [] )
True
>>> exact_change( 42, [] )
False
But my outcome is:
TypeError: 'int' object is not iterable
Please help me! What am I missing?

For the useit recursive call, you are passing a single int instead of the remaining list, see below:
def exact_change( target_amount, L ):
if target_amount > sum(L):
return False
elif target_amount == 0:
return True
elif target_amount < 0:
return False
elif target_amount > 0 and not L:
return False
else:
loseit = exact_change(target_amount, L[1:])
# reduce target amount since we use current coin
useit = exact_change(target_amount - L[0], L[1:])
return loseit or useit

You are trying to iterate through a single integer. This is not possible. You iterate through a list.

Related

Not fining last element in list

What I'm trying to do is taking the even indexes of a list then adding them together and lastly multiplying the total with the last element in the list. When I try with a set of negative numbers then suddenly its multiplying with index[1]
def checkio(array: list) -> int:
"""
sums even-indexes elements and multiply at the last
"""
total = 0
evennumbs = []
if len(array) == 0:
return 0
for i in array:
if array.index(i) % 2 == 0:
evennumbs.append(i)
for e in evennumbs:
#print(total, " + ", e, " = ")
total += e
print(evennumbs)
print(total)
total = total * array[-1]
return total
# These "asserts" using only for self-checking and not necessary for auto-testing
if __name__ == '__main__':
(checkio([-37,-36,-19,-99,29,20,3,-7,-64,84,36,62,26,-76,55,-24,84,49,-65,41]))
#assert checkio([0, 1, 2, 3, 4, 5]) == 30, "(0+2+4)*5=30"
#assert checkio([1, 3, 5]) == 30, "(1+5)*5=30"
#assert checkio([6]) == 36, "(6)*6=36"
#assert checkio([]) == 0, "An empty array = 0"
This is the output I'm getting
[-37, -19, 29, 3, -64, 36, 26, 55, -65]
-36
-36 is the number it's multiplying with instead of 41.
Your function would be simplified a lot using slicing:
def checkio(array: list) -> int:
if not array:
return 0
return sum(array[::2])*array[-1]
assert checkio([0, 1, 2, 3, 4, 5]) == 30, "(0+2+4)*5=30"
assert checkio([1, 3, 5]) == 30, "(1+5)*5=30"
assert checkio([6]) == 36, "(6)*6=36"
assert checkio([]) == 0, "An empty array = 0"
Aside from the useless need for loops in your solution, this bit in particular is incorrect:
for i in array:
if array.index(i) % 2 == 0:
evennumbs.append(i)
this would fail on input such as [1,2,3,3] or [1,2,2,3] as list.index always returns the first occurrence
array.index(i) returns the index of the first occurrence of i in array. The first occurrence of the value 84 in your test array is on an odd index, although it later occurs on an even index as well, and so you are losing it.
You should probably simply loop over the indices directly.
for i in range(0, len(array)+1, 2):
evennumbs.append(array[i])
But of course, this can be simplified to just
evennumbs = array[::2]
and so the entire function can be simplified to
from typing import List
def checkio(array: List[int]) -> int:
if len(array) == 0:
return 0
return sum(array[::2]) * array[-1]

Should check every numeral of number and got bad output

i have a task:
got a range on input
[x;y]
then i should check every number from that range and check every numeral in number. if its odd, i should print it
for example: 3, 20
i should print 4,6,8,20
def check(num):
if int(num) % 2 == 0:
return True
x, y = int(input()), int(input())
numbers = []
if x <= y:
while x != y:
for i in str(x):
if check(i):
numbers.append(x)
x += 1
else:
while y != x:
for i in str(y):
i = int(i)
if check(i):
numbers.append(y)
y += 1
if y == x:
for i in str(x):
if check(i):
numbers.append(x)
print(numbers)
it prints
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 20, 21, 22, 22, 23, 24, 24, 25, 26, 26, 27, 28, 28, 29]
instead of 2,4,6,8,20,22,24,26,28
You are checking and approving based on a single digit for each number. You should check all of them before appending the entire number. That's why you get 22 twice: once for the first 2 and once for the second. You get 10, because even though 1 is odd, 0 is even and so you append it to your list.
Move the check for the entire number into the function check and have it return True only if all digits are even. This shortens your code. Also note that you can trivially swap x and y if the user entered them in the wrong order.
The function check immediately returns False as soon as it finds a digit i is odd, and you can see it can only return True if the loop ended and all digits were even.
def check(num):
for i in str(num):
if int(i) % 2 != 0:
return False
return True
x, y = int(input()), int(input())
if x > y:
x,y = y,x
numbers = []
while x <= y:
if check(x):
numbers.append(x)
x += 1
print (numbers)
Result, with 3 and 20 entered (but 20 and 3 would also work):
[4, 6, 8, 20]

Why is it showing 'None' as an output for my function in python?

Write a function accordian(l) that takes as input a list of integer l and returns True if the absolute difference between each adjacent pair of elements strictly increases.
def accordian(l):
for i in range(len(l)):
diff = []
for i in range(len(diff)):
diff = l[i] - l[i+1]
if diff[i] < diff[i+1]:
return True
else:
return False
print(accordian([1,3,7,2,9]))
Output: "None"
Your code doesn't work because the inner loop never runs, since the length of diff is 0, however a range of 0 doesn't proceed, your code will work if you add a value to diff, I can't give a code since I don't fully understand what you wanna do.
You can try:
def accordian(data):
diff = []
for index, value in enumerate(data):
if index == 0:
continue
diff.append(data[index] - data[index - 1])
flag = True
for index, single_element in enumerate(diff):
if index == 0:
continue
if diff[index] <= diff[index - 1]:
flag = False
break
return flag
print(accordian([1, 3, 7, 2, 9]))
print(accordian([1, 3, 7, 13, 21]))
print(accordian([1, 3, 5, 7, 9]))
Output:
False
True
False

Check if modulo of a number exists in a tuple

I'm trying to check modulo of a number against a tuple of numbers, if the modulo is equals to one of the values in the tuple I want to return True else return False.
This is what I had tried so far:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
for i in range(0, len(k)):
if k[i] == y % 30:
return True
else:
return False
def main():
print(check(1439))
main()
It always returns false.
This is always returning false as only first item is checked. If first item is a match then it will return true. For example, if y is 32 then it will return true. You need to return false after checking all values, i.e. outside of for loop. Or a better solution is to use in operator.
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return y % 30 in k
It always returns false because this code:
for i in range(0, len(k)):
if k[i] == y % 30:
return True
else:
return False
returns true or false based only on the first item in the array, because it returns in both possible code paths. Either k[0] == y % 30 and it returns true, or k[0] != y % 30 and it returns false.
If you want to use this loop-based solution, you need to check every item in the array, returning true immediately if it matches, otherwise returning false only after the list is exhausted, something like (using the for n in k variant of the loop since the index is irrelevant here):
for n in k:
if n == y % 30:
return True
return False
The full program is thus:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
for n in k:
if n == y % 30:
return True
return False
def main():
print(check(1439))
print(check(36))
main()
with the first call producing true as 1439 % 30 == 29 (in the list) but the second giving false because 36 % 30 == 6 (not in the list).
Of course, there's a far more Pythonic way to achieve this:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return any (x == y % 30 for x in k)
That basically finds any element in k for which that element is equal to y % 30. See this link for more information on the Python any operation, and you'll see instantly the equivalent code given is remarkably similar to your loop:
def any(iterable):
for element in iterable:
if element:
return True
return False
But, of course, it turns out to be unnecessary to use any in this particular case as y % 30 is effectively a fixed value in the context of searching through the list. Instead, you can opt for the much simpler:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return (y % 30) in k
leaving the any variant for more complex comparisons not easily doable, such as only checking even numbers from the list:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return any (x == y % 30 for x in k if x % 2 == 0)
You can accomplish this with a generator expression inside any():
def check(y):
return any(n == y % 30 for n in k)
This builds an iterator of booleans that is true for all elements of k that are divisors of y.

Making recursive function in python

This is a homework problem. I try to get a recursive function:
def problem_a(n):
answer.append(n)
if n == 1:
return answer
elif n % 2 == 0:
answer.append(n/2)
else :
answer.append(n*3 + 1)
problem_a(n*3 + 1)
This code obviously doesn't work as answer isn't defined as a list. With loops it would work, but I want to make a recursive function. I could just use as input a list, but I wonder if there exist something more elegant.
problem_a(7) should give as output:
[7, 22, 11, 34, 17, 52, 26, 13, 40 , 20, 10 ,5 ,16, 8, 4, 2, 1]
One alternative solution to the ones that have been suggested so far (which use an extra argument to pass the list up the recursive chain) is to build the final list as you return from the recursion. This is not terribly efficient, since concatenating lists requires copying both of them, but it will work:
def problem_a(n):
if n == 1:
return [n]
elif n % 2 == 0:
return [n] + problem_a(n // 2)
else:
return [n] + problem_a(3*n + 1)
You could try a generator:
def problem_a(n):
yield n
if n == 1:
return
elif n % 2 == 0:
x = n / 2
else:
x = n * 3 + 1
for y in problem_a(x):
yield y
print list(problem_a(7))
You can define a local variable answer and pass it around in recursive calls.
def problem_a(n, answer = None):
answer = [n] if answer is None else answer
if n == 1:
return answer
elif n % 2 == 0:
n = n/2
answer.append(n)
else:
n = n*3 + 1
answer.append(n)
return problem_a(n, answer)
print problem_a(7)
output:
[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
There is a problem with your skeleton solution. You need to recurse when n % 2 == 0 as well as in the final else. The answer variable is given a default value so that it is initialized to [] when the function is first called without an argument.
def problem_a(n, answer=None):
if answer == None:
answer = []
answer.append(n)
if n == 1:
return answer
elif n % 2 == 0:
return problem_a(n/2, answer)
else :
return problem_a(n*3 + 1, answer)
>>> problem_a(7)
[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
Edit
As per the comments, using a mutable default argument is a bad idea. Just set it to None like in the other posts and check if its None to create a new list. I changed the answer to reflect this.
The original bad code was as follows:
def problem_a(n, answer=[]):
answer.append(n)
...
You can also use a closure:
>>> def s():
ret = []
def f(n):
ret.append(n)
if n % 2 == 0:
f(int(n/2))
elif n != 1:
f(int(n*3 + 1))
return ret
return f
>>> s()
<function f at 0x00000000033A5848>
>>> s()(7)
[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]

Categories

Resources