There is known problem called 3SUM.
Here is a little altered question: Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target.
I'm trying to write code for it on two different sites with code-challenge problems. If I write outer loop from 0 and forward (as in wiki) I get accepted result on both sites. But if I write code as below (difference in outer loop and settings of "j" and "k") than on one of them I get wrong answer on some test case (I don't know it).
Could you tell me please if there is a problem in my code? It would be awesome to get input which causes wrong answer if code is really has mistake.
def threeSumClosest(self, A, B):
A.sort()
closest = 1000000000
if len(A) < 3:
return closest
for i in xrange(len(A)-1, 1, -1):
j = 0
k = i - 1
while j < k:
S = A[i] + A[j] + A[k]
if S == B:
return B
elif S > B:
if closest is None or abs(B - S) < abs(B - closest):
closest = S
k -= 1
else:
if closest is None or abs(B - S) < abs(B - closest):
closest = S
j += 1
return closest
There is nothing wrong with your code, I think the test case where your code fails is a case where two right answers exist. Consider the following example:
A = {1, 2, 3, 6, 10} and B = 16
In this case, if you run the code with your current settings (outer loop starting from the end), then your code will output 17 which is 10 + 6 + 1; however, with the "wiki" settings (outer loop starting from the beginning), the output would be 15 which is 10 + 2 + 3. In both cases the difference between the answer and B is 1, but the numbers are different.
This could be easily checked: in your code, change the two conditions of abs(B - S) < abs(B - closest) to abs(B - S) <= abs(B - closest) (inside the elif and else statements). This will make sure that you would get the same answer as if you would have started from the beginning instead of the end in the outer loop. Make these two changes and resubmit your code, it should take care of it.
Related
I have a little problem which looks like a “combinatorics” problem.
We know that 1+2+3+…+k = (k^2 + k)/2; so, let’s take the set of numbers S = {1,2,3,4,…,(k^2 + k)/2} and divide this collection into k parts:
The 1st part has 1 element 1; the 2nd has 2 elements 2,3; the 3rd has 3 elements 4,5,6; …and so on…; the kth having k elements (k^2 – k + 2)/2,…,(k^2 + k)/2.
Then I have to draw a random integer in S, say i = random.randint(1, (k^2 + k)/2) and I have to do some operations according to the element that was drawn:
if i == 1:
`something`
else if 2 <= i <= 3:
`something else`
else if 4 <= i <= 6:
`something else`
…
else: # last line when `i` is in the last `kth` part
`something else`
The number k I have to use is variable, so I can't actually write the above program, because I don't know a priori where it should stop...
It seems to me that the best would be to define a function:
def cases(k):
i = random.randint(1, (k^2 + k)/2)
if i == 1:
`something`
else if 2 <= i <= 3:
… and so on…
But the problem remains: how could I write such a function without a specific k? There may be a trick in Python to do this, but I don't see how.
All ideas will be welcome.
Sorry for the indenting; I acknowledge it's wrong. Following the comment of Zach Munro, I allow myself an answer to better clarify the idea that I had in mind and which was not very clear.
Below is the kind of program I was thinking of; the something and something else are actually similar, for they use the same function, but with a different domain each time:
def cases(start, end, k):
delta = (end - start) / k
i = random.randint(1, (k**2 + k)/2)
if i == 1:
# random in the 1st part
x = random.uniform(start, start + 1*delta)
elif 2 <= i <= 3:
# random in the 2nd part
x = random.uniform(start + 1*delta, start + 2*delta)
elif 4 <= i <= 6:
# random in the 3rd part
x = random.uniform(start + 2*delta, start + 3*delta)
...
elif (k**2 – k + 2)/2 <= i <= (k**2 + k)/2:
# random in the kth part
x = random.uniform(start + (k-1)*delta, start + k*delta)
The question is always how to stop using ... in the program, but to make something that runs when the parameters are provided (start is the beginning of an interval, end is the end of the interval and k is in fact the number of parts into which we separate this interval).
Basically, we sample more and more as we move away from the origin of the interval.
I'm completely stuck on a task in one of the exercises we've been given however and was hoping someone could help me with it.
The following is the actual task:
Consider the sequence: x(n+1)= 0.2x(n)−α(x(n)^2−5) with x(0)=
1 for α successively equal to -0.5, +0.5, -0.25, +0.25.
Check the convergence; if the sequence converges, print the message Sequence converged to x= (the value you got) otherwise print No convergence detected
Check whether there are negative elements in the sequence
(Hint: If |xn−xn−1| < 10−9 consider a sequence to be convergent)
I'm not sure how to do sequences in python though and haven't found anything that explains how via googling so have been unsuccessful in trying to do it so far. After numerous attempts, I'm completely stuck.
This is the code I've done:
conv = [-0.5, 0.5, -0.25, 0.25]
b=0
a=conv[b]
c=0
for x in conv:
x1=0.2*x-a*((x**2)-5)
if abs(x1 - x) < 1.e-9:
c += 1
x = x1
b += 1
if c > 0:
print('Sequence converged to x=' + x)
if c === 0:
print('No converge detected')
You need to loop over the values in your "conv" list, assigning them to a, like "for a in conv:". Each iteration of the loop is a sequence as defined by a different "a" value. Then inside that loop, another loop like:
for a in conv:
convergence_determined = False
n = 0
x = 1 # this is x(0) for this sequence
while not convergence_determined:
prev_x = x
n = n += 1
next_x = 0.2 * x - a * (x * x - 5)
x = next_x
if abs(x - prev_x) < 1.e-9:
convergence_determined = True
print('for a = ' + str(a) + ', converged to ' + str(x))
break
# you will need some scheme to identify non-convergence
This is not tested code, just to give you an idea of how to proceed.
The procedure is called 'fixed-point iteration'. The question is similar to this SO question, asked yesterday (and likely others).
The sequence definition shows a as a constant. Indeed, letting a vary for a given sequence in the way indicated makes no sense as it would guarantee non-convergence. The instructor's notation is sloppy, but I am sure that the intent is for students to run 4 iterations, one for each value of a1. (I say this also because I know what fixed-point iteration behaviors are illustrated by the particular choices for a.)
The code below mixes my answer from the link above with the update code from this question. N is chosen as large enough for this problem (I started larger). Charon, I leave it to you to use the results to answer the questions posed by the instructor.
for a in [-0.5, 0.5, -0.25, 0.25]:
x = 1.0
n = 30
for i in range(n):
x1 = 0.2*x - a*(x**2 - 5)
print(i, x) # remove before submitting
if abs(x1 - x) < 1.e-9:
print('a = {a}, n = {i}, result is {x}.'.format(a=a, i=i, x=x))
break
x = x1
else:
print('No convergence within {n} iterations.'.format(n=n))
I want to know how to automate this part:
if n + list1[0] == list2[0] and n + list1[1] == list2[1] and n + list1[2] == list2[2]:
In this code:
def find_first_match(amount_of_checks):
for n in range(range_start, range_end):
if n + list1[0] == list2[0] and n + list1[1] == list2[1] and n + list1[2] == list2[2]:
first_match = n
return first_match
Meaning perform specified amount of n + list1[index] == list2[index] checks automatically, instead of manually hard-coding those 3 comparing statements in there. And not loose any performance?
I tried to replace this hard-coded if statement with this code down below, but it's a few times slower than the hardcoded way:
if all((n + a == b) for a, b in zip(list1[:amount_of_checks], list2[:amount_of_checks])):
So is there a way to:
make it not hard-coded (use a variable's value to generate specified amount of check)
retain performance
Update:
The first list is always the same, the second list always has random values, so I want it to go through the specified range of numbers n (100, 101, 102, ...) and find the first n that would satisfy ALL the checks (find the 2nd list that has the same values as the first list)
I want it to work with all the operations, like +,-,*,/,% etc
if all((n % a == b) for a, b in zip(list1[:amount_of_checks], list2[:amount_of_checks]))
This code is slow because the slices list1[:amount_of_checks] and list2[:amount_of_checks] iterate amount_of_checks times to create sublists that get thrown away. It's particularly unfortunate when (n % a == b) evaluates to False on an early iteration because all is happy to shorcut evaluation in these situations, but you've already paid the performance penalty in the sublist creation.
Use itertools.islice to avoid the performance penalty of creating the sublists:
zip(islice(list1, amount_of_checks), islice(list2, amount_of_checks))
This can be streamlined by switching the order or zip and islice
islice(zip(list1, list2), amount_of_checks)
Put it all together and you get
if all((n % a == b) for a, b in islice(zip(list1, list2), amount_of_checks))
I think you are missing a key point here. You do not need to guess the size of your delta. You can rearrange n + list1[x] == list2[x] to read n == list2[x] - list1[x]. This way, there is only one or no values of n which make all the elements you want to compare equal to each other. You can do something like:
def find_n(amount_of_checks, list1, list2):
deltas = set(a - b for a, b in zip(list1[:amount_of_checks], list2[:amount_of_checks]))
if len(deltas) == 1:
return next(deltas)
This is a very simplified approach. One improvement that might help with performance would be to use itertools.islice instead of the index [1:amount_of_checks] since that would avoid allocating a new pair of lists.
Your original code only allows n within a certain range. If this is something you want and not just an artifact, you can add that test as well:
def find_n(amount_of_checks, list1, list2, n_start, n_end):
deltas = set(b - a for a, b in zip(list1[1:amount_of_checks], list2[1:amount_of_checks]))
if len(deltas) == 1:
n = next(deltas)
if n >= n_start and n < n_end:
return next(deltas)
Update in response to your update
You should be able to write all the operations besides modulo in the same way:
For n - list1[x] == list2[x], use deltas = set(a + b ...
For n * list1[x] == list2[x], use deltas = set(b / a ...
For n / list1[x] == list2[x], use deltas = set(b * a ...
For n**list1[x] == list2[x], use deltas = set(b ** (1 / a) ...
etc.
The problem with modulo is that it does not have a unique inverse operation. I do not remember enough number theory at this point to say if there will be a faster solution than just using #Steven's answer using a direct application of all, islice and zip, but I suspect not.
Use the builtin all function
if all(list1[i]-list2[i]==n for i in range(start, end)):
# Whatever you want to do
if all([(n + list1[i] == list2[i]) for i in range(start, end)]):
# ...
Just change start and end according to your range
However, of course this isn't quite as fast as writing out all the conditions by hand. If we measure execution time using timeit with some sample values, it becomes obvious:
timeit.timeit('all([(2 + 1 == 3) for _ in range(0, 5)])', number=10000)
> 0.008927443002903601
timeit.timeit('2 + 1 == 3 and 2 + 1 == 3 and 2 + 1 == 3 and 2 + 1 == 3 and 2 + 1 == 3', number=10000)
> 0.0011130370003229473
so keep that in mind (since I don't know how high your performance needs are)
I was trying to calculate value of pi using this formula:
I had written this code for finding it for a given n:
def pisum(n):
sum=3.0
x=2.0
while (n>0):
if n%2==1:
sum=sum+(4/(x*(x+1)*(x+2)))
else :
sum=sum-(4/(x*(x+1)*(x+2)))
x=x+2
n=n-1
return str(sum)
It runs fine for n=0 and n=1 and gives output 3.0, 3.16666666667. But for n=50 the output should be 3.1415907698497954 but it is giving 2.85840923015. Why so much difference? Please help to correct if i had done something wrong.
The problem is that you are using n%2 in order to determine whether to subtract or add. It is not the amount of loops that you start with that should matter, but which loop you're in. To see that, try using your function for an odd number, e.g. 51 and you will see that it will give you a correct answer.
To explain further, if you start with n=50, you will initially subtract (4/(x*(x+1)*(x+2))) from 3 rather than add to it, but if you start with n=51, you will initially add.
If you modify your function as follows:
def pisum(n):
sum = 3.0
x = 2.0
for i in range(n):
if i % 2 == 0:
sum = sum + (4 / (x * (x + 1) * (x + 2)))
else:
sum = sum - (4 / (x * (x + 1) * (x + 2)))
x = x + 2
return str(sum)
you will always get a correct result.
You made a small mistake.
One correct program:
def pisum(n):
sum = 3.
for i in xrange(2, 2*n+2, 2):
sum += (4. if (i&2) == 2 else -4.)/i/(i+1)/(i+2)
return sum
Being more conservative with number of lines:
def pisum(n):
return 3. + sum([(4. if (i&2) == 2 else -4.)/i/(i+1)/(i+2) for i in xrange(2,2*n+2,2)])
Mistake in yours:
You are iterating on n in reverse, thus one time (odd value of n) you are calculating:
and for another value of n (even value apart from 0) you are calculating
I'm working on a homework assignment that asks me to create a Pascal Triangle using a recursive function. Below is what I've managed so far along with what I was given to work with. I'm quite new to Python and programming so I've got no idea where to head from here, any help would be appreciated!
def combination(n, k):
print((n - 1) / (k - 1)) + ((n - 1) / k)
def pascals_triangle(rows):
for row in range(rows):
answer = ""
for column in range(row + 1):
answer = answer + combination(row, column) + "\t"
print(answer)
pascals_triangle(5)
You are not, in fact, using recursion at all in your answer. I think you are trying to code the formula nCk = (n-1)C(k-1) + (n-1)Ck. You need, therefore, to call combination from within itself (with a guard for the "end" conditions: nC0 = nCn = 1):
def combination(n, k):
if k == 0 or k == n:
return 1
return combination(n - 1, k - 1) + combination(n - 1, k)
def pascals_triangle(rows):
for row in range( rows):
answer = ""
for column in range( row + 1):
answer = answer + str(combination(row, column)) + "\t"
print(answer)
pascals_triangle(5)
Output:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
Note that this is a spectacularly inefficient way of doing this: you are calling combination many, many times with the same arguments each time you get a binomial coefficient. You might consider caching the coefficients you find as you go along.
The other problem with your code is that your combination function wasn't actually returning anything, it was simply printing a value and exiting (returning None).