Check if modulo of a number exists in a tuple - python

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.

Related

Python recursion function parameters issue

I'm calling a function inside itself many times to solve the subset sum problem, using as it called, the recursion solution; anyway, I can't figure out why n (which is the number of elements of the array) value is getting decreasing at first, until it reach 0, which is I get it, but then, after calling it again within itself, it makes n value incremented. Why is that happening, as the whole function doesn't even have an increment contribution for the n value? Where n gets its increasing value from?
Here is the code:
def printAllSubsetsRec(arr, n, currentSubset, sum):
# If remaining sum is 0, then print all
# elements of current subset.
if (sum == 0):
i = 0
sumOfValue = 0
for value in currentSubset:
i += 1
sumOfValue += value
if (i == len(currentSubset)):
print(value, " = ", sumOfValue)
else:
print(value, end=" + ")
return True
# If there are no elements in the array and the sum is not equal to 0.
if (n == 0 and sum != 0):
return None
# I consider two cases for every element:
# a) Excluding last element.
# b) Including last element in current subset.
# -------------------------------------------------
# Excluding the last element:
printAllSubsetsRec(arr, n - 1, currentSubset, sum)
v = [] + currentSubset
v.append(arr[n - 1])
# Including the last element:
printAllSubsetsRec(arr, n - 1, v, sum - arr[n - 1])
#Main:
arr = [10, 7, 5, 18, 12, 20, 15]
sum = 35
n = len(arr)
currentSubset = []
printAllSubsetsRec(arr, n, currentSubset, sum)
The output should be:
18 + 7 + 10 = 35
12 + 18 + 5 = 35
20 + 5 + 10 = 35
15 + 20 = 35
Thanks in advance!
Recursion is a functional heritage and so using it with functional style yields the best results. This means avoiding things like mutation, variable reassignment, and other side effects -
logical if without a corresponding else
mutation and reassignment of i and sumOfValue
side effects like print
Recursion doesn't have to be difficult or painful. Using functional disciplines we can write subsets(t,n) with inductive reasoning -
If the target sum n is zero, yield the empty solution
(inductive) otherwise n is negative or positive. If n is negative or the input array t is empty, we are out-of-bounds. stop iteration.
(inductive) n is positive and t has at least one element. For all s of the subproblem (t[1:],n-t[0]), prepend t[0] to s and yield. And yield all results of the subproblem (t[1:],n)
def subsets(t, n):
if n == 0:
yield () #1
elif n < 0 or not t:
return #2
else:
for s in subsets(t[1:], n - t[0]): #3
yield (t[0], *s)
yield from subsets(t[1:], n)
for s in subsets([10, 7, 5, 18, 12, 20, 15], 35):
print(s)
(10, 7, 18)
(10, 5, 20)
(5, 18, 12)
(20, 15)
Notice -
All operations do not mutate or reassign variables
Side effects like print are traded for yield
Caller is free to utilize and transform the results any way desired
To format the results as an mathematical expression -
for s in subsets([10, 7, 5, 18, 12, 20, 15], 35):
print(" + ".join(map(str, s)), "=", 35)
10 + 7 + 18 = 35
10 + 5 + 20 = 35
5 + 18 + 12 = 35
20 + 15 = 35
To collect all outputs of a generator into a list, use list -
print(list(subsets([10, 7, 5, 18, 12, 20, 15], 35)))
[(10, 7, 18), (10, 5, 20), (5, 18, 12), (20, 15)]

Split number into the primes inside it

So I have a list of numbers that look like "3723311723" and "13617172343". As you can see these numbers can be split into prime numbers e.g "3723311723" could be split into 37, 23, 31 ect. How could I write a python program that takes a number like this as an input and returns a list of the primes inside it (in the order they are found)?
Thanks.
If you know that the numbers are definitely gonna be prime, then you just have to break up the string into substrings of length 2, right?
s = "37233141712331719337"
print([int(s[i:i+2]) for i in range(0, len(s), 2)])
Output:
[37, 23, 31, 41, 71, 23, 31, 71, 93, 37]
EDIT:
This does a recursive search to find non-overlapping primes. If there's no valid split, it returns False. The usual caveats of recursion apply: if the input is too long, you'll recurse too deep and the program will blow up. But you can use a stack instead of recursing if that's an issue.
def is_prime(n):
for k in range(2, n):
if n % k == 0:
return False
return True
def primesplit(s, i=0):
if i+1 >= len(s):
return []
if i+2 <= len(s):
two_digits = int(s[i:i+2])
if is_prime(two_digits):
remaining_digits = primesplit(s, i+2)
if isinstance(remaining_digits, list):
return [two_digits] + remaining_digits
one_digit = int(s[i:i+1])
if not is_prime(one_digit):
return False
remaining_digits = primesplit(s, i+1)
if isinstance(remaining_digits, list):
return [one_digit] + remaining_digits
return False
s = "37233141712331719337"
result = primesplit(s)
print(result)
print("".join(map(str, result)) == s)
Output:
[37, 23, 31, 41, 71, 23, 31, 7, 19, 3, 37]
True
It's a bit complicated what you are asking for, but here's what I thought you meant:
Given a number, look for any two digit prime within that number(I assume they ARE allowed to overlap)
A easy way to do that is like this:
def isPrime(number):
if number>1:
for i in range(2,number):
if (number%i)==0:
return False
return True
else:
return False
def getPrimes(number):
number=str(number)
retList=[]
for i in range(len(number)-1):
temp=int(number[i:i+2])
if isPrime(temp):
retList+=[temp]
return retList
This does NOT check for single digit primes, but that could easily be added if you needed it (simply check every digit in the original number if they are prime).
Is this what you wanted?
This is what you are looking for:
The loop finds both 1 and 2 digit prime numbers in the order they appear in the original number and there will be no duplicates too.
In [126]: n
Out[126]: '37233141712331719337'
In [127]: primes = []
...: for i in range(len(n)-1):
...: n1 = int(n[i])
...: n2 = int(n[i:i+2])
...: if isPrime(n1):
...: if n1 not in primes:
...: primes.append(n1)
...: if isPrime(n2):
...: if n2 not in primes:
...: primes.append(n2)
...:
In [128]: primes
Out[128]: [3, 37, 7, 2, 23, 31, 1, 41, 17, 71, 19]
Here is how you can use the isprime method from the sympy module, and zip:
from sympy import isprime
n = "37233141712331719337"
lst = [int(i + j) for i, j in zip(n, n[1:]) if isprime(int(i + j))]
print(lst)
Output:
[37, 23, 31, 41, 17, 71, 23, 31, 17, 71, 19, 37]

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]

python function exact change won't work

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.

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