I am attempting the sumOFTwo challenge on CodeFights.com but I unfortuantly cannot complete it to view the solution. All my tests suceedd until the 15th hidden test and it says it exceeds the time limit.
The challenge is - You have two integer arrays, a and b, and an integer target value v. Determine whether there is a pair of numbers, where one number is taken from a and the other from b, that can be added together to get a sum of v. Return true if such a pair exists, otherwise return false.
My code is -
def sumOfTwo(a,b,v):
a.sort()
b.sort()
if(0 in a and v in b):
return True
elif(v in a and 0 in b):
return True
else:
for i in a:
for j in b:
if(i + j == v):
return True
return False
I know it could be shrunken down to about 6 lines of code, but I kept adding in lines that could help the code possibly finish quicker. Are there any other optimizations I am missing.
You could just turn one of the lists to set, iterate over the other list and see if v - value_from_list exists in the set:
def sumOfTwo(a,b,v):
b = set(b)
return any(v - x in b for x in a)
print(sumOfTwo([3, 6, 7], [2, 1], 9))
print(sumOfTwo([3, 6, 7], [2, 1], 10))
print(sumOfTwo([3, 6, 7], [2, 1], 4))
print(sumOfTwo([3, 6, 7], [2, 1], 3))
Output:
True
False
True
False
Time complexity of above in O(n).
Here is how I solved it in Python:
def sumOfTwo(a, b, v):
#No need to iterate a huge list, if the other list is empty
if not a or not b:
return False
#kill duplicates
b = set(b)
#iterate through list a to look if the wanted difference is in b
for x in a:
if (v-x) in b:
return True
return False
This is what I have. It passes all the tests, hidden included, but it takes too long on four of the hidden tests.
def sumOfTwo(a, b, v):
for i in a:
if((v-i) in b):
return True
return False
#niemmi's answer passes the time limit portion. I didn't know sets were faster than arrays/lists. Thanks, good to know. If I add b=set(b) before the for loop, it passes.
Try this:
function sumOfTwo(a, b, v) {
if(a.length==0)return false;
if(b.length==0)return false;
for(var i=0; i<a.length; i++){
if(b.indexOf(v-a[i])>0){
return true;
}
}
return false;}
Related
I'm trying to write a function in python that generates an array of outputs using a specific formula but uses another formula if a certain condition is met.
The code I wrote is,
import numpy as np
def fun(a,b):
for i in range(len(b)):
if a != b[i]:
return a+b[i]
elif a == b[i]:
return a-b[i]
a=1
b=np.array([5,4,1,2,3])
fun(a,b)
and I get as a result,
6
rather than,
array([6, 5, 0, 3, 4])
can anyone direct me towards the appropriate code for this task, I would like to generalize the idea over more complex formulas.
The problem in your approach is that it returns on the very first iteration instead of creating a list and appending to it then returning that list.
With a list comprehension (unfortunately np.array does not work with generator expressions):
def fun(a, b):
return np.array([n - 1 if n == a else n + 1 for n in b])
But since you are using numpy you would be better off using the tools it offers.
In this case, np.where:
a = 1
b = np.array([5,4,1,2,3])
print(np.where(b == 1, b - 1, b + 1))
Outputs
[6 5 0 3 4]
you need to calculate each value, append it to a list and finally return the list
import numpy as np
def fun(a,b):
res = []
for i in range(len(b)):
if a != b[i]:
val = a+b[i]
elif a == b[i]:
val = a-b[i]
res.append(val)
return res
a=1
b=np.array([5,4,1,2,3])
fun(a,b)
once return is executed, the execution of the function stops
Use
import numpy as np
def fun(a,b):
my_list=[]
for i in range(len(b)):
if a != b[i]:
my_list.append(a+b[i])
elif a == b[i]:
my_list.append(a-b[i])
return np.array(my_list)
a=1
b=np.array([5,4,1,2,3])
fun(a,b)
Output:
array([6, 5, 0, 3, 4])
You would need to build a return object and then return it once at the end of the function, rather than returning inside the loop.
Something along the lines of:
def fun(a, b):
result = np.zeros_like(b)
for i in range(len(b)):
if ...:
result[i] = a+b[i]
else:
...
return result
def fun_lst(lst, a, b):
if min(lst)<b and max(lst)>a:
return True
return False
How do I check if the values in the list are bigger than a and smaller than b? I tried the above, but in this example: fun_lst([-1, 3.5, 6], -2.4, 0)the function returns True and it supposed to return False.
Do this:
def fun_lst(lst, a, b):
if min(lst) > a and max(lst) < b:
return True
return False
print(fun_lst([-1, 3.5, 6], -2.4, 0) )
Output:
False
Doing min(lst) > a ensures every element is bigger than a.
Doing max(lst) < b ensures every element is smaller than b.
Alternate solution:
def fun_lst(lst, a, b):
return all(a < elem < b for elem in lst)
You can try this one liner if you like
all([num < b and num > a for num in lst])
This code here will check each item in the list, if an item is found that is not greater than a and less than b then it returns false, otherwise it returns true.
def fun_lst(lst, a, b):
for item in lst:
if not a < item < b:
return False
return True
myList = [1,2,3,4,5,6,7,8,9]
lower_limit = 3
upper_limit = 8
bool_output = all([i > lower_limit and i < upper_limit for i in myList])
print(bool_output)
False
myList = [1,2,3,4,5,6,7,8,9]
lower_limit = 0
upper_limit = 10
bool_output = all([i > lower_limit and i < upper_limit for i in myList])
print(bool_output)
True
you should try this:
def fun_lst(lst, a, b):
return all(n > a and n < b for n in lst)
If you have a provision to use numpy try this
In [1]: import numpy as np
In [3]: np.array(b)
Out[3]: array([ 3, 1, 4, 66, 8, 3, 4, 56])
In [17]: b[(2<b) & (b<5)]
Out[17]: array([3, 4, 3, 4])
Different a method:
def fun_lst(lis, x, y):
list = [i>x and i<y for i in lis]
return False if False in list else True
It's a little easy:
def fun_lst(lis, x, y):
return x<max(lis)<y
lambda version:
fun_lst = lambda lis, x, y: x<max(lis)<y
Outputs:
fun_lst([-1, 3.5, 6], -2.4, 0) #Output: False
I just did a coding challenge for a company and was unable to solve this problem. Problem statement goes like:
Given an array of integers, find the number of subsequences in the array whose sum is divisible by k, where k is some positive integer.
For example, for [4, 1, 3, 2] and k = 3, the solution is 5. [[3], [1, 2], [4,3,2], [4,2], [1,3,2]] are the subsequences whose sum is divisible by k, i.e. current_sum + nums[i] % k == 0, where nums[i] is the current element in the array.
I tried to solve this recursively, however, I was unable to pass any test cases. My recursive code followed something like this:
def kSum(nums, k):
def kSum(cur_sum, i):
if i == len(nums): return 0
sol = 1 if (cur_sum + nums[i]) % k == 0 else 0
return sol + kSum(cur_sum, i+1) + kSum(cur_sum + nums[i], i+1)
return kSum(0, 0)
What is wrong with this recursive approach, and how can I correct it? I'm not interested in an iterative solution, I just want to know why this recursive solution is wrong and how I can correct it.
Are you sure that is not the case test? For example:
[4, 1, 3, 2], k = 3
has
4+2 = 6, 1+2=3, 3, 1+2+3=6, 4+2+3 = 9
So, your function is right (it gives me 5) and I don't see a major problem with your function.
Here is a javascript reproduction of what you wrote with some console logs to help explain its behavior.
function kSum(nums, k) {
let recursive_depth = 1;
function _kSum(cur_sum, i) {
recursive_depth++;
if (i == nums.length) {
recursive_depth--;
return 0;
}
let sol = 0;
if (((cur_sum + nums[i]) % k) === 0) {
sol = 1;
console.log(`Found valid sequence ending with ${nums[i]} with sum = ${cur_sum + nums[i]} with partial sum ${cur_sum} at depth ${recursive_depth}`);
}
const _kSum1 = _kSum(cur_sum, i+1);
const _kSum2 = _kSum(cur_sum + nums[i], i+1);
const res = sol + _kSum1 + _kSum2;
recursive_depth--;
return res;
}
return _kSum(0, 0);
}
let arr = [4, 1, 3, 2], k = 3;
console.log(kSum(arr, k));
I think this code actually gets the right answer. I'm not fluent in Python, but I might have inadvertently fixed a bug in your code though by adding parenthesis around (cur_sum + nums[i]) % k
It seems to me that your solution is correct. It reaches the answer by trying all subsequences, which has 2^n complexity. We could formulate it recursively in an O(n*k) search space, although it could be more efficient to table. Let f(A, k, i, r) represent how many subsequences leave remainder r when their sum is divided by k, using elements up to A[i]. Then:
function f(A, k, i=A.length-1, r=0){
// A[i] leaves remainder r
// when divided by k
const c = A[i] % k == r ? 1 : 0;
if (i == 0)
return c;
return c +
// All previous subsequences
// who's sum leaves remainder r
// when divided by k
f(A, k, i - 1, r) +
// All previous subsequences who's
// sum when combined with A[i]
// leaves remainder r when
// divided by k
f(A, k, i - 1, (k + r - A[i]%k) % k);
}
console.log(f([1,2,1], 3));
console.log(f([2,3,5,8], 5));
console.log(f([4,1,3,2], 3));
console.log(f([3,3,3], 3));
I'm looking for the median of three, using this for a pivot in a QuickSort. I would not like to import any statistics library because I believe it creates a bit of overhead which I would like to reduce as much as possible.
def median(num_list):
if (num_list[0] > num_list[len(num_list) - 1]) and (num_list[0] < num_list[int(len(num_list)//2)]):
return num_list[0]
elif (num_list[int(len(num_list)//2)] > num_list[len(num_list) - 1]) and (num_list[0] > num_list[int(len(num_list)//2)]):
return num_list[int(len(num_list)//2)]
else:
return num_list[len(num_list) - 1]
this seems to be returning the last else statement every time, I'm stumped...
In Quicksort you do not usually want just to know the median of three, you want to arrange the three values so the smallest is in one spot, the median in another, and the maximum in yet another. But if you really just want the median of three, here are two ways, plus another that rearranges.
Here's a short way to find the median of a, b, and c.
return a + b + c - min(a, b, c) - max(a, b, c)
If you want only comparisons, and to get what may be the quickest code, realize that three comparisons may need to be executed but you want to try for only two. (Two comparisons can handle four cases, but there are six arrangements of three objects.) Try
if a < b:
if b < c:
return b
elif a < c:
return c
else:
return a
else:
if a < c:
return a
elif b < c:
return c
else:
return b
If you want to rearrange the values so a <= b <= c,
if a > b:
a, b = b, a
if b > c:
b, c = c, b
if a > b
a, b = b, a
return b
Let Python do the work for you. Sort the three elements, then return the middle one.
def median(num_list):
return sorted([num_list[0], num_list[len(num_list) // 2], num_list[-1]])[1]
Using min and max:
>>> numlist = [21, 12, 16]
>>> a, b, c = numlist
>>> max(min(a,b), min(b,c), min(a,c))
16
>>>
Going out on a limb - I have a functional streak so here is the itertools equivalent, even though it means importing a module
>>> import itertools
>>> numlist = [21, 12, 16]
>>> z = itertools.combinations(numlist, 2)
>>> y = itertools.imap(min, z)
>>> max(y)
16
Hi so i'm trying to make a function where I subtract the first number with the second and then add the third then subtract the fourth ie. x1-x2+x3-x4+x5-x6...
So far I have this, I can only add two variables, x and y. Was thinking of doing
>>> reduce(lambda x,y: (x-y) +x, [2,5,8,10]
Still not getting it
pretty simple stuff just confused..
In this very case it would be easier to use sums:
a = [2,5,8,10]
sum(a[::2])-sum(a[1::2])
-5
Use a multiplier that you revert to +- after each addition.
result = 0
mult = 1
for i in [2,5,8,10]:
result += i*mult
mult *= -1
You can keep track of the position (and thus whether to do + or -) with enumerate, and you could use the fact that -12n is +1 and -12n+1 is -1. Use this as a factor and sum all the terms.
>>> sum(e * (-1)**i for i, e in enumerate([2,5,8,10]))
-5
If you really want to use reduce, for some reason, you could do something like this:
class plusminus(object):
def __init__(self):
self._plus = True
def __call__(self, a, b):
self._plus ^= True
if self._plus:
return a+b
return a-b
reduce(plusminus(), [2,5,8,10]) # output: -5
Or just using sum and a generator:
In [18]: xs
Out[18]: [1, 2, 3, 4, 5]
In [19]: def plusminus(iterable):
....: for i, x in enumerate(iterable):
....: if i%2 == 0:
....: yield x
....: else:
....: yield -x
....:
In [20]: sum(plusminus(xs))
Out[20]: 3
Which could also be expressed as:
sum(map(lambda x: operator.mul(*x), zip(xs, itertools.cycle([1, -1]))))