Create a Recursive Function as Well as a Closed Function Definition - python-3.x

The goal of this assignment is to take the recurrence relation given at the bottom, and then create a recursive function under recFunc(n), as well as a closed function definition underneath nonRecFunc(n). A closed function means our function should solely depend on n, and that its output should
match the recursive function's exactly. Then, find the value for n = 15 and n = 20, and use it as instructed below. You should probably need to use a characteristic equation to solve this problem.
What is the value for nonRecFunc(20) (divided by) nonRecFunc(15), rounded to the nearest integer.
Problem:
Solve the recurrence relation a_n = 12a_n-1 - 32a_n-2 with initial conditions a_0 = 1 and a_1 = 4.
I am confused as to how I should attack this problem and how I can use recursion to solve the issue.
def recFunc(n):
if n == 0:
return 1
elif n == 1:
return 2
else:
return recFunc(n - 1) + 6 * recFunc(n - 2)
def nonRecFunc(n):
return 4/5 * 3 ** n + 1/5 * (-2) ** n
for i in range(0,10):
print(recFunc(i))
print(nonRecFunc(i))
print()

As mentioned in a my comment above, I leave the recursive solution to you.
For the more mathematical question of the non-recursive solution consider this:
you have
x_n = a x_(n-1) + b x_(n-2)
This means that the change of x is more or less proportional to x as x_n and x_(n-1) will be of same order of magnitude. In other words we are looking for a function type giving
df(n)/dn ~ f(n)
This is something exponential. So the above assumption is
x_n = alpha t^n + beta s^n
(later when solving for s and t the motivation for this becomes clear) from the start values we get
alpha + beta = 1
and
alpha t + beta s = 2
The recursion provides
alpha t^n + beta s^n = a ( alpa t^(n-1) + beta s^(n-1) ) + b ( alpa t^(n-2) + beta s^(n-2) )
or
t^2 alpha t^(n-2) + s^2 beta s^(n-2) = a ( t alpa t^(n-2) + s beta s^(n-2) ) + b ( alpa t^(n-2) + beta s^(n-2) )
This equation holds for all n such that you can derive an equation for t and s.
Plugging in the results in the above equations gives you the non-recursive solution.
Try to reproduce it and then go for the actual task.
Cheers.

Related

Splitting an int64 into two int32, performing math, then re-joining

