Checking Powers of Four - Edge Case - python

Disclosure: This question is from codewars.
Write a method that returns true if a given parameter is a power of 4, and false if it's not. If parameter is not an Integer (eg String, Array) method should return false as well.
I cannot for the life of me figure out what edge case I'm missing. Both code samples produce the same error that 'True should equal False' for some test. (I tried it two ways when the first didn't work, since I was positive the second would.)
def powerof4(n):
if n <= 0 or not isinstance(n, int): return False
else:
while (n != 1):
if (n%4 != 0): return False
else: n = n/4
return True
and
import math
def powerof4(n):
if ((not isinstance(n, int)) or n&(n-1) != 0 or n == 0):
return False
#Now, I cheat, since 4^n = (2^n)^2
reduce_to_2 = math.sqrt(n)
if math.floor(reduce_to_2) != reduce_to_2:
return False
else:
reduce_to_2 = int(reduce_to_2)
return reduce_to_2&(reduce_to_2 - 1) == 0

Your first problem is that you are checking if the type of the argument is int but starting with numbers larger than 2^32 thats not true for Python 2 which codewars is using.
The next error is if you print the value at codewars at which the test fails you see it's for the call powerof4(True). isinstance(True, (int,long)) is True because bool is a subclass of int.
In your first code change your typecheck to
if n <= 0 or type(n) not in (int,long): return False
To add another variation on the problem. When I solved this problem initially some time ago I did it with some bit fiddling :)
def powerof4(n):
if type(n) not in (int, long):
return False
bin_repr = bin(n)[2:]
return bin_repr[0]=="1" and bin_repr.count("0")%2==0 and bin_repr.count("1")==1

There's an easier way.
import math
def powerof4(n):
return math.log(n, 4) % 1 == 0

There is one less obvious gotcha. In Python 2 the number could be too big to fit in an int and it would be a long instead:
>>> isinstance(1000000000000000000000000000000, int)
False
whereas Python 3 would return
>>> isinstance(1000000000000000000000000000000, int)
True
The easiest algorithm on any CPython (*except for the isinstance check) could be
def powerof4(n):
if n <= 0 or not isinstance(n, (int, long)):
return False
return hex(n).rstrip('0') in ('0x1', '0x4')
This converts the number into hex, and removes trailing zeroes; a number is a power of 4 if and only if the hex representation is 1 or 4 followed by any number of zeroes. (hint: it would be a power of 16 if it were 1 followed by zeroes).
With bitwise logic:
test = 1
while n < test:
test <<= 2
return n == test
In Python 2.7 and 3.3+ this is even easier, no loop needed:
b = n.bit_length()
return bool(b & 1) and 1 << (b - 1) == n

Like this?
def isPowerOf4(n):
try:
while n:
if n==1:
return True
if ((n>>2)<<2) != n:
return False
n >>= 2
except:
return False
return False

Related

Short-circuiting a condition statement

