I have a question about python precedence. I have the following code:
def gcdIter(a, b):
ans = min(a,b)
while ((a%ans is not 0) and (b%ans is not 0)):
ans -= 1
return ans
My question is about the while logical statement. I added several parenthesis just to make sure that the expression would be evaluated the way I was thinking, but is not. The while loop is being breaked before the both expressions are true. Were I'm wrong?
I found a way to do the same thing without using two expressions, in:
def gcdIter(a, b):
ans = min(a,b)
while ((a%ans + b%ans is not 0)) :
ans -= 1
return ans
But I still wanna know why the first code isn't running the way I think it should.
Do not use identity testing (is or is not) to test for numerical equality. Use == or != instead.
while a%ans != 0 and b%ans != 0:
is tests for object identity (that both operators are the same python object), which is not the same thing as testing if the values are equivalent.
Since 0 is also considered False in a boolean context, you can even omit the != in this case:
while a % ans and b % ans:
The fractions module already has a gcd() function that implements the greatest common divisor algorithm correctly:
from fractions import gcd
print gcd(a, b)
It uses the Euclidian algorithm, python style:
def gcd(a, b):
"""Calculate the Greatest Common Divisor of a and b.
Unless b==0, the result will have the same sign as b (so that when
b is divided by it, the result comes out positive).
"""
while b:
a, b = b, a%b
return a
Related
Question asked to sum first n natural numbers.
My answer is:
def sum_numbers(x):
if x == 1:
return x
else:
return sum_numbers(x-1) + x
However, there is a more succinct:
def sum_numbers(n):
return n + sum_numbers(n-1) if n else 0
Was wondering how I should interpret the sum_numbers(n-1) if n? when does the else 0 come into play and n stop holding true? Looking at my original answer it seems its trying to say that we recurse function until x==1 before we return the entire sum?
Many thanks in advance!
The ternary operator
If you are familiar with other programming languages, python's a if b else c is expressed:
b ? a : c in C and Java;
if b then a else c in OCaml and Haskell.
?: is often called "the ternary operator", and the whole expression is called a "conditional expression" as opposed to the "conditional statement" you are familiar with.
In all cases, it is an expression that evaluates to the result of a or the result of c depending on the truth-value of b.
Inside a function, the two following fragments of code are equivalent:
if b:
return a
else:
return c
return (a if b else c)
Note that the expression is evaluated lazily, meaning that only the relevant subexpression is evaluated. For instance, the following code is correct and does not result in a ZeroDivisionError:
x = 6
y = 0
z = ((x / y) if (y != 0) else (x / 2))
print(z)
Output: 3.
Converting between int and bool
The condition used in the conditional statement n + sum_numbers(n-1) if n else 0 is simply "n". This might be unexpected, because n is a number, not a condition, right?
There is a python feature that any value can be used as a condition. This includes numbers, lists, dicts, strings, etc. In that case, "zero" or "empty" values mean false, and "nonzero" or "non-empty" values mean true. Since n is a number, "n" is the same as "n != 0" as the condition here.
Conclusion
Finally, the given piece of code is equivalent to:
def sum_numbers(n):
if n != 0:
return n + sum_numbers(n-1)
else:
return 0
The interpretation of: return n + sum_numbers(n-1) if n else 0 is this:
First split off two expressions: n + sum_numbers(n-1) and 0 because the if else should be interpreted as:
<expr1> if <cond> else <expr2>
This leaves <cond> above which is n in your expression. This is using n as the conditional, which means bool(n), which in the case of an integer means it returns False if 0 otherwise True.
So your expression means return n + sum_numbers(n-1) if n is truthy (ie non-zero) else return 0.
Note that the evaluation of n as a bool is performed before either of the other two expressions.
So the second sum_numbers is really returning the sum of 0..n
Google or Amazone ask the following question in an interview, would my solution be accepted?
problem: find the index of the first occurrence of the given word from the given string
note: Above problem is from a website and following code passed all the test cases. however, I am not sure if this is the most optimum solutions and so would be accepted by big giants.
def strStr(A, B):
if len(A) == 0 or len(B) == 0:
return -1
for i in range(len(A)):
c = A[i:i+len(B)]
if c == B:
return i
else:
return -1
There are a few algorithms that you can learn on this topic like
rabin karp algorithm , z algorithm ,kmpalgorithm
which all run in run time complexity of O(n+m) where n is the string length and m is the pattern length. Your algorithm runs in O(n*m) runtime complexity . I would suggest starting to learn from rabin karp algorithm, I personally found it the easiest to grasp.
There are also some advanced topics like searching many patterns in one string like the aho-corasick algorithm which is good to read. I think this is what grep uses when searching for multiple patterns.
Hope it helps :)
Python actually has a built in function for this, which is why this question doesn't seem like a great fit for interviews in python. Something like this would suffice:
def strStr(A, B):
return A.find(B)
Otherwise, as commenters have mentioned, inputs/outputs and tests are important. You could add some checks that make it slightly more performant (i.e. check that B is smaller than A), but I think in general, you won't do better than O(n).
If you want to match the entire word to the words in the string, your code would not work.
E.g If my arguments are print(strStr('world hello world', 'wor')), your code would return 0, but it should return -1.
I checked your function, works well in python3.6
print(strStr('abcdef', 'bcd')) # with your function. *index start from 0
print("adbcdef".find('bcd')) # python default function. *index start from 1
first occurrence index, use index() or find()
text = 'hello i am homer simpson'
index = text.index('homer')
print(index)
index = text.find('homer')
print(index)
output:
11
11
It is always better to got for the builtin python funtions.
But sometimes in the interviews they will ask for you to implemente it yourself. The best thing to do is to start with the simplest version, then think about corner cases and improvements.
Here you have a test with your version, a slightly improved one that avoid to reallocating new strings in each index and the python built-ing:
A = "aaa foo baz fooz bar aaa"
B = "bar"
def strInStr1(A, B):
if len(A) == 0 or len(B) == 0:
return -1
for i in range(len(A)):
c = A[i:i+len(B)]
if c == B:
return i
else:
return -1
def strInStr2(A, B):
size = len(B)
for i in range(len(A)):
if A[i] == B[0]:
if A[i:i+size] == B:
return i
return -1
def strInStr3(A, B):
return A.index(B)
import timeit
setup = '''from __main__ import strInStr1, strInStr2, strInStr3, A, B'''
for f in ("strInStr1", "strInStr2", "strInStr3"):
result = timeit.timeit(f"{f}(A, B)", setup=setup)
print(f"{f}: ", result)
The results speak for themselves (time in seconds):
strInStr1: 15.809420814999612
strInStr2: 7.687011377005547
strInStr3: 0.8342400040055509
Here you have the live version
I need to find the best (quickest) way to check for a given complex number z if its absolute value is smaller or equal to some arbitrary static number, E.G 6.
My tries
The naive approach I used is:
def check(z):
if abs(z) <= 6:
return True
return False
But since calculating the absolute value of a complex number in cartesian representation (which I assume is the way in which python stores complex numbers) requires calculating a square root, I thought that squaring both sides would be quicker E.G
def check2(z):
if z.real**2 + z.imag**2 <= 36:
return True
return False
Or some other method of squaring, like
def check3(z):
if z.real*z.real + z.imag*z.imag <= 36:
return True
return False
But while testing, I found that the first method is quicker by a large margin.
Is the first method really the quickest? If so, how? I found no documentation on how python handles complex number methods internally.
The builtin functions are written in C, that is why they are faster. You can import dis from dis to see that check has only 10 instructions while the other methods have 13.
And even then I want to point out that you are cheating! You are doing some computations for the function. The general case would be this.
def check(z, n):
if abs(z) <= n:
return True
return False
def check2(z, n):
if z.real ** 2 + z.imag ** 2 <= n ** 2:
return True
return False
So you do save a square root incheck2, but that is at the price of squaring.
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.
I have two pieces of python code finding two positive integers' GCD.
Here is the correct one:
def gcdRecur(a, b):
if b == 0:
return a
return gcdRecur(b, a%b)
Here is the one with bug:
def gcdRecur(a, b):
a = max(a, b)
b = min(a, b)
if b == 0:
return a
return gcdRecur(b, a%b)
It's easy to see the differences between these two pieces of code. And I know that there is no need to add
a = max(a, b)
b = min(a, b)
before the control flow. I can't find any logic mistakes in the latter code, but it print out the wrong result.
------use former code find GCD of 182 ans 224------
print out 14
------use former code find GCD of 182 ans 224------
print out 224(wrong answer)
So I guess it may be associated with the principle of recursion in python which I don't know at all. Can anyone help me and tell me what's going on T T.
Thank you.
The problem is when you call a = max(a,b) and b is the max value, the old a will be missing, and a will equal b which leads to gcd(b,b) == b