I am working within constraints of hardware that has 64bit integer limit. Does not support floating point. I am dealing with very large integers that I need to multiply and divide. When multiplying I encounter an overflow of the 64bits. I am prototyping a solution in python. This is what I have in my function:
upper = x >> 32 #x is cast as int64 before being passed to this function
lower = x & 0x00000000FFFFFFFF
temp_upper = upper * y // z #Dividing first is not an option, as this is not the actual equation I am working with. This is just to make sure in my testing I overflow unless I do the splitting.
temp_lower = lower * y // z
return temp_upper << 32 | lower
This works, somewhat, but I end up losing a lot of precision (my result is off by sometimes a few million). From looking at it, it appears that this is happening because of the division. If sufficient enough it shifts the upper to the right. Then when I shift it back into place I have a gap of zeroes.
Unfortunately this topic is very hard to google, since anything with upper/lower brings up results about rounding up/down. And anything about splitting ints returns results about splitting them into a char array. Anything about int arithmetic bring up basic algebra with integer math. Maybe I am just not good at googling. But can you guys give me some pointers on how to do this?
Splitting like this is just a thing I am trying, it doesnt have to be the solution. All I need to be able to do is to temporarily go over 64bit integer limit. The final result will be under 64bit (After the division part). I remember learning in college about splitting it up like this and then doing the math and re-combining. But unfortunately as I said I am having trouble finding anything online on how to do the actual math on it.
Lastly, my numbers are sometimes small. So I cant chop off the right bits. I need the results to basically be equivalent to if I used something like int128 or something.
I suppose a different way to look at this problem is this. Since I have no problem with splitting the int64, we can forget about that part. So then we can pretend that two int64's are being fed to me, one is upper and one is lower. I cant combine them, because they wont fit into a single int64. So I need to divide them first by Z. Combining step is easy. How do I do the division?
Thanks.
As I understand it, you want to perform (x*y)//z.
Your numbers x,y,z all fit on 64bits, except that you need 128 bits for intermediate x*y.
The problem you have is indeed related to division: you have
h * y = qh * z + rh
l * y = ql * z + rl
h * y << 32 + l*y = (qh<<32 + ql) * z + (rh<<32 + rl)
but nothing says that (rh<<32 + rl) < z, and in your case high bits of l*y overlap low bits of h * y, so you get the wrong quotient, off by potentially many units.
What you should do as second operation is rather:
rh<<32 + l * y = ql' * z + rl'
Then get the total quotient qh<<32 + ql'
But of course, you must care to avoid overflow when evaluating left operand...
Since you are splitting only one of the operands of x*y, I'll assume that the intermediate result always fits on 96 bits.
If that is correct, then your problem is to divide a 3 32bits limbs x*y by a 2 32bits limbs z.
It is thus like Burnigel - Ziegler divide and conquer algorithm for division.
The algorithm can be decomposed like this:
obtain the 3 limbs a2,a1,a0 of multiplication x*y by using karatsuba for example
split z into 2 limbs z1,z0
perform the div32( (a2,a1,a0) , (z1,z0) )
here is some pseudo code, only dealing with positive operands, and with no guaranty to be correct, but you get an idea of implementation:
p = 1<<32;
function (a1,a0) = split(a)
a1 = a >> 32;
a0 = a - (a1 * p);
function (a2,a1,a0) = mul22(x,y)
(x1,x0) = split(x) ;
(y1,y0) = split(y) ;
(h1,h0) = split(x1 * y1);
assert(h1 == 0); -- assume that results fits on 96 bits
(l1,l0) = split(x0 * y0);
(m1,m0) = split((x1 - x0) * (y0 - y1)); -- karatsuba trick
a0 = l0;
(carry,a1) = split( l1 + l0 + h0 + m0 );
a2 = l1 + m1 + h0 + carry;
function (q,r) = quorem(a,b)
q = a // b;
r = a - (b * q);
function (q1,q0,r0) = div21(a1,a0,b0)
(q1,r1) = quorem(a1,b0);
(q0,r0) = quorem( r1 * p + a0 , b0 );
(q1,q0) = split( q1 * p + q0 );
function q = div32(a2,a1,a0,b1,b0)
(q,r) = quorem(a2*p+a1,b1*p+b0);
q = q * p;
(a2,a1)=split(r);
if a2<b1
(q1,q0,r)=div21(a2,a1,b1);
assert(q1==0); -- since a2<b1...
else
q0=p-1;
r=(a2-b1)*p+a1+b1;
(d1,d0) = split(q0*b0);
r = (r-d1)*p + a0 - d0;
while(r < 0)
q = q - 1;
r = r + b1*p + b0;
function t=muldiv(x,y,z)
(a2,a1,a0) = mul22(x,y);
(z1,z0) = split(z);
if z1 == 0
(q2,q1,r1)=div21(a2,a1,z0);
assert(q2==0); -- otherwise result will not fit on 64 bits
t = q1*p + ( ( r1*p + a0 )//z0);
else
t = div32(a2,a1,a0,z1,z0);

Solve for x using python

I came across a problem. One string is taken as input say
input_string = "12345 + x = x * 5 + (1+x)* x + (1+18/100)"
And get output of x using python. I am not able to figure out logic for this.
Here is a complete SymPy example for your input:
from sympy import Symbol, solve, Eq
from sympy.parsing.sympy_parser import parse_expr
input_string = "12345 + x = x * 5 + (1+x)* x + (1+18/100)"
x = Symbol('x', real=True)
lhs = parse_expr(input_string.split('=')[0], local_dict={'x':x})
rhs = parse_expr(input_string.split('=')[1], local_dict={'x':x})
print(lhs, "=", rhs)
sol = solve(Eq(lhs, rhs), x)
print(sol)
print([s.evalf() for s in sol])
This outputs:
x + 12345 = x*(x + 1) + 5*x + 59/50
[-5/2 + 9*sqrt(15247)/10, -9*sqrt(15247)/10 - 5/2]
[108.630868798908, -113.630868798908]
Note that solve() gives a list of solutions. And that SymPy normally does not evaluate fractions and square roots, as it prefers solutions without loss of precision. evalf() evaluates a float value for these expressions.
Well, that example shows a quadratic equation which may have no solutions, one solution, or two solutions. You would have to rearrange the terms symbolically to come to
input_string = "x**2 + 5*x - 12345 + (118/100)"
But that means you need to implement rules for multiplication, addition, subtraction and potentially division. At least for Python there is a library called SymPy which can parse such strings and provide an expression that you can evaluate and even solve.

Exponential sum using recursion in Python

I found here: exponential sum using recursion.python
Exactly the same problem with the same conditions to implement.
A brief description: We have started studying recursion and got some questions to solve using only recursion without any loop.
So we are asked to write a function calculating the exponential sum.
So here are my tries:
def exp_n_x(n, x):
if n <= 0:
return 1
return (x/n)*exp_n_x(n-1, x)
It actually only calculates the n'th one, without summing up the others to i=0.
I tried to make the function sum every exponential element so:
def exp_n_x(n, x):
if n <= 0:
return 1
sum = (x/n)*exp_n_x(n-1, x)
n = n - 1
return sum + (x/n)*exp_n_x(n-1, x)
But it doesn't help me...
Thanks.
You are pretty close to a solution in the first function, but you are missing two critical things: you need to raise x to the power of n and divide it by n! (n-factorial). The factorial function is the product of all integers from 1 to n, with a special case that 0! is 1. Also, you are creating a product when you need a sum. Putting these together you have:
def factorial(n):
if n < 2:
return 1
return n * factorial(n - 1)
def exp_n_x(n, x):
if n < 1:
return 1
return x ** n / factorial(n) + exp_n_x(n - 1, x)
I think your problem is that the sum you're computing has terms that can be computed from the previous terms, but not (as far as I can see) from the previous sums. So you may need to have two separate recursive parts to your code. One computes the values of the next term based on the previous term, and one that adds the new term to the previous sum.
def term(n, x):
if n <= 0:
return 1
return x / n * term(n-1, x)
def exp_sum(n, x):
if n <= 0:
return 1
return exp_sum(n-1, x) + term(n, x)
This is hideously inefficient, since the terms for the smaller n values get computed over and over. But that's probably OK for learning about recursion (I expect you'll learn about ways to avoid this issue with memoziation or dynamic programming eventually).
Note that you can combine the two functions into one, as long as you don't mind changing the function signature and returning two values at once (in a tuple) from the recursion. You could add a non-recursive helper function to make the user-facing function work as expected:
def exp_sum_recursive(n, x): # this function returns term, sum tuples
if n <= 0:
return 1, 1
term, sum = exp_sum_recursive(n-1, x)
term *= x / n # each new term is based off of the previous term
return term, sum + term # the new sum adds the new term to the old sum
def exp_sum(n, x): # this is a non-recursive helper function
return exp_sum_recursive(n, x)[1] # it only returns the sum from the recursive version
Since you've achieved recursion with exp_n_x() why throw an inefficient recursive factorial() in the mix when Python already provides us with one:
from math import factorial
def exp_n_x(n, x):
return 1 if n < 1 else x ** n / factorial(n) + exp_n_x(n - 1, x)

