Dynamic programming solution for 2d subset sum - algorithm

So i have this problem: given a set of two dimensional tuples on the form {x,y}, where all x and y are positive integers, decide if it is possible to take out a subset so that:
√( (∑x)² + (∑y)²) = A²
For a positive integer A.
Example, given
[{2,2},{1,4},{1,2}] and A = 5
one solution is {2,2} and {1,2} since 3² + 4² = 5²
It is allowed to reuse the same tuple multiple times.
The goal is th solve this with dynamic programming. I was looking at http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/, a dynamic solution of a subset sum problem; however the difference here is that all the terms are squared and 2d, so i don't believe that method works

There may be faster options, but a simple PD is:
T(X, Y, i): Is it possible to achieve the ∑x = X and ∑y = Y using up to the i-th term?
T(0, 0, 0) = TRUE
T(X, Y, i) = FALSE if X<0 or Y<0 or (i==0 and X!=0 and Y!=0)
T(X, Y, i) = T(X-V[i].X, Y-V[i].Y, i) or T(X, Y, i-1)
Then, scan every pair (X, Y), to find one that X²+Y²=A² and T(X, Y, n) is true (where n is the size of the set).
Here is a non-optimized recursive version just to prove the concept (in Python):
def T(V, x, y, i):
if x==0 and y==0 and i==0: return []
if x<0 or y<0 or i<=0: return None
answer = T(V, x-V[i-1][0], y-V[i-1][1], i)
if answer is not None: return answer + [V[i-1]]
return T(V, x, y, i-1)
def solve(V, A):
for x in range(A):
for y in range(A):
if x*x+y*y==A*A:
answer = T(V, x, y, len(V))
if answer:
return answer
return None
print(solve([(2,2),(1,4),(1,2)], 5))
It prints one possible solution:
[(2, 2), (1, 2)]

Related

Algorithm for selecting the differents pair

May be somebody can help me with it.
So, I have a set of pairs x0-y0, x1-y1, etc.
And always x[i]<y[i]. Thus I need a function (or algorithm) for every pair, so
F(x[i],y[i]) = result[i], and each result for a particular pair must be an integer unique value.
Let M = max(y) - min(y) + 1, then use the formula:
F(x, y) = x * M + y
Remarks:
You don't have to use the exact maximum and minimum, you can use an upperbound and a lowerbound, M = U - L + 1 with U larger than all y and L smaller than all y;
Of course you could do it the other way around instead, with K = max(x) - min(x) + 1, and F(x, y) = y * K + x;
When using a finite integer type, be careful with overflow, for instance if x and y both have values larger than 46340, then F(x, y) won't fit in a 32-bit signed integer.

Find a number for minimum sum of nth power of absolute difference in an array

My question is similar to this, but instead if the absolute difference is raised to a power 'c' (which will be given as input) is there an algorithm to find the answer?
For example, given A = {a1, a2,...., an} and c it should find an x such that it minimises |a1 − x|^c +|a2 − x|^c +··· +|an − x|^c.
If c = 1 it's the median of the sorted array and if c = 2 it's the average of the array, but I can't find connection between median and average which we can extend to any value of c.
I assume that c is a positive integer.
If it is not an integer, then the fractional powers are hard to calculate. If it is negative, then as x goes to infinity (either way) the result goes to 0, so there is no global minimum. If it is 0, then x does not matter. So a positive integer is the only thing that makes sense.
Now each term is a convex function. The sum of convex functions is itself convex. Convex functions have the following properties. Suppose that x < y < z. If f(x) = f(z) then the global minimum is between them. If f(x) = f(y) = f(z), that's a straight line segment. And finally, if f(y) < min(f(x), f(z)) then the global minimum is between x and z.
This is sufficient for a variation on binary search.
while z - x > some tolerance:
if z-y > y-x:
y1 = (y + z) / 2
if f(y1) < f(y):
(x, y, z) = (y, y1, z)
elif f(y1) = f(y):
(x, y, z) = (y1, (2*y1 + y)/3, y)
else:
(x, y, z) = (y1, y, z)
else:
y1 = (x + y) / 2
if f(y1) < f(y):
(x, y, z) = (x, y1, y)
elif f(y1) = f(y):
(x, y, z) = (y1, (2*y1 + y)/3, y)
else:
(x, y, z) = (y1, y, z)
As this runs, each iteration reduces the size of the interval to at most 3/4 of what it previously was. And therefore you will narrow in on the answer.
If you special case c = 1, you can do even better. The second derivative will be defined everywhere and be a non-decreasing function. This allows you to do a binary search, but guess where in the interval the minimum is expected to be. If you land close, you know which way you're wrong, and can put a much tighter bound on it.

calculate x ^ (1 / y) mod m fast (modular root)

