checking integer overflow in python - 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

Related

Asserting that a number is in binary

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

How to reorder digits of a number and insert digit 5 to get the maximum possible absolute value

Please advise how I can reorder digits of a number and add a digit 5 to the result so that its absolute value will be the highest.
For example, if the input is 578 the expected result is 8755. Otherwise, if the input is negative -483, the output is expected to be -8543.
I've managed to make it work on positive numbers only, however, I need to make it work for negative numbers as well:
def solution(N):
a = [] # list of digits, e.g. int(123)
while N != 0:
v = N % 10 # last digit as div remainder, e.g.: 123 % 10 = 3
N = int(N / 10) # remove last digit using integer division: 123 / 10 = 12.3; int(12.3) = 12
a = [v] + a # concatenate two lists: newly created list with one element (v = 3) and list a
# as a result the digits will be in natural order => [1,2,3]
if len(a) == 0: # need to create list with one element [0] as the cycle before ignores 0
a = [0]
inserted = False
for i in range(0, len(a)): # i = 0, 1, 2; len = 3
if a[i] < 5:
# a[from:to exclusive] e.g.: [1, 2, 3][0:2] => [1, 2]. index of 1 is 0, index of 2 is 1, index 2 is excluded
a = a[0:i] + [5] + a[i:]
inserted = True
break
if not inserted:
a = a + [5]
N = 0 # reconstruct number from digits, list of digits to int
for i in range(0, len(a)):
N = N * 10 + a[i] # 0 + 1; 1 * 10 + 2; 12 * 10 + 3 = 123
return N
if __name__ == ‘__main__’:
print(“Solution:”, solution(0))
here i made some major changes by using some inbuilt python methods :
def solution(N):
sign = False #to determine the sign of N (positive or negative )
if N < 0:
sign = True
N= N * -1 # as N<0 we make it positive
a = []
while N != 0:
v = N % 10
N = int(N / 10)
a = [v] + a
a.append(5) # in built method to add an element at the end of the list
a.sort() # in built method to sort the list (ascending order)
a.reverse() # in build method to reverse the order of list (make it descending order)
N = 0
for i in range(0, len(a)):
N = N * 10 + a[i]
if sign: # convert negative integers back to negative
N = N * -1
return N
Sample output :
for negative
solution(-2859)
-98552
positive
solution(9672)
97652
If you need to insert 5 and to make the output number the maximum number both for negative and positive numbers (and without the condition to not replace or transform the input set of digits), then this may be a solution:
def solution(N):
negative = False
if N < 0:
negative = True
N = N * -1 # as N<0 we make it positive
a = []
while N != 0:
v = N % 10
N = int(N / 10)
a = [v] + a
if len(a) == 0:
a = [0]
inserted = False
for i in range(0, len(a)):
if (not negative and a[i] < 5) or (negative and a[i] > 5):
a = a[0:i] + [5] + a [i:]
inserted = True
break
if not inserted:
a = a + [5]
N = 0
for i in range(0, len(a)):
N = N * 10 + a[i]
if negative:
N = N * -1
return N
if __name__ == '__main__':
print("Solution:", solution(N))
Will the below do the trick:
x=-34278
no_to_insert=5
res=int(''.join(sorted(list(str(abs(x)))+[str(no_to_insert)], reverse=True)))
if x<0:
res=-res
Output:
-875432
Java Solution
public int solution(int N) {
int digit = 5;
if (N == 0) return digit * 10;
int neg = N/Math.abs(N);
N = Math.abs(N);
int n = N;
int ctr = 0;
while (n > 0){
ctr++;
n = n / 10;
}
int pos = 1;
int maxVal = Integer.MIN_VALUE;
for (int i=0;i<=ctr;i++){
int newVal = ((N/pos) * (pos*10)) + (digit*pos) + (N%pos);
if (newVal * neg > maxVal){
maxVal = newVal*neg;
}
pos = pos * 10;
}
return maxVal;
}

Narcissistic numbers in Python

I am beginner to the Python programming language and I have been using a website to help me exercise. It gave me this challenge to make a program that returns true if a given number is narcissistic or false otherwise.
Examples of narcissistic numbers:
153 (3 digits): 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
1634 (4 digits): 1^4 + 6^4 + 3^4 + 4^4 = 1 + 1296 + 81 + 256 = 1634
But for some reason when the number 371 is given the function returns False instead of True.
The code:
def narcissistic(value):
logical = True
logical2 = True
i = 0
j = 0
notation = 10
sum = 0
#Calculating the number notation
while logical:
if 10 ** i <= value:
notation = 10 ** i
i = i + 1
else:
logical = False
#i from now on is also the qauntity of digits
while logical2:
if ( notation / 10 ** j ) >= 1:
sum = sum + ( value // ( notation / 10 ** j ) ) ** i
j = j + 1
else:
logical2 = False
if sum == value:
return True
else:
return False
Your code is very close! The issue lies here:
sum = sum + ( value // ( notation / 10 ** j ) ) ** i
For 1634, this multiplies 1, 16, 163, and 1634. You need only the LSB of these numbers, in this example 1, 6, 3, and 4 - use the modulo operator to get this. If we mod them by 10 to get only the LSB...
sum = sum + (( value // ( notation / 10 ** j ) ) % 10) ** i
...then the code works perfectly.
Demo
It would probably be easier to do this task by converting the value to a string and back. Taking the length of the string is an easy way to get the number of digits ("the poor man's logarithm"), and you can easily iterate over individual digits:
def narcissistic(value):
str_value = str(value)
num_digits = len(str_value)
return (value == sum(int(digit) ** num_digits for digit in str_value))
>>> narcissistic(153)
True
>>> narcissistic(1634)
True
>>> narcissistic(371)
True
>>> narcissistic(372)
False
Could grab individual digits without converting to string
import math
def narcissistic(value):
n = math.floor(math.log10(value)) + 1
x = [math.floor((value/10**i)%10)**n for i in range(n)]
print(sum(x) == value)
narcissistic(371)
#True
change ^ to **
def narcissistic(number):
number_string = str(number)
number_len = len(number_string)
number_nar = 0
for char in number_string:
number_nar+= int(char) ** number_len
return number_nar
number = 153
number_nar = narcissistic(number)
print(number_nar)
number = 1634
number_nar = narcissistic(number)
print(number_nar)
output:
153
1634
This can be solved using list comprehension in 1 line of code.
def Narcissistic(x):
y = sum([int(i)**(len(x)) for i in (x)])
return Narcissistic(x)

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.

How to divide with a loop? (Python)

I am trying to write a function to determine if a number is prime. I have come up with
the following solution, however inelegant, but cannot figure out how to write it.
I want to do the following: take the number x and divide it by every number that is less than itself. If any solution equals zero, print 'Not prime.' If no solution equals zero, print 'Prime.'
In other words, I want the function to do the following:
x % (x - 1) =
x % (x - 2) =
x % (x - 3) =
x % (x - 4) =
etc...
Here is as far as I have been able to get:
def prime_num(x):
p = x - 1
p = p - 1
L = (x % (p))
while p > 0:
return L
Wikipedia provides one possible primality check in Python
def is_prime(n):
if n <= 3:
return n >= 2
if n % 2 == 0 or n % 3 == 0:
return False
for i in range(5, int(n ** 0.5) + 1, 6):
if n % i == 0 or n % (i + 2) == 0:
return False
return True

Categories

Resources