Python implementation of bilinear quadrilateral interpolation

I'm trying to perform bilinear quadrilateral interpolation. So I have four nodes with known values and I want to find a value that lies in between those four nodes by interpolation, but the four nodes do not form a rectangle. 4-node sketch
I found several ways to solve this, but none of them is implemented in Python already. Does there exist somewhere an already finished python implementation? If not which of the two solutions below would you recommend? Or would you recommend another approach?
**************Different solutions*******************
Solution 1:
I found here, https://www.colorado.edu/engineering/CAS/courses.d/IFEM.d/IFEM.Ch16.d/IFEM.Ch16.pdf, that I should solve the following set of equations: set of equations with Ni being: N definition.
Finally this results in solving a set of equations of the form:
a*x+b*y+c*xy=z1
d*x+e*y+f*xy=z2
with x and y being the unknowns. This could be solved numerically using fsolve.
Solution 2:
This one is completely explained here: https://math.stackexchange.com/questions/828392/spatial-interpolation-for-irregular-grid
but it's quite complex and I think it will take me longer to code it.
Due to a lack of answers I went for the first option. You can find the code below. Recommendations to improve this code are always welcome.
import numpy as np
from scipy.optimize import fsolve
def interpolate_quatrilateral(pt1,pt2,pt3,pt4,pt):
'''Interpolates a value in a quatrilateral figure defined by 4 points.
Each point is a tuple with 3 elements, x-coo,y-coo and value.
point1 is the lower left corner, point 2 the lower right corner,
point 3 the upper right corner and point 4 the upper left corner.
args is a list of coordinates in the following order:
x1,x2,x3,x4 and x (x-coo of point to be interpolated) and y1,y2...
code based on the theory found here:
https://www.colorado.edu/engineering/CAS/courses.d/IFEM.d/IFEM.Ch16.d/IFEM.Ch16.pdf'''
coos = (pt1[0],pt2[0],pt3[0],pt4[0],pt[0],
pt1[1],pt2[1],pt3[1],pt4[1],pt[1]) #coordinates of the points merged in tuple
guess = np.array([0,0]) #The center of the quadrilateral seem like a good place to start
[eta, mu] = fsolve(func=find_local_coo_equations, x0=guess, args=coos)
densities = (pt1[2], pt2[2], pt3[2], pt4[2])
density = find_density(eta,mu,densities)
return density
def find_local_coo_equations(guess, *args):
'''This function creates the transformed coordinate equations of the quatrilateral.'''
eta = guess[0]
mu = guess[1]
eq=[0,0]#Initialize eq
eq[0] = 1 / 4 * (args[0] + args[1] + args[2] + args[3]) - args[4] + \
1 / 4 * (-args[0] - args[1] + args[2] + args[3]) * mu + \
1 / 4 * (-args[0] + args[1] + args[2] - args[3]) * eta + \
1 / 4 * (args[0] - args[1] + args[2] - args[3]) * mu * eta
eq[1] = 1 / 4 * (args[5] + args[6] + args[7] + args[8]) - args[9] + \
1 / 4 * (-args[5] - args[6] + args[7] + args[8]) * mu + \
1 / 4 * (-args[5] + args[6] + args[7] - args[8]) * eta + \
1 / 4 * (args[5] - args[6] + args[7] - args[8]) * mu * eta
return eq
def find_density(eta,mu,densities):
'''Finds the final density based on the eta and mu local coordinates calculated
earlier and the densities of the 4 points'''
N1 = 1/4*(1-eta)*(1-mu)
N2 = 1/4*(1+eta)*(1-mu)
N3 = 1/4*(1+eta)*(1+mu)
N4 = 1/4*(1-eta)*(1+mu)
density = densities[0]*N1+densities[1]*N2+densities[2]*N3+densities[3]*N4
return density
pt1= (0,0,1)
pt2= (1,0,1)
pt3= (1,1,2)
pt4= (0,1,2)
pt= (0.5,0.5)
print(interpolate_quatrilateral(pt1,pt2,pt3,pt4,pt))

