Python Debugging: weird event when negative sign is in front - python

I was doing an assignment question.
Write a program, divisible_by_11(num), to return the divisibility of num
by 11. i.e. divisible_by_11(num) should return True is num is divisible by 11,
or False otherwise. Implement this function recursively and using the following algorithm.
Note: a number is divisible by 11 if the difference between the sum of odd digits
and the sum of even digits is divisible by 11. Note that 0 is divisible by 11.
def divisible_by_11(num):
def helper(num,i):
if num==0:
return 0
elif i%2:
return helper(num//10,i+1)-num%10
Question is about replacing the above line with return -num%10+ helper(num//10,i+1)
elif i%2==0:
return num%10+helper(num//10,i+1)
return helper(num,0)%11==0
this code works, however if I wrote return -num%10+ helper(num//10,i+1) instead of return helper(num//10,i+1)-num%10, my code would fail. Can anyone tell me what's happening?

The issue with the alternate form is due to order of operations. The unary-minus operator binds more tightly than the mod operator. That is, the expression -num%10 is interpreted as (-num) % 10, and the modulus of a negative number is not the same thing as its last digit.
There are a few ways you could fix it. The easiest would probably be to add your own parentheses so that the mod happens first: return -(num%10) + helper(num//10,i+1) should work as expected.
Unrelated to that issue, I'm very skeptical that your assignment allows you to do %11 in the final return, since that operation is all you would need to solve the whole problem without the rest!
Instead, I suspect it wants you to use recursion for that part too (and maybe not for adding up the digits). Instead of return helper(num,0)%11==0, try:
while num > 10:
num = helper(num, 0)
return num == 0

Related

Debugging in Hungarian Maximum Matching

I wrote a code to solve the following algorithm question:
Given a number of positive integers all larger than 1, find the maximum number of pairs whose sum is a prime number. The number of positive integers is always an even number.
For example, given 2 5 6 13 2 11, the answer is 3 since 2+5=7, 6+13=19, 2+11=13.
I wrote the following code to solve the problem. I know this is not the optimal algorithm, but I just cannot find the bug in it that results in my failure in test cases.
def _isPrime(num):
for i in range(2, int(num**0.5)+1):
if num % i==0:
return False
return True
def findPairs(odds, evens, pairDict):
if len(odds)==0 or len(evens)==0:
return 0
key=' '.join(list(map(str, odds+evens)))
if key in pairDict:
return pairDict[key]
n=0
for i in range(len(evens)):
newOdds=odds.copy()
newEvens=evens.copy()
del newOdds[0]
del newEvens[i]
if _isPrime(odds[0]+evens[i]):
n=max(n,findPairs(newOdds, newEvens, pairDict)+1)
else:
n=max(n,findPairs(newOdds, newEvens,pairDict))
pairDict[key]=n
return n
numbers=list(map(int,input().split()))
odds=[i for i in numbers if i%2==1]
evens=[j for j in numbers if j%2==0]
pairDict={}
print(findPairs(odds,evens,pairDict))
Can someone help me find where the problem is. Thanks a lot!
The problem is that the recursion always tries to match the first odd number with some even number. This can go wrong if there are fewer even numbers than odd numbers because it will use up an even number that could have been used for a later match.
For example, consider "13 2 3". This code will return 0, but 2+3 is a prime.
You could fix it by also allowing an extra recursion case where the first odd number is discarded without reducing the even list.
del newOdds[0]
n=max(n,findPairs(newOdds, newEvens, pairDict)) # added line
del newEvens[i]

Optimising code for finding the next prime number

I'm new to both Python and StackOverflow so I apologise if this question has been repeated too much or if it's not a good question. I'm doing a beginner's Python course and one of the tasks I have to do is to make a function that finds the next prime number after a given input. This is what I have so far:
def nextPrime(n):
num = n + 1
for i in range(1, 500):
for j in range(2, num):
if num%j == 0:
num = num + 1
return num
When I run it on the site's IDE, it's fine and everything works well but then when I submit the task, it says the runtime was too long and that I should optimise my code. But I'm not really sure how to do this, so would it be possible to get some feedback or any suggestions on how to make it run faster?
When your function finds the answer, it will continue checking the same number hundreds of times. This is why it is taking so long. Also, when you increase num, you should break out of the nested loop to that the new number is checked against the small factors first (which is more likely to eliminate it and would accelerate progress).
To make this simpler and more efficient, you should break down your problem in areas of concern. Checking if a number is prime or not should be implemented in its own separate function. This will make the code of your nextPrime() function much simpler:
def nextPrime(n):
n += 1
while not isPrime(n): n += 1
return n
Now you only need to implement an efficient isPrime() function:
def isPrime(x):
p,inc = 2,1
while p*p <= x:
if x % p == 0: return False
p,inc = p+inc,2
return x > 1
Looping from 1 to 500, especially because another loop runs through it, is not only inefficient, but also confines the range of the possible "next prime number" that you're trying to find. Therefore, you should make use of while loop and break which can be used to break out of the loop whenever you have found the prime number (of course, if it's stated that the number is less than 501 in the prompt, your approach totally makes sense).
Furthermore, you can make use of the fact that you only need check the integers less than or equal to the square root of the designated integer (which in python, is represented as num**0.5) to determine if that integer is prime, as the divisors of the integers always come in pair and the largest of the smaller divisor is always a square root, if it exists.

Understanding recursive odd/even functions

I'm currently studying python from http://www.sololearn.com/Play/Python and I'm having trouble understanding why this code works.
def is_even(x):
if x == 0:
return True
else:
return is_odd(x-1)
def is_odd(x):
return not is_even(x)
print(is_odd(1))
I get how recursion works for a fibonacci and factorial but I can't wrap my head around this one.
is_even's base case resolves to True. Since is_odd(x) returns not is_even(x), the value True will be a part of the expression returned by is_odd. The question is how many times will that True value be negated. By tracing the calls you can see it will be negated an even number of times, and hence "retain" its truthiness, when x is odd [e.g.: x=3 ==> (not (not (not (not True)))) == True] and an odd number of times, and hence "lose" its truthiness, when x is even [e.g.: x=2 ==> (not (not (not True))) == False]. There's probably some term from logic that names this general property of multiple negation.
It's based on an inductive definition of evenness:
Zero is even
If some number "n" is even, then "n+1" is not even
If some number "n" is not even, then "n+1" is even
"odd" is obviously "not even".
The code takes this definition, and checks it backwards - using recursion.
If i have zero, then it is even
If I have some other number "n" , then it is even if "n-1" is not - that is, if "n-1" is odd.
That recursive function is really a bad way to teach recursion, you should apply recursion only when it's useful. In fact, test those functions with negative numbers and you'll get RuntimeError: maximum recursion depth exceeded errors.
To check parity numbers you'd better use % operator or & and operator, ie:
def is_even(x):
return (x & 1) == 0
def is_odd(x):
return (x & 1) == 1
That said, I think #Elazar & #DAXaholic answers should give you some insights about that buggy recursive function and wrap your mind about it.
A little hint:
0 -> True
1 -> not True
2 -> not not True
3 -> not not not True
...
and so on.

python: checking if a number is prime, specifying range

I have a problem with a this piece of code that I'm writing to check if a number is prime.
import sys
import math
def is_prime(num):
for j in range(2,(int(math.sqrt(num)+1))):
if (num % j) == 0:
return False
else:
return True
for a in range(1,10):
if is_prime(a):
print a
What I get is: 5, 7, 9
I don't understand why is 3 excluded? I went back to the first portion of the code and tried is_prime(3), but it returned me neither True nor False. Does this mean that 3 is outside the range of divisors I'm checking? How should I correct the code such that 3 is included in my list of primes?
Edit:
Hello again, thanks for the answers so far, so I've tried to solve the problem of truncation using int(round()). I've also tried putting the else block outside the loop, but it doesn't seem to work. Can anyone please explain why this is insufficient and suggest how I should correct it so it works? Thanks in advance! :)
import sys
import math
def is_prime(num):
for j in range(2,int(round(math.sqrt(num)+1)):
if (num % j) == 0:
return False
return True
Your function returns True as soon as it sees that the number is not divisible by any j. It should only return True if the number is not divisible by all j.
As a side-effect of fixing this bug, you'll also fix the bug whereby your function sometimes returns None (for example, when num is 3).
int() truncates, not rounds, so int(math.sqrt(3) + 1) == 2. range(2, 2) is empty, so nothing will be returned.
Another problem is that your else block is inside of the loop. If you test the first 100 numbers, you will quickly notice that your is_prime function will return True for any odd number.
The square root of 3 is less than 2, so the loop is never entered and nothing is returned.

Python 3: Recursivley find if number is even

I am writing a program that must find if a number is even or not. It needs to follow this template. I can get it to find if a number is even or not recursively
The key is that you need to return a boolean value:
def isEven(num):
if (num <= 0):
return (num == 0)
return isEven(num-2)
For larger numbers though this quickly exceeds the default maximum recursion depth for Python. That can be remedied by calling sys.setrecursionlimit(n) where n is the number of recursive calls you want to allow. n in turn is limited by the platform you are on.
Try this, it works for integer values with 0 <= n <= sys.getrecursionlimit()-2:
def even(n):
return True if n == 0 else odd(n - 1)
def odd(n):
return False if n == 0 else even(n - 1)
It's a nice example of a pair of mutually recursive functions. Not the most efficient way to find the answer, of course - but nevertheless interesting from an academic point of view.
This template will help. You need to fill in the commented lines. The one you have in the question won't work - you aren't passing anything into isEven. This will only work if n >= 0, otherwise it will crash your program. Easy enough to fix if you ever need to deal with negative numbers.
def isEven(n):
if n == 0:
# Number is even
elif n == 1:
# Number is odd
else:
# Call the function again, but with a different n
Taking up wim's challenge to find a "different" way to do this: The prototypical recursive pattern is foo(cdr(x)), with a base case for the empty list… so let's write it around that:
def isEven(num):
def isEvenLength(l):
if not l:
return True
return not isEvenLength(l[1:])
return isEvenLength(range(num))
A really dumb use case for recursion, but here is my version anyway
import random
def isEven(num):
if random.random() < 0.5:
# let's learn about recursion!
return isEven(num)
else:
# let's be sane!
return num % 2 == 0
disclaimer: if you submitted this you'd probably tick off the teacher and come across as a smartypants.

Categories