I wrote a function:
# given a n x m grid return how many different ways there are to move from top left to
# bottom right by only being able to move right or down
def grid(n, m, memo = {}):
if f'{n},{m}' in memo:
return memo[f'{n},{m}']
if n == 1 and m == 1:
return 1
if n == 0 or m == 0:
return 0
memo[f'{n},{m}'] = grid(n,m-1,) + grid(n-1,m)
return grid(n,m-1,) + grid(n-1,m)
Recently I read a bit about short-circuiting in Python and I am trying to understand it further.
As I understand it does not provide any boost in runtime, just sort of syntax sugar.
For example:
1 < 2 < 3 # is True
1 < 2 and 2 < 3 # is also True
# hence
(1 < 2 < 3) == 1 < 2 and 2 < 3 # is True
I was wondering can I write my function with this kind of short-circuiting in my if statements?
I came up with this:
def grid(n, m, memo = {}):
if f'{n},{m}' in memo:
return memo[f'{n},{m}']
if (n or m) == 1:
return 1
if (n and m) == 0:
return 0
memo[f'{n},{m}'] = grid(n,m-1,) + grid(n-1,m)
return grid(n,m-1,) + grid(n-1,m)
Is there any smarter way of using the short-circuit here?
(1 < 2 < 3) is not short-circuiting - I think you misunderstood the meaning of the term. You are correct that it is merely syntax sugar - although it can produce some very weird results in obscure cases. (1 < 2 < 3) expands to (1 < 2) and (2 < 3) - the middle operand is copied to both and and is used for the joining operator.
Short circuiting occurs when python already knows the answer to a boolean expression, even before calculating both the inputs. For example
def false():
print("false")
return False
def true():
print("true")
return True
print(false() and true())
The output would be
false
False
Because when python sees False and, it already knows that the result is False (because and requires both operands to be True), so it doesn't bother running the second half of the line.
This real short circuiting does result in a performance boost, but since you can't turn off short circuiting, it doesn't really matter ¯\_(ツ)_/¯
if (n or m) == 1 is definitely not the same thing as if n == 1 or m == 1. The first if statement is equivalent to:
value = n
if not value:
value = m
if value == 1:
# do something:
Or expressed more succinctly:
if (n if n else m) == 1:
# do something
In other words, n or m only evaluates m if n is False (or 0 if n is an integer), otherwise the result of the expression is n.
What you want to avoid redundancy is:
if 1 in (n, m): # equivalent to: if 1 is either n or m:
Update: Demo
n = 4
m = 1
if (n or m) == 1:
print('if branch taken')
else:
print('else branch taken')
Prints:
else branch taken
if (n or m) == 1
evaluates to
if (<bool>) == 1 # e.g. if {True,False} == 1
which is probably not what you want, since it is essentially evaluating the truthiness of n or m.
Your existing code already captures the nature of short-circuiting;
if n == 1 and m == 1
will only evaluate the second argument m == 1 iff n == 1, or will otherwise short-circuit.
To your comment
As I understand it does not provide any boost in runtime, just sort of syntax suggar.
Well, actually it does provide a runtime boost if Python is able to skip evaluating what would otherwise be "expensive" conditions to evaluate because it is able to short-circuit early.

Happy Number String Python function