Count the Number of Zero's between Range of integers

. Is there any Direct formula or System to find out the Numbers of Zero's between a Distinct Range ... Let two Integer M & N are given . if I have to find out the total number of zero's between this Range then what should I have to do ?
Let M = 1234567890 & N = 2345678901
And answer is : 987654304
Thanks in advance .
Reexamining the Problem
Here is a simple solution in Ruby, which inspects each integer from the interval [m,n], determines the string of its digits in the standard base 10 positional system, and counts the occuring 0 digits:
def brute_force(m, n)
if m > n
return 0
end
z = 0
m.upto(n) do |k|
z += k.to_s.count('0')
end
z
end
If you run it in an interactive Ruby shell you will get
irb> brute_force(1,100)
=> 11
which is fine. However using the interval bounds from the example in the question
m = 1234567890
n = 2345678901
you will recognize that this will take considerable time. On my machine it does need more than a couple of seconds, I had to cancel it so far.
So the real question is not only to come up with the correct zero counts but to do it faster than the above brute force solution.
Complexity: Running Time
The brute force solution needs to perform n-m+1 times searching the base 10 string for the number k, which is of length floor(log_10(k))+1, so it will not use more than
O(n (log(n)+1))
string digit accesses. The slow example had an n of roughly n = 10^9.
Reducing Complexity
Yiming Rong's answer is a first attempt to reduce the complexity of the problem.
If the function for calculating the number of zeros regarding the interval [m,n] is F(m,n), then it has the property
F(m,n) = F(1,n) - F(1,m-1)
so that it suffices to look for a most likely simpler function G with the property
G(n) = F(1,n).
Divide and Conquer
Coming up with a closed formula for the function G is not that easy. E.g.
the interval [1,1000] contains 192 zeros, but the interval [1001,2000] contains 300 zeros, because a case like k = 99 in the first interval would correspond to k = 1099 in the second interval, which yields another zero digit to count. k=7 would show up as 1007, yielding two more zeros.
What one can try is to express the solution for some problem instance in terms of solutions to simpler problem instances. This strategy is called divide and conquer in computer science. It works if at some complexity level it is possible to solve the problem instance and if one can deduce the solution of a more complex problem from the solutions of the simpler ones. This naturally leads to a recursive formulation.
E.g. we can formulate a solution for a restricted version of G, which is only working for some of the arguments. We call it g and it is defined for 9, 99, 999, etc. and will be equal to G for these arguments.
It can be calculated using this recursive function:
# zeros for 1..n, where n = (10^k)-1: 0, 9, 99, 999, ..
def g(n)
if n <= 9
return 0
end
n2 = (n - 9) / 10
return 10 * g(n2) + n2
end
Note that this function is much faster than the brute force method: To count the zeros in the interval [1, 10^9-1], which is comparable to the m from the question, it just needs 9 calls, its complexity is
O(log(n))
Again note that this g is not defined for arbitrary n, only for n = (10^k)-1.
Derivation of g
It starts with finding the recursive definition of the function h(n),
which counts zeros in the numbers from 1 to n = (10^k) - 1, if the decimal representation has leading zeros.
Example: h(999) counts the zero digits for the number representations:
001..009
010..099
100..999
The result would be h(999) = 297.
Using k = floor(log10(n+1)), k2 = k - 1, n2 = (10^k2) - 1 = (n-9)/10 the function h turns out to be
h(n) = 9 [k2 + h(n2)] + h(n2) + n2 = 9 k2 + 10 h(n2) + n2
with the initial condition h(0) = 0. It allows to formulate g as
g(n) = 9 [k2 + h(n2)] + g(n2)
with the intital condition g(0) = 0.
From these two definitions we can define the difference d between h and g as well, again as a recursive function:
d(n) = h(n) - g(n) = h(n2) - g(n2) + n2 = d(n2) + n2
with the initial condition d(0) = 0. Trying some examples leads to a geometric series, e.g. d(9999) = d(999) + 999 = d(99) + 99 + 999 = d(9) + 9 + 99 + 999 = 0 + 9 + 99 + 999 = (10^0)-1 + (10^1)-1 + (10^2)-1 + (10^3)-1 = (10^4 - 1)/(10-1) - 4. This gives the closed form
d(n) = n/9 - k
This allows us to express g in terms of g only:
g(n) = 9 [k2 + h(n2)] + g(n2) = 9 [k2 + g(n2) + d(n2)] + g(n2) = 9 k2 + 9 d(n2) + 10 g(n2) = 9 k2 + n2 - 9 k2 + 10 g(n2) = 10 g(n2) + n2
Derivation of G
Using the above definitions and naming the k digits of the representation q_k, q_k2, .., q2, q1 we first extend h into H:
H(q_k q_k2..q_1) = q_k [k2 + h(n2)] + r (k2-kr) + H(q_kr..q_1) + n2
with initial condition H(q_1) = 0 for q_1 <= 9.
Note the additional definition r = q_kr..q_1. To understand why it is needed look at the example H(901), where the next level call to H is H(1), which means that the digit string length shrinks from k=3 to kr=1, needing an additional padding with r (k2-kr) zero digits.
Using this, we can extend g to G as well:
G(q_k q_k2..q_1) = (q_k-1) [k2 + h(n2)] + k2 + r (k2-kr) + H(q_kr..q_1) + g(n2)
with initial condition G(q_1) = 0 for q_1 <= 9.
Note: It is likely that one can simplify the above expressions like in case of g above. E.g. trying to express G just in terms of G and not using h and H. I might do this in the future. The above is already enough to implement a fast zero calculation.
Test Result
recursive(1234567890, 2345678901) =
987654304
expected:
987654304
success
See the source and log for details.
Update: I changed the source and log according to the more detailed problem description from that contest (allowing 0 as input, handling invalid inputs, 2nd larger example).
You can use a standard approach to find m = [1, M-1] and n = [1, N], then [M, N] = n - m.
Standard approaches are easily available: Counting zeroes.

Resources