Leetcode 4 binary search while loop - python

I'm trying to solve leetcode problem 4 which needs you to do binary search.
Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.
The overall run time complexity should be O(log (m+n)).
This is my code:
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
if len(nums1) > len(nums2):
return self.findMedianSortedArrays(nums2, nums1)
A, B = nums1, nums2
total = len(A) + len(B)
half = total // 2
l, r = 0, len(A) - 1
while l < r:
i = l + (r - l) // 2
j = half - i - 1 - 1
Aleft = A[i] if i >= 0 else float("-inf")
Aright = A[i + 1] if (i + 1) < len(A) else float("inf")
Bleft = B[j] if j >= 0 else float("-inf")
Bright = B[j + 1] if (j + 1) < len(B) else float("inf")
if Aleft <= Bright and Bleft <= Aright:
if total % 2:
return min(Aright, Bright)
else:
return (max(Aleft, Bleft) + min(Aright, Bright)) / 2
elif Aleft > Bright:
r = i - 1
elif Bleft > Aright:
l = i + 1
It gives this error note:
TypeError: None is not valid value for the expected return type double
raise TypeError(str(ret) + " is not valid value for the expected return type double");
Line 52 in _driver (Solution.py)
_driver()
Line 59 in <module> (Solution.py)
During handling of the above exception, another exception occurred:
TypeError: must be real number, not NoneType
Line 18 in _serialize_float (./python3/__serializer__.py)
Line 61 in _serialize (./python3/__serializer__.py)
out = ser._serialize(ret, 'double')
Line 50 in _driver (Solution.py)
However if I change the while loop condition to just while True:
class Solution:
def findMedianSortedArrays(self, nums1, nums2):
if len(nums1) > len(nums2):
return self.findMedianSortedArrays(nums2, nums1)
A, B = nums1, nums2
total = len(A) + len(B)
half = total // 2
l, r = 0, len(A) - 1
while True:
i = l + (r - l) // 2
j = half - i - 1 - 1
Aleft = A[i] if i >= 0 else float("-inf")
Aright = A[i + 1] if (i + 1) < len(A) else float("inf")
Bleft = B[j] if j >= 0 else float("-inf")
Bright = B[j + 1] if (j + 1) < len(B) else float("inf")
if Aleft <= Bright and Bleft <= Aright:
if total % 2:
return min(Aright, Bright)
else:
return (max(Aleft, Bleft) + min(Aright, Bright)) / 2
elif Aleft > Bright:
r = i - 1
elif Bleft > Aright:
l = i + 1
It runs perfectly.
Why the difference? How could these two different in logic?
Any help will be much appreciated.

The error you see is a little obscure because LeetCode is taking your solution code and wrapping it up for execution - but 1 hint you can tell from the error is that something is returning None when it's expecting a double.
The thing that's different is that if l >= r, none of the code in the while block will execute and the function will return with an implicit None value. If you instead change to while True:, the code within will always execute at least once and if the code falls into Aleft <= Bright and Bleft <= Aright, then the function will return with a non-None value.
if you add a return <some-number-here> after the while loop at the end of the function, you won't get the same error however you won't have the right answer either since the failing test case will probably return with whatever value you hardcoded in.
In the default test case, you can see that this happens at some point in your code because l, r = 0, 0 if you add a print(l, r) at the end of the function(outside of the while loop) followed by the dummy return value.
My advice (and I know some IDEs warn about this as well) would be to use explicit returns if a function is expected to return something and try not to force consumers of your function to handle None if you can - consistent types make for happy programmers.

Related

Find how many combinations of integers possible to reach the result