How can I solve x ^ ( 1 / y ) mod m fast, where x, y, m are all positive integers?
This is to reverse the calculation for x ^ y mod m. For example
party A hands party B agree on positive integer y and m ahead of time
party A generates a number x1 (0 < x1 < m), and hands party B the result of x1 ^ y mod m, call it x2
party B calculates x2 ^ ( 1 / y ) mod m, so that it gets back x1
I know how to calculate x1 ^ y mod m fast, but I don't know how to calculate x2 ^ (1 / y) mod m fast. Any suggestions?
I don't know how to call this question. Given x ^ y mod m is called modular exponentiation, is this called modular root?
I think you're asking this question: Given y, m, and the result of x^y (mod m) find x (assuming 0 <= x < m).
In general, this doesn't have a solution -- for example, for y=2, m=4, 0^2, 1^2, 2^2, 3^2 = 0, 1, 0, 1 (mod 4), so if you're given the square of a number mod 4, you can't get back the original number.
However, in some cases you can do it. For example, when m is prime and y is coprime to m-1. Then one can find y' such that for all 0 <= x < m, (x^y)^y' = x (mod m).
Note that (x^y)^y' = x^(yy'). Ignoring the trivial case when x=0, if m is prime Fermat's Little Theorem tells us that x^(m-1) = 1 (mod m). Thus we can solve yy' = 1 (mod m-1). This has a solution (which can be found using the extended Euclidean algorithm) assuming y and m-1 are coprime.
Here's working code, with an example with y=5, m=17. It uses the modular inverse code from https://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm
def egcd(a, b):
if a == 0: return b, 0, 1
g, x, y = egcd(b%a, a)
return g, y - (b//a) * x, x
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise AssertionError('no inverse')
return x % m
def encrypt(xs, y, m):
return [pow(x, y, m) for x in xs]
def decrypt(xs, y, m):
y2 = modinv(y, m-1)
return encrypt(xs, y2, m)
y = 5
m = 17
e = encrypt(range(m), y, m)
print decrypt(e, y, m)
RSA is based on the case when m is the product of two distinct primes p, q. The same ideas as above apply, but one needs to find y' such that yy' = 1 (mod lcm((p-1)(q-1))). Unlike above, one can't do this easily only given y and m, because there are no known efficient methods for finding p and q.

Need a recursive version of the Euclid's algorithm

I have a task where I have the algorithm of Euclid and need to make a recursive version of it. I can't really get what the recursive version of an algorithm is actually, so any help here would be very appreciated! :)
The given algorithm is:
X ← MAX
Y ← MIN
while (Y != 0){
mod ← X mod Y
X ← Y
Y ← mod}
GCD ← X
The recursion is actually very similar to the iterative
GCD(X,Y):
if Y == 0:
return X
else:
return GCD(Y, X mod Y)
Here I assume X >= Y > 0,
Essentially the recursion is solving the problem with a smaller X' and Y' until the answer is obvious(Here X' = Y and Y' = X % Y).
The recursive version algorithm of Euclid for solving Greatest Common Divisor(GCD) is (C version) :
int GCD(X, Y)
{
if ((X % Y) == 0)
{
return Y;
}
else
{
return GCD(Y, X % Y);
}
}

Number of different solutions of xy+yz+ xz = N

I have been trying to solve a problem on spoj.
Here is the link to the problem.
http://www.spoj.pl/problems/TAP2012B/
From what I have interpreted, I need to find the number of solutions of the equation xy+yz+xz = N
where n is given to us.
x>=y>=z
z can be zero.
But x and y cannot.
I tried doing solving this via implementing 3 for loops (bad approach).
It is giving the right answer but it is too slow.
Also, other people have solved it in almost no time (0.00)
So I am sure there is a very different approach to this problem.
For N = 20,
the number of different solutions is 5 :
(6,2,1)
(5,4,0)
(10,2,0)
(4,2,2,)
(20,1,0)
Maybe there is some brillian solution built on number-theory. But simply rethinking the task can reduce algorithm complexity as well.
For instance, we don't need a third loop as we can calculate z as (N - x*y)/(x+y). And we don't have to run y all the way to x every time, as we know, that z is not negative, therefore N >= xy.
N = 9747
for x in range(1, N+1):
max_y = min( N / x, x)
for y in range(1, max_y+1):
if (N - x*y) % (x+y) == 0:
z = (N - x*y) / (x+y)
if z <= y:
print x,y,z
You are approaching towards the right direction there will be 3 nested loops but try to reduce the no. of times the loop operates.... Follow the question and conditions carefully.....
You are obviously learning, so it would have had been better if you would do everything yourself, but you now have a great solution from akalenuk, and I hope that you will learn a few things from it as well.
If you are learning python at the same time, I will give you an equivalent solution to akalenuk's, but this time with list comprehension which is a very useful mechanism:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, min( N/x, x) + 1 )
for z in [ (N - x*y) / (x+y) ]
if (N - x*y) % (x+y) == 0
if z <= y]
The point is in pruning the solution space. The code above is already quite optimised. You might start with something like:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, x+1 )
for z in range(y+1)
if N == x*y + y*z + x*z]
This would run quite long. So, the first point of optimization may be adding the condition on y:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, x+1 )
if x*y <= N
for z in range(y+1)
if N == x*y + y*z + x*z]
This already cuts down the time considerably, as for non-promising y the z-loop is not run at all. Then, you notice that you may actually replace that if-statement by explicit computation of maximum y, as akalenuk did:
N = 10000
print [(x, y, z)
for x in range(1, N+1)
for y in range(1, min(x, N/x) +1)
for z in range(y+1)
if N == x*y + y*z + x*z]
This will again speed it up.
As you are learning, I recommend you try all these, and your own, time it, and learn from it.
I also recommend to try and time different, similar solutions

Resources