Asserting that a number is in binary - python

Im working on my homework and encountered a problem. I had to string numbers in binary back to back.
Lets say we have joined(1, 3) - 1 is the starting number and 3 says that Im gonna work with 2 more numbers (if i had joined(5, 4), id work with 5, 6, 7 and 8)
1 1
2 10
3 11
result 11011
def num_to_2(number):
num2 = 0
exp = 0
while number >= 1:
num2 += (number % 2) * (10 ** exp)
number = number // 2
exp += 1
return num2
def num_lenght(number):
if number == 0:
return 0
lenght = 0
while number >= 1:
number /= 10
lenght += 1
return lenght
def joined(start, count):
result = 0
end = start + count - 1
for i in range(end, start - 1, -1):
number = num_to_2(i)
res_lenght = num_lenght(result)
result += number * (10 ** res_lenght)
return result
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111
The function works properly but it gives me results without the 0b prefix, which i need in order to pass the asserts. How do i add it there? and also: i cant use strings.
Thanks in advance!
Edit: i added the rest of my code so it makes more sense

I already solved my problem, what i had to do was "manually" convert the pseudo-binary number into base 10 number. this is my code now:
def convert_to_2(number):
num2 = 0
exp = 0
while number >= 1:
num2 += (number % 2) * (10 ** exp)
number = number // 2
exp += 1
return num2
def num_lenght(number):
if number == 0:
return 0
lenght = 0
while number >= 1:
number /= 10
lenght += 1
return lenght
def joined(start, count):
result = 0
end = start + count - 1
for i in range(end, start - 1, -1):
number = convert_to_2(i)
res_lenght = num_lenght(result)
result += number * (10 ** res_lenght)
result = convert_to_10(result)
return result
def convert_to_10(number):
num10 = 0
exp = 0
while number >= 1:
num10 += (number % 10) * (2 ** exp)
number = number // 10
exp += 1
return num10
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111
if __name__ == "__main__":
main()
thank you so much for your help(:

Here is a bit-shifting version which passes all assertions:
from math import ceil, log2
from functools import reduce
def join2(a,b):
n = ceil(log2(b+1))
return (a<<n) | b
def joined(start, count):
return reduce(join2,range(start,start+count))
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111

Well, it's unclear what your teachers mean with "don't use strings". I found this a very strange homework, so I did it, without strings.
I'm not sure what you are supposed to learn from it, but here it is:
def to_binary(number):
b = 0
while number >= 2**(b+1):
b += 1
while True:
if number >= 2**b:
yield 1
number -= 2**b
else:
yield 0
b -= 1
if b < 0:
return
def joined(start, count):
result = 0
for i in range(start, start + count):
for digit in to_binary(i):
result = (result << 1) + digit
return result
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111
It implements a to_binary() function that will yield a sequence of integers. Then the join function will binary shift the result to the left, and add that one or zero.
No strings attached...

You don't need to worry about the 0b prefix, it is merely a way to express numeric literals in Python source code. They could have written 27 or 0x1b instead of 0b11011 but the binary form makes it clearer what bit pattern is expected in the integer value returned by joined().
You can use the integer's .bit_length() method to know how many bits are used to represent a number. This should make the function a bit simpler.
def joined(start,count):
result = 0
for n in range(start,start+count):
result <<= n.bit_length() # offset by the number of bits
result |= n # add the number's bits
return result
if you're not allowed to use that method, you can write your own function to do it:
def bitLength(N): return 0 if not N else bitLength(N//2)+1
If you're also not allowed to use bit-wise operators, you can do it with multiplications and additions:
def joined(start,count):
result = 0
for n in range(start,start+count):
result *= 2**bitLength(n) # offset by the number of bits
result += n # add the number's bits
return result

Related

Infinite continued Fraction in Python

I am currently trying to implement a function that approximate the e constant in Python.
from fractions import Fraction
def fractionalSum(number, array):
def inside(index, place):
if place >= 0:
return Fraction(1, index + place)
else:
return Fraction(1, index)
if number == 0:
return 0
elif number == 1:
return inside(array[number - 1], 0)
elif number == 2:
return inside(1, fractionalSum(number - 1, array))
elif number == 88:
return inside(array[0], inside(array[1], inside(array[2], inside(array[3], inside(array[4], 0)))))
else:
return inside(fractionalSum(number - 2, array), inside(fractionalSum(number - 1, array), 0))
expansion = [1]
it = 1
clock = 0
for i in range(1, 110):
if clock == 0:
expansion.append(2 * it)
it += 1
clock = 2
if clock != 0:
expansion.append(1)
clock -= 1
print(expansion)
print(2 + fractionalSum(3, expansion))
I am currently trying recursion to calculate it but the code is not producing the correct results.
In the fractionalsum function having number 2 should call the same function with number-1 but the results is wrong.
number = 88 produces the correct value for number 5. I am trying to implement it recursively to approximate it with numbers > 50.
I haven't investigated what exactly you may have done wrong, but a recursive implementation of Continued Fraction should be fairly simple, so I'm suggesting this instead:
ONE = Fraction(1, 1)
def continuedFraction(array):
return _continuedFraction(array, 0)
def _continuedFraction(array, index):
result = Fraction(array[index], 1)
if index + 1 < len(array):
return result + ONE / _continuedFraction(array, index + 1)
return result

Implementing memoization within a Collatz algorithm (Python)

I am trying to perform a Collatz algorithm on the following code. It works fine when I use a range of 1-10 etc... However, if the range is for example 1-500,000 it's too slow and won't ever show me the output of the longest sequence.
numberArray = []
s=int(1)
f=int(10)
def collatz(n):
global count
if n == 1:
count += 1
numberArray.append(count)
return True
elif (n % 2) == 0:
count += 1
collatz(n/2)
else:
count += 1
collatz(3*n+1)
for i in range (s, f+1):
count = 0
ourNumber = i
collatz(i)
print(max(numberArray))
Stef means something like this, which uses a dictionary to memorise the values that have already been counted:
s = 1
f = 10000000
def collatz(n):
if n in collatz.memory:
return collatz.memory[n]
if (n % 2) == 0:
count = collatz(n//2)+1
else:
count = collatz((3*n+1)//2)+2
collatz.memory[n] = count
return count
collatz.memory = {1:0}
highest = max(collatz(i) for i in range(s, f+1))
highest_n = max(collatz.memory, key=collatz.memory.get)
print(f"collatz({highest_n}) is {highest}")
Output:
collatz(8400511) is 685
Use lru_cache decorator. Its function to memorize (cache) the returned value of function called with specific argument.
Also read how to write clean code in python
The next code solves your problem
from functools import lru_cache
number_array = []
s = 1
f = 500000
#lru_cache
def collatz(n: int):
if n == 1:
return 1
elif n % 2 == 0:
return 1 + collatz(n // 2)
else:
return 1 + collatz(3 * n + 1)
for i in range(s, f + 1):
number_array.append(collatz(i))
print(number_array)

Why classical division ("/") for large integers is much slower than integer division ("//")?

I ran into a problem: The code was very slow for 512 bit odd integers if you use classical division for (p-1)/2. But with floor division it works instantly. Is it caused by float conversion?
def solovayStrassen(p, iterations):
for i in range(iterations):
a = random.randint(2, p - 1)
if gcd(a, p) > 1:
return False
first = pow(a, int((p - 1) / 2), p)
j = (Jacobian(a, p) + p) % p
if first != j:
return False
return True
The full code
import random
from math import gcd
#Jacobian symbol
def Jacobian(a, n):
if (a == 0):
return 0
ans = 1
if (a < 0):
a = -a
if (n % 4 == 3):
ans = -ans
if (a == 1):
return ans
while (a):
if (a < 0):
a = -a
if (n % 4 == 3):
ans = -ans
while (a % 2 == 0):
a = a // 2
if (n % 8 == 3 or n % 8 == 5):
ans = -ans
a, n = n, a
if (a % 4 == 3 and n % 4 == 3):
ans = -ans
a = a % n
if (a > n // 2):
a = a - n
if (n == 1):
return ans
return 0
def solovayStrassen(p, iterations):
for i in range(iterations):
a = random.randint(2, p - 1)
if gcd(a, p) > 1:
return False
first = pow(a, int((p - 1) / 2), p)
j = (Jacobian(a, p) + p) % p
if first != j:
return False
return True
def findFirstPrime(n, k):
while True:
if solovayStrassen(n,k):
return n
n+=2
a = random.getrandbits(512)
if a%2==0:
a+=1
print(findFirstPrime(a,100))
As noted in comments, int((p - 1) / 2) can produce garbage if p is an integer with more than 53 bits. Only the first 53 bits of p-1 are retained when converting to float for the division.
>>> p = 123456789123456789123456789
>>> (p-1) // 2
61728394561728394561728394
>>> hex(_)
'0x330f7ef971d8cfbe022f8a'
>>> int((p-1) / 2)
61728394561728395668881408
>>> hex(_) # lots of trailing zeroes
'0x330f7ef971d8d000000000'
Of course the theory underlying the primality test relies on using exactly the infinitely precise value of (p-1)/2, not some approximation more-or-less good to only the first 53 most-significant bits.
As also noted in a comment, using garbage is likely to make this part return earlier, not later:
if first != j:
return False
So why is it much slower over all? Because findFirstPrime() has to call solovayStrassen() many more times to find garbage that passes by sheer blind luck.
To see this, change the code to show how often the loop is trying:
def findFirstPrime(n, k):
count = 0
while True:
count += 1
if count % 1000 == 0:
print(f"at count {count:,}")
if solovayStrassen(n,k):
return n, count
n+=2
Then add, e.g.,
random.seed(12)
at the start of the main program so you can get reproducible results.
Using floor (//) division, it runs fairly quickly, displaying
(6170518232878265099306454685234429219657996228748920426206889067017854517343512513954857500421232718472897893847571955479036221948870073830638539006377457, 906)
So it found a probable prime on the 906th try.
But with float (/) division, I never saw it succeed by blind luck:
at count 1,000
at count 2,000
at count 3,000
...
at count 1,000,000
Gave up then - "garbage in, garbage out".
One other thing to note, in passing: the + p in:
j = (Jacobian(a, p) + p) % p
has no effect on the value of j. Right? p % p is 0.

How to write 2**n - 1 as a recursive function?

I need a function that takes n and returns 2n - 1 . It sounds simple enough, but the function has to be recursive. So far I have just 2n:
def required_steps(n):
if n == 0:
return 1
return 2 * req_steps(n-1)
The exercise states: "You can assume that the parameter n is always a positive integer and greater than 0"
2**n -1 is also 1+2+4+...+2n-1 which can made into a single recursive function (without the second one to subtract 1 from the power of 2).
Hint: 1+2*(1+2*(...))
Solution below, don't look if you want to try the hint first.
This works if n is guaranteed to be greater than zero (as was actually promised in the problem statement):
def required_steps(n):
if n == 1: # changed because we need one less going down
return 1
return 1 + 2 * required_steps(n-1)
A more robust version would handle zero and negative values too:
def required_steps(n):
if n < 0:
raise ValueError("n must be non-negative")
if n == 0:
return 0
return 1 + 2 * required_steps(n-1)
(Adding a check for non-integers is left as an exercise.)
To solve a problem with a recursive approach you would have to find out how you can define the function with a given input in terms of the same function with a different input. In this case, since f(n) = 2 * f(n - 1) + 1, you can do:
def required_steps(n):
return n and 2 * required_steps(n - 1) + 1
so that:
for i in range(5):
print(required_steps(i))
outputs:
0
1
3
7
15
You can extract the really recursive part to another function
def f(n):
return required_steps(n) - 1
Or you can set a flag and define just when to subtract
def required_steps(n, sub=True):
if n == 0: return 1
return 2 * required_steps(n-1, False) - sub
>>> print(required_steps(10))
1023
Using an additional parameter for the result, r -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r * 2)
for x in range(6):
print(f"f({x}) = {required_steps(x)}")
# f(0) = 0
# f(1) = 1
# f(2) = 3
# f(3) = 7
# f(4) = 15
# f(5) = 31
You can also write it using bitwise left shift, << -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r << 1)
The output is the same
Have a placeholder to remember original value of n and then for the very first step i.e. n == N, return 2^n-1
n = 10
# constant to hold initial value of n
N = n
def required_steps(n, N):
if n == 0:
return 1
elif n == N:
return 2 * required_steps(n-1, N) - 1
return 2 * required_steps(n-1, N)
required_steps(n, N)
One way to get the offset of "-1" is to apply it in the return from the first function call using an argument with a default value, then explicitly set the offset argument to zero during the recursive calls.
def required_steps(n, offset = -1):
if n == 0:
return 1
return offset + 2 * required_steps(n-1,0)
On top of all the awesome answers given earlier, below will show its implementation with inner functions.
def outer(n):
k=n
def p(n):
if n==1:
return 2
if n==k:
return 2*p(n-1)-1
return 2*p(n-1)
return p(n)
n=5
print(outer(n))
Basically, it is assigning a global value of n to k and recursing through it with appropriate comparisons.

checking integer overflow in python

class Solution(object):
def reverse(self, x):
"""
:type x: int
:rtype: int
"""
negative = False
if(x < 0):
x = x * -1
negative = True
else:
x = x
sum = 0
dig = 1
strX = str(x)
lst = list(strX)
for i in lst:
sum += int(i) * dig
dig *= 10
if(abs(sum) > 2 ** 32):
return 0
elif(negative == True):
return sum * -1
else:
return sum
This is a leetcode problem that asks us to reverse an integer. I know it's a dirty code but it still works but it does not return 0 when the reversed integer overflows. I tried to check that on the line
if(abs(sum) > 2 ** 32):
return 0
but one of the test cases gives me:
Input: 1563847412
Output: 2147483651
Expected: 0
First, I am not sure why this overflows, and I am not sure how to fix this.
Thanks!
change if(abs(sum) > 2 ** 32): to if(abs(sum) > (2 ** 31 - 1)): or abs(sum) > (1 << 31) - 1): The largest 32 bit signed interger is actually not 2^32 but (2 ^ (31)) -1). because we need one bit reserve as the sign bit.
Read about it here of why The number 2,147,483,647 (or hexadecimal 7FFF,FFFF) is the maximum positive value for a 32-bit signed binary integer
I guess some thing light weight like below could perhaps achieve the same logic, For someone else looking , the main overflow check after reversed 32 bit int is
if(abs(n) > (2 ** 31 - 1)):
return 0
Full code below
def reverse(self, x):
neg = False
if x < 0:
neg = True
x = x * -1
s = str(x)[::-1]
n = int(s)
if neg:
n = n*-1
if(abs(n) > (2 ** 31 - 1)):
return 0
return n
The largest 32-bit signed integer is (1 << 31) - 1 which is (2**31)-1 but not (2**32).
Try This way :
class Solution(object):
def reverse(self, x):
"""
:type x: int
:rtype: int
"""
negative = False
if (x < 0):
x = x * -1
negative = True
else:
x = x
sum = 0
dig = 1
strX = str(x)
lst = list(strX)
for i in lst:
sum += int(i) * dig
dig *= 10
if (abs(sum) > ((1 << 31) - 1)): #use (1 << 31) - 1) instead of 2 ** 32
return 0
elif (negative == True):
return sum * -1
else:
return sum
if __name__ == '__main__':
x = 1563847412
sol = Solution().reverse(x)
print(sol)
Output :
0
class Solution:
def reverse(self, x: int) -> int:
split = [i for i in str(x)]
split = split[::-1]
final = ''
if split[-1]=='-':
final += '-'
for i in split[0:-1]:
print(i)
final+=i
else:
for i in split[0:]:
final+=i
final = int(final)
if(abs(final) > (2 ** 31 - 1)):
return 0
return(final)
you can simply use:
if sum >= pow(2,31)-1:
return 0
if sum > ((1 << 31) - 1):
return 0
else:
if negative == True:
sum = -sum
return sum

Categories

Resources