Generating sequence of numbers with recursion python - python-3.x

The goal is to generate catalan numbers ! my code works up to n = 30 (i tried the same algorithm in JAVA and it's totally correct,but, then something strange happens with python , it gives wrong numbers back after n=30. I'm totally sure that there is an issue about rounding or maybe formats, but can't figure it out by myself!
def catalan(n):
if n < 0:
return -1
else:
if n == 0:
return 1
else:
c_n = (4*n-2)/(n+1)*catalan(n-1)
return int(c_n)

By using /(n+1) you produce a floating point number, which by its nature has a limited precision. This precision is not accurate enough for the larger numbers that appear with n > 30.
So instead, use a formula that sticks with integer numbers: first multiply and only then perform the division, an integer division:
c_n = (4*n-2)*catalan(n-1)//(n+1)
The cast to int is then also unnecessary, and you can just do:
return c_n
Side note: you don't need else when you return in the if part of the statement. So you can write:
def catalan(n):
if n < 0:
return -1
if n == 0:
return 1
return (4*n-2)*catalan(n-1)//(n+1)

Related

2^n question (it didn't work on large numbers)

a power of two is a number of the form 2n where n is an integer, i.e. the result of exponentiation with number two as the base and integer n as the exponent.
i want to test a power of two number.For example if i input 128 program input should be True because 128=2^7
so i wrote this code:
import math
def power_of_two(x):
if(x==0):
print ("False")
return False
else:
n = math.log2(x)
if n%1 > 0:
return False
else:
return True
but in this code if i try for example 4096 it works well but if i try larger numbers,for example 4722366482869645213702 it didn't work it output True(should be False)
how can i fix this problem??
def power_of_two(x):
return x > 0 and (x & (x-1)) == 0
Explanation.
Powers of 2 look like
10000000000000000000
After subtraction of 1 they look like
01111111111111111111
Bitwise and of these numbers is 0. For other positive numbers it's false.
A simple solution is to convert the number to its binary form, using bin then test if the first digit is a 1 and all others are 0.
def is_a_power_of_two(x):
if x == 1:
return True
b = bin(x)[2:]
return int(b[0]) == 1 and int(b[1:]) == 0
That's not very fast, but if performances are not an issue for you then it's just fine.
You can test that there are no false negatives using this:
for i in range(100):
assert is_a_power_of_two(2**i)

Python 3, any better/cleaner way to write these functions that use for loops?

I'm trying to write code in the most simplest and cleanest way possible. I've found a few ways to shorten and simplify my code through functions that I've never seen before or through using other methods. I'd like to expand my knowledge on writing code using various (but simple) methods, and also expand my function 'vocabulary'.
Here are the functions:
1. Perfect number:
If a number's divisors' sum is equal to the number itself, it is a perfect number. We dont count the number itself as a divisor. E.g. 6's divisors are 1, 2, 3. The sum of the divisors is 6. Therefore 6 is a perfect number.
def perfect_number(num):
if type(num) != int or num < 0:
return None
divisors = []
total = 0
for x in range(num):
if num % (x+1) == 0:
if num != x+1:
divisors += [x+1]
for x in divisors:
total += x
if total == num:
return True
return False
2. Pattern:
A function that takes a positive integer and prints a pattern as follows:
pattern(1): '#-'
pattern(2): '#-#--'
pattern(5): '#-#--#---#----#-----'
def pattern(num):
if type(num) != int or num < 0:
return None
output = ''
for x in range(num):
output += '#'+('-'*(x+1))
return output
3. Reversed Numbers:
A function that takes 2 integers. It goes through every number in the range between those 2 numbers, if one of those numbers is a palindrome (the same thing backwards e.g. 151 is a 'palindrome'), it will increase a variable by 1. That variable is then returned.
invert_number(num) returns the opposite of num as an integer.
def reversed_numbers(low, high):
output = 0
for x in range(low,high+1):
if invert_number(x) == x:
output += 1
return output
It is assumed that low is lower than high.
If I broke a rule or if this doesnt fit here, please tell me where I can post it/how I can improve. Thanks :)

How to handle negative cases for prime check in Python?

With regard to the "xrange" function - ("range" in Python3) what happens when I do a negative check inside a loop? In this case, a negative number could be regarded as an edge case, but always returns None. Any insights?
The problem is you are checking if the number is negative inside the for loop. For instance if x=-3, then you are trying to run a for loop in range(2,-1) which is None. So the for loop never runs and hence returns True.
def isprime(x):
if x<=0:
return(False)
for a in range(2,(x//2)+1):
if(x%a==0):
return(False)
return(True)
By it's elementary school definition, prime numbers are defined for positive numbers only, thus your function should return False for every negative number, for example:
def isprime(x):
if x <= 0:
return False
for a in range(2, (x//2)+1):
if x % a == 0:
return False
return True
That being said, it is possible to extend the definition (as done in some fields in math), to include negative numbers as well (for further discussion see here and here). In this case, for every negative number -n, -n is prime iff n is prime. Therefore your code could be something like:
def isprime(x):
if x <= 0: # or use any |abs| method you'd like, like numpy's
x = -x
for a in range(2, (x//2)+1):
if x % a == 0:
return False
return True

Wrong output binary search program

In writing a BinarySearch program, I've written the program:
def binary_search(array, x, low=0, high=None):
if high is None:
high = len(array)
while low < high:
mid = (low+high)//2
midval = array[mid]
if midval < x:
low = mid+1
elif midval > x:
high = mid
else:
return mid
return -1
When I put the following:
binary_search([1,2,2,3],2)
the output given by the program is
2
However, I would like the program to give as output the index of the first integer 'x' it finds. So in the previous example it would be '1' instead of '2'. Any idea on how I can alter this?
You need to remove the early out (the final else condition), replacing the prior elif with a straight else; only when the loop terminates do you test for equality and choose to return the index found or -1 if it wasn't found:
def binary_search(array, x, low=0, high=None):
if high is None:
high = len(array)
while low < high:
mid = (low+high)//2
if array[mid] < x:
low = mid+1
else:
high = mid
return -1 if low >= len(array) or array[low] != x else low
It's also a good idea to behave this way because in general, you don't want to perform multiple comparisons per loop (< and > would each invoke comparisons, which could be expensive depending on the type); simplifying to exactly one non-numeric comparison per loop saves time (and often runs faster; Python libraries often hand implement < and ==, and use wrappers to implement the other comparators in terms of < and ==, making them slower).
This is actually what bisect.bisect_left does in its pure Python implementation; it's otherwise nearly identical to your code. It makes it take longer, because it's more likely to take the full log(n) steps to identify the left most instance of a value, but the incremental cost is usually going to be small unless your input has many repeated values.
Given [1,2,2,3] the line mid = (low+high)//2 is evaluated for the first run as:
mid = (0 + 4) // 2 ==> 2
Than array[mid] satisfies the condition (its value is exactly 2), and the index returned is mid (2).
if midval < x:
...
elif midval > x:
...
else:
return mid

11+ digit ints not working

I'm using python 3 for a small extra credit assignment to write an RSA cracker. The teacher has given us a fairly large (large enough to require more than 32 bits) int and the public key. My code works for primes < 32 bits. One of the reasons I chose python 3 is because I heard it can handle arbitrarily large integers. In the python terminal I tested this by doing small things such as 2**35 and factorial(70). This stuff worked fine.
Now that I've written the code, I'm running in to problems with overflow errors etc. Why is it that operations on large numbers seem to work in the terminal but won't work in my actual code? The errors state that they cannot be converted to their C types, so my first guess would be that for some reason the stuff in the python interpreter is not being converter to C types while the coded stuff is. Is there anyway to get this working?
As a first attempt, I tried calculating a list of all primes between 1 and n (the large number). This sort of worked until I realized that the list indexers [ ] only accept ints and explode if the number is higher than int. Also, creating an array that is n in length won't work if n > 2**32. (not to mention the memory this would take up)
Because of this, I switched to using a function I found that could give a very accurate guess as to whether or not a number was prime. These methods are pasted below.
As you can see, I am only doing , *, /, and % operations. All of these seem to work in the interpreter but I get "cannot convert to c-type" errors when used with this code.
def power_mod(a,b,n):
if b < 0:
return 0
elif b == 0:
return 1
elif b % 2 == 0:
return power_mod(a*a, b/2, n) % n
else:
return (a * power_mod(a,b-1,n)) % n
Those last 3 lines are where the cannot convert to c-type appears.
The below function estimates with a very high degree of certainty that a number is prime. As mentioned above, I used this to avoid creating massive arrays.
def rabin_miller(n, tries = 7):
if n == 2:
return True
if n % 2 == 0 or n < 2:
return False
p = primes(tries**2)
if n in p:
return True
s = n - 1
r = 0
while s % 2 == 0:
r = r+1
s = s/2
for i in range(tries):
a = p[i]
if power_mod(a,s,n) == 1:
continue
else:
for j in range(0,r):
if power_mod(a, (2**j)*s, n) == n - 1:
break
else:
return False
continue
return True
Perhaps I should be more specific by pasting the error:
line 19, in power_mod
return (a * power_mod(a,b-1,n)) % n
OverflowError: Python int too large to convert to C double
This is the type of error I get when performing arithmetic. Int errors occur when trying to create incredibly large lists, sets etc
Your problem (I think) is that you are converting to floating point by using the / operator. Change it to // and you should stay in the int domain.
Many C routines still have C int limitations. Do your work using Python routines instead.

Resources