I am pretty new to Python and just got started in Leet and I am doing the Happy Number question, only half of the test cases have been passed. I would appreciate any help. Thanks
A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
My test cases were 19, 100 where it output True correctly but when I do 7, it is wrong
def isHappy(self, n: int) -> bool:
if (n == 1):
return True
sum = 0
flag = False
for j in range(1,100):
x = str(n)
a = list(x)
for i in range(0,len(a)):
sum += int(a[i])*int(a[i])
if sum == 1:
return True
break
else:
x = sum
return False
Here is an implementation using a set to keep track of numbers that we have already seen. (I've removed the self argument here for sake of something that can be run outside of your test class.)
def isHappy(n: int) -> bool:
seen = set()
while True:
if n == 1:
return True
if n in seen:
return False
seen.add(n)
n = sum(int(c) ** 2 for c in str(n))
Your code has various issues aside from the fact that the number 100 is arbitrary.
Mainly that you never update n in your loop. Also you do not wait for the completion of the for loop before testing sum (in fact your break is never reached), you initialise sum only once, and you return False prematurely. Here is a minimally corrected version of your code, although still subject to the fact that there is no rule about 100 maximum iterations.
def isHappy(n: int) -> bool:
if (n == 1):
return True
for j in range(1,100):
x = str(n)
a = list(x)
sum = 0
for i in range(0,len(a)):
sum += int(a[i])*int(a[i])
if sum == 1:
return True
else:
n = sum
return False

Think python exercise 6.4

A number, a, is a power of b if it is divisible by b and a/b is a power of b. Write a function called is_power that takes parameters a and b and returns True if a is a power of b. Note: you will have to think about the base case.
I found this peace of code as it's solution:
def is_power(a,b):
if (a % b == 0):
return True
if (a/b == 1):
return True
else:
(is_power (a/b, b) )
else:
return False
But I guess some lines are not necessary. Here is my own code:
def is_power(a,b):
if (a % b == 0):
return True
else:
return False
What is the reason of existence of extra lines?
Both codes don't work for float numbers such as is_power(2.25, 1.5). Both, return False.
To answer part-1 of your question I have to remind you that the question here doesn't ask you to check whether a is divisible by b, but rather it requires you to find out if 'a' can be expressed as (+ve) exponential of 'b' i.e. a = b^n
As for part-2 of your question consider the function below, as it works for both integral & floating point inputs.
def is_power(a,b):
if a==b:
return True
elif (abs(a)>1 and abs(b)>1) or (abs(a)<1 and abs(b)<1):
return is_power(a/b, b)
return False
The second conditional statement arises from the fact that +ve exponents of any number with an absolute value greater(or less) than 1 will always be greater(or less) than 1. If absolute values of 'a' & 'b' lie on either side of unity then you can never find a +ve exponent such that a = b^n
The above function also takes care of the situation when either 'a' or 'b' is 1. In neither of these situations will you be able to find a +ve exponent 'n' such that a = b^n.
your second code is not correct, take the example of 6 and two your function will return true, but 6 is not a power of two .
def is_power(a, b):
while a % b == 0:
if a == b: return True
a /= b
return False
print(is_power(6, 2))
print(is_power(8, 2))
for the second example, comparing if two doubles are equal is usually done to a given magnitude like given eps = 0.0000001
a == b => abs(a - b) < eps .
#mehdi maick thanks for your correct answer. Here's recursive version, by help of your answer, which I was looking for.
def is_power2(a, b):
if a % b == 0 :
if a == b:
return True
else:
return is_power(a/b, b)
return False
helper Function
def is_divisible(a, b):
if a % b == 0:
return True
else:
return False
main Function
def is_power(a, b):
if a == b:
return True
elif b == 1:
return False
else:
return is_divisible(a,b) and is_power(a/b, b)
TEST CASES
print("is_power({0},{1}) returns: {2} ".format(10,2,is_power(10,2)))
print("is_power({0},{1}) returns: {2} ".format(27,3,is_power(27,3)))
print("is_power({0},{1}) returns: {2} ".format(1,1,is_power(1,1)))
print("is_power({0},{1}) returns: {2} ".format(10,1,is_power(10,1)))
print("is_power({0},{1}) returns: {2} ".format(3,3,is_power(3,3)))
Outputs
is_power(10,2) returns: False
is_power(27,3) returns: True
is_power(1,1) returns: True
is_power(10,1) returns: False
is_power(3,3) returns: True
What is the reason of existence of extra lines?
The question asks you to think about "Edge Cases". This part of the code "if (a/b == 1)" is handling an edge case.
Also, the question says "True if a is a power of b". By removing the else part of the loop, you are avoiding this from happening.
We can concise this code even more by simple mentioning the conditions with return function.
As conditions themselves are boolean, we can get a simple True or False:
def is_divisible(a,b):
return a%b==0 and (a/b)%b==0
print(is_divisible(121,11))
def is_divisible(x, y):
return x % y == 0
def is_power(a, b):
if a == 1: #every positive integer that has an exponent of 0 is a power of "1".
return True
elif is_divisible(a, b): #a is divisible by b
if a == b: #see explanation below
return True
elif b == 1 and a != 1: #the only positive integer that is a power of "1" is "1" itself
return False
else:
return is_power(a/b, b) #a/b is a power of b
return False
# Conditional if a == b, is a safeguard to avoid a/b < b as a result of recursion.
# e.g. a=4, b=2.
# First iteration. 4 % 2 == 0 is True. Then is_power( 4/2, 2 )
# Second iteration 2 % 2 == 0 is True. Then is_power ( 2/2, 2 ).
# Third iteration 1 % 2 == 0 is False.
# 4 is a power of 2. Without this conditional it would mistakenly return false.
print("is_power(10, 2) returns: ", is_power(10, 2))
print("is_power(27, 3) returns: ", is_power(27, 3))
print("is_power(1, 1) returns: ", is_power(1, 1))
print("is_power(10, 1) returns: ", is_power(10, 1))
print("is_power(3, 3) returns: ", is_power(3, 3))
#with edge conditions and negative value of a and b.
def is_power (a,b):
if a==1 or a==b: #always true for power of 0, always true for power of 1
return True
elif (a==0 or b==0 or b==1) or (b>a and b>0):
return False
else:
if a%b == 0 and is_power (a/b,b):
return True
else:
return False
Test Cases:
is_power(0, 0) returns: True
is_power(1, 0) returns: True
is_power(0, 1) returns: False
is_power(1, 1) returns: True
is_power(1, 2) returns: True
is_power(2, 1) returns: False
is_power(2, 2) returns: True
is_power(3, 2) returns: False
is_power(4, 2) returns: True
is_power(5, 2) returns: False
is_power(6, 2) returns: False
is_power(7, 2) returns: False
is_power(8, 2) returns: True
is_power(9, 2) returns: False
is_power(10, 2) returns: False
is_power(-1, 0) returns: False
is_power(-1, -1) returns: True
is_power(1, -1) returns: True
is_power(0, -1) returns: False
is_power(-4, 2) returns: False
is_power(-8, 2) returns: False
is_power(4, -2) returns: True
is_power(8, -2) returns: False
is_power(-4, -2) returns: False
is_power(-8, -2) returns: True
is_power(-2, -2) returns: True
is_power(-2, -4) returns: False
is_power(-2, -8) returns: False
Try this code, but remember it will only work for integers not floating point numbers:
def is_power(a,b):
if a==b:
return True
if a%b != 0:
return False
return is_power(a/b,b)
Also, the code you are using will not just hold true for exponentials but every multiple of 'b'

Prime number checking function not working for negative numbers

def is_prime(x):
x = abs(x)
if x == 0 or x == 1:
return False
elif x == 2:
return True
for i in range(2, x):
if x%i == 0:
return False
return True
The tester says the above code shouldn't return true for x = -7.
Please help.
Thank you :)
**Edit: **
im so sorry, just read somewhere that any number less than 2 (i.e 0, 1 and all negative numbers are not prime
It does return True for me. Check the value of x after you call abs(x), it will maybe help.
It does return True for negative numbers for me.
Also you can run the loop from 2 to x/2 and reduce the complexity.
My Python is not good, but something like this should work better:
def is_prime(x):
# Handle 1, 0 and negatives.
if x < 2:
return False
# Handle even numbers.
elif x % 2 == 0:
return x == 2
# Test with odd divisors.
for i in range(3, sqrt(x), 2):
if x % i == 0:
return False
return True
The sqrt(x) limit is a big time saver, and dealing with even numbers separately can halve the time with well mixed inputs.

Python function, odd, that takes in one number and returns True

Here is condition.
Write a Python function, odd, that takes in one number and returns True when the number is odd and False otherwise.
Condition is x: int or float.
and returns: True if x is odd, Falae otherwise
My code is
def odd(x):
while x % 2 != 0:
return (x % 2 == 1)
When if odd(62) above code is works, but odd(62) output is None. How can I correct False answer?
Please Help me.
Your function doesn't return anything if the number is not odd. You don't need a while loop at all:
>>> def odd(x):
... return x % 2 != 0
...
>>> odd(62)
False
>>> odd(63)
True
Also see other ways to check if the number is odd or not:
How to determine if an integer is even or odd
You don't want to use a while loop, a simple if will do it. The reason you get none is because the while loop doesn't run in the "even" condition so there is no return.
An even simpler way of writing it is to return the condition itself:
def odd(x):
return x % 2 == 1
The while loop is messing it up.
def odd(x):
return x % 2 == 1
return (x % 2 != 0)
This will return a boolean value; evaluates True if number is odd and False otherwise.
def odd(x):
'''
x: int
returns: True if x is odd, False otherwise
'''
while x%2 != 0:
return True
else:
return False

Categories

Resources