I'm a bit stuck on a python problem.
I'm suppose to write a function that takes a positive integer n and returns the number of different operations that can sum to n (2<n<201) with decreasing and unique elements.
To give an example:
If n = 3 then f(n) = 1 (Because the only possible solution is 2+1).
If n = 5 then f(n) = 2 (because the possible solutions are 4+1 & 3+2).
If n = 10 then f(n) = 9 (Because the possible solutions are (9+1) & (8+2) & (7+3) & (7+2+1) & (6+4) & (6+3+1) & (5+4+1) & (5+3+2) & (4+3+2+1)).
For the code I started like that:
def solution(n):
nb = list(range(1,n))
l = 2
summ = 0
itt = 0
for index in range(len(nb)):
x = nb[-(index+1)]
if x > 3:
for index2 in range(x-1):
y = nb[index2]
#print(str(x) + ' + ' + str(y))
if (x + y) == n:
itt = itt + 1
for index3 in range(y-1):
z = nb[index3]
if (x + y + z) == n:
itt = itt + 1
for index4 in range(z-1):
w = nb[index4]
if (x + y + z + w) == n:
itt = itt + 1
return itt
It works when n is small but when you start to be around n=100, it's super slow and I will need to add more for loop which will worsen the situation...
Do you have an idea on how I could solve this issue? Is there an obvious solution I missed?
This problem is called integer partition into distinct parts. OEIS sequence (values are off by 1 because you don't need n=>n case )
I already have code for partition into k distinct parts, so modified it a bit to calculate number of partitions into any number of parts:
import functools
#functools.lru_cache(20000)
def diffparts(n, k, last):
result = 0
if n == 0 and k == 0:
result = 1
if n == 0 or k == 0:
return result
for i in range(last + 1, n // k + 1):
result += diffparts(n - i, k - 1, i)
return result
def dparts(n):
res = 0
k = 2
while k * (k + 1) <= 2 * n:
res += diffparts(n, k, 0)
k += 1
return res
print(dparts(201))

Use Recursion to Find Distinct Ways N can be computed

Was recently trying to solve this coding challenge from a company and I was stumped.
Let T(n) denote the number of different ways that a value of n cents, where n >= 4 and n is even, can be made by using 4-cent and 6-cent coins. For example, if n = 12 then we can use 3 4-cent coins or 2 6-cent coins, so T(12) = 2. Write a recursive algorithm in Python to find T(n) for n >= 4 and n is even.
I nailed down the base cases to be T(n < 4 or n not even) = 0, T(4) = 1 distinct way (1 4-cent coin) and T(6) = 1 distinct way (1 6-cent coin). But I'm not entirely sure how to proceed with a value greater than 6 and is even. Actually, if n > 4 and is even I did think of using modulo (%), so
if(n % 4 == 0): increment count
if(n % 6 == 0): increment count
I guess, I'm stuck on the recursive part because the two if-statements I've computed would count as only a single a way whereas there can be multiple ways to compute N.
Not recursive, but should help you get started.
To determine unique solutions, you are basically asking for partitions of N such that N1 + N2 = N and N1 % 4 == 0 and N2 % 6 == 0. An iterative solution would go something like this:
count = 0
for j in range(0, N + 1, 4):
if (N - j) % 6 == 0:
count += 1
Turning this loop into a recursion is trivial:
def count(N):
def count4(N, n4):
if n4 > N:
return 0
return int((N - n4) % 6 == 0) + count4(N, n4 + 4)
if N < 4 or N % 2:
return 0
return count4(N, 0)
Assuming that ways means "exact order in which coins are laid out", here is a recursive solution.
def T_recurse (n):
if 0 == n:
return 1
elif n < 3:
return 0
else:
return T_recurse(n - 4) + T_recurse(n - 6)
print(T_recurse(100))
And a faster solution
def T_iter(n):
if n < 0:
return 0
else:
answers = [1, 0, 0, 0, 1, 0]
while len(answers) <= n:
answers.append(answers[-4] + answers[-6])
return answers[n]
print(T_iter(100))
(There is also an analytical solution involving the roots of the polynomial x^6 - x^2 - 1, but that is slower to calculate in practice.)
Assuming that ways means "this many of one, that many of the other", then here is a recursive solution:
def S_recurse (n, coins):
if 0 == n:
return 1
elif n < 0:
return 0
elif len(coins) == 0:
return 0
else:
return S_recurse(n - coins[0], coins) + S_recurse(n, coins[1:])
S_recurse(12, [4, 6])
The recursive slowdown is not as bad though still exponential. However but iterative gives you quadratic:
def S_iter (n, coins):
last_row = [0 for i in range(n + 1)]
last_row[0] = 1
for coin in coins:
this_row = []
for i in range(n+1):
if i < coin:
this_row.append(last_row[i])
else:
this_row.append(last_row[i] + this_row[i - coin])
last_row = this_row
return last_row[n]
You can use an optional parameter to keep track of the current sum of 6-cent coins for a given recursive call, and return 1 when the given number is divisible by 4 after deducting the sum of 6's:
def count46(n, sum6=0):
return sum6 <= n and (((n - sum6) % 4) == 0) + count46(n, sum6 + 6)
so that:
for i in range(4, 24, 2):
print(i, count_4_6(i))
outputs:
4 1
6 1
8 1
10 1
12 2
14 1
16 2
18 2
20 2
22 2
Not the most optimized but it returns an array of all distinct solutions
def coins(n, sum=0, current=[], answers=[]):
if sum > n:
return
if sum == n:
answers.append(current)
return
a4 = list(current)
a4.append(4)
coins(n, sum+4, a4, answers)
lastIndex = len(current) - 1
if len(current) == 0 or current[lastIndex] == 6:
a6 = list(current)
a6.append(6)
coins(n, sum+6, a6, answers)
return answers
Try it online!

How to get a prime collection within 2^63 - 1 in Python

I want to get a prime number set within 2^63 - 1 in Python,I have seen the following code on the web:
limit = 2**63 - 2
p = [True] * (limit + 1)
# p = bitarray(limit + 1)
p[0] = p[1] = False
for i in range(2, int(math.sqrt(limit) + 1)):
if p[i]:
for j in range(i * i, limit + 1, i):
p[j] = False
prime = [i for i in range(limit + 1) if p[i]]
print(prime)
But when I run this program, the compiler complains that can not fit 'int' into an index-sized integer.
I tried to solve the problem with bitarray, but the index of the array is still too big.
You can use the following code. It is using the Sieve of Eratosthenes in combination with a generator function in order to reduce the memory usage of this algorithm. It is furthermore exploiting the less commonly known fact that every prim number > 4 can be written as 6*n ± 1.
import math
limit = 2 ** 63 - 1
def isPrim(n, belowPrims):
limit = int(math.sqrt(n))
for prim in belowPrims:
if prim > limit: break
if n % prim == 0: return False
return True
def calcPrims():
yield 2
yield 3
toTest, nextN = [], 6
while True:
p1 = nextN - 1
if isPrim(p1, toTest):
yield p1
toTest.append(p1)
p2 = nextN + 1
if isPrim(p2, toTest):
yield p2
toTest.append(p2)
nextN += 6
for prim in calcPrims():
if prim > limit:
break
print(prim)
Edit
This link here https://primes.utm.edu/notes/faq/six.html explains briefly why every prim number can be written in the form 6*n ± 1.
You can use sympy:
import sympy
print(list(sympy.primerange(0,2**63-1)))
but as 2^63 is quite large this will take some time.
if you have a primes() generator of some kind, you could do this:
is_prime_var = 0
MAX = 1 << 5
last_p = 0
for p in primes():
if p > MAX:
break
print(p, p-last_p)
is_prime_var <<= (p - last_p)
is_prime_var |= 1
last_p = p
is_prime_var <<= (MAX - last_p - 1)
now the locations of the primes are stored (in reversed order) in the integer is_prime_var.
then the expression (is_prime >> (MAX-n-1)) & 1 would be 1 if n is prime; 0 otherwise:
def is_prime(n):
return bool((is_prime_var >> (MAX-n-1)) & 1)
you could use primes() from this excellent answer as prime generator.
thers is also this answer of mine about a fast and memory-efficient sieve of eratosthenes. might also be interesting.

perfect squares leetcode missing testcase with recursive solution

Trying to solve this problem with recursion but for input 7168 getting wrong answer.
Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
def recursive(self, n, result, dp):
if n in dp:
return dp[n]
#very large number
large_no = 1 << 31
if n < 1:
return 0
#checking if n is a square or not?
r = n**0.5
if int(r)*int(r) == n:
return result + 1
#iterate from square root till 1 checking all numbers
r = int(r)
while r >= 1:
large_no = min(large_no, self.recursive(n - int(r)*int(r), result + 1, dp))
r -= 1
#memoize the result
dp[n] = large_no
return large_no
I am calling above function as this: self.recursive(7168, 0, {})
Answer should be 4 but I am getting 5. Please don't suggest alternative ways to solve this problem as I have tried them already and it works. I am here to just know the problem with this logic.
First, you have a typo: m should be large_no.
But you're using dp incorrectly: you should be caching the smallest way to write i as the sum of squares, but you're actually caching the result of whatever path you happen to get there.
That means you may cache an accidentally larger value than necessary, and your algorithm is wrong. Although the algorithm is wrong, 7168 is the first value for which it produces the wrong result.
Drop the result argument, change return result+1 to return 1 and your recursive call to:
large_no = min(large_no, 1+self.recursive(n - int(r)*int(r), dp))
A cleaned-up, working version of your code:
def recursive(n, dp):
if n in dp:
return dp[n]
if n == 0: return 0
best = n
for r in xrange(int(n**0.5), 0, -1):
best = min(best, 1 + recursive(n - r*r, dp))
dp[n] = best
return dp[n]
I think the problem is that you're passing result down into your recursion but do not take it into account in memoizing.
recursive(X, Y, dp) and recursive(X, Z, dp) both return dp[X] if X in dp but return dp[X] + y and dp[X] + z, respectively, if dp[X] is not yet memoized (where y = R - Y and z = R - Z, with R the value of result when dp[X] got memoized).
I would get rid of result altogether:
def recursive(self, n, dp):
if n in dp:
return dp[n]
#very large number
large_no = 1 << 31
if n < 1:
return 0
#checking if n is a square or not?
r = n**0.5
if int(r)*int(r) == n:
return 1
#iterate from square root till 1 checking all numbers
r = int(r)
while r >= 1:
large_no = min(large_no, self.recursive(n - int(r)*int(r), dp))
r -= 1
#memoize the result
dp[n] = large_no + 1
return large_no + 1

Codewars. Some tests are passed, but i need to get tests which outputs the following mistake: 3263 should equal -1

Can you explain it what problems are here? To my mind, this code is like a heap of crap but with the right solving. I beg your pardon for my english.
the task of this kata:
Some numbers have funny properties. For example:
89 --> 8¹ + 9² = 89 * 1
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:
Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k
If it is the case we will return k, if not return -1.
Note: n, p will always be given as strictly positive integers.
dig_pow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
dig_pow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
dig_pow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
dig_pow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
def dig_pow(n, p):
if n > 0 and p > 0:
b = []
a = str(n)
result = []
for i in a:
b.append(int(i))
for x in b:
if p != 1:
result.append(x ** p)
p += 1
else:
result.append(x ** (p + 1))
if int((sum(result)) / n) < 1:
return -1
elif int((sum(result)) / n) < 2:
return 1
else:
return int((sum(result)) / n)
test results:
Test Passed
Test Passed
Test Passed
Test Passed
3263 should equal -1
I don't know what exact version of Python you're using. This following code are in Python 3. And if I get you correctly, the code can be as simple as
def dig_pow(n, p):
assert n > 0 and p > 0
digits = (int(i) for i in str(n)) # replaces your a,b part with generator
result = 0 # you don't use result as a list, so an int suffice
for x in digits: # why do you need if in the loop? (am I missing something?)
result += x ** p
p += 1
if result % n: # you just test for divisibility
return -1
else:
return result // n
The major problem is that, in your objective, you have only two option of returning, but you wrote if elif else, which is definitely unnecessary and leads to problems and bugs. The % is modulus operator.
Also, having an if and not returning anything in the other branch is often not a good idea (see the assert part). Of course, if you don't like it, just fall back to if.
I believe this could work as well and I find it a little easier to read, however it can definitely be improved:
def dig_pow(n, p):
value = 0
for digit in str(n):
value += int(digit)**p
p += 1
for k in range(1,value):
if value/k == n:
return k
return -1
this is some example simple example than using:
digits = (int(i) for i in str(n))
I'm opting to use this version since I am still a beginner which can be done with this alt way:
result = 0
for digits in str(n):
#iterate through each digit from n
# single of digits turn to int & power to p
for number in digits:
result += int(number) ** p
p += 1
as for the full solution, it goes like this:
def dig_pow(n, p):
# example n = 123 , change it to string = 1, 2, 3
# each string[] **p, and p iterate by 1
# if n % p not equal to p return - 1
result = 0
for digits in str(n):
#iterate through each digit from n
# single digit turn to int & power to p
for number in digits:
result += int(number) ** p
p += 1
if result % n:
return -1
else:
return result // n

Categories