I have to write a recursive function (we'll call it arrow(n)) which draws an arrow that works like this:
arrow(4)
Printed output :
*
**
***
****
***
**
*
where arrow can only take one parameter like shown above.
Is it possible only by using one parameter with recursion? I'm curious because it was a test question and I can't find any solution.
Thanks
The recursion is in the helper functions, rather than arrow, but it's still single-parameter recursion in each case.
def arrow_top(n):
if n > 0:
arrow_top(n-1)
print('*' * n)
def arrow_bot(n):
if n > 0:
print('*' * n)
arrow_bot(n-1)
def arrow(n):
arrow_top(n)
arrow_bot(n-1)
arrow(4)
Output:
*
**
***
****
***
**
*
No, even when recursing, you'll need two variables (one to keep track of the current count, and another to keep track of the size).
You can get cute and use an inner function.
def arrow(n):
def _arrow(k, n):
print('*' * (n - k + 1))
if k > 1:
_arrow(k - 1, n)
print('*' * (n - k + 1))
_arrow(n, n)
arrow(4)
# *
# **
# ***
# ****
# ***
# **
# *
It's essentially the more unreadable equivalent of loops, but hey, that's the nature of exam questions.
This works by setting a global to remember where to iterate to:
def arrow(n):
# remember max, but only once
global top
try:
top
except NameError:
top = n
n = 1
if n < top:
print(n * '*')
arrow(n + 1)
print(n * '*')
elif n == top:
print(n * '*')
arrow(4)
Related
So, I'm trying to find the value of cos(x), where x=1.2. I feel the script I have written should be fine, however, the value I get out isn't correct. That is; cos(1.2)=0.6988057880877979, for 25 terms, when I should get out: cos(1.2)=0.36235775.
I have created a similar program for calculating sin(1.2) which works fine.
Calculating sin(1.2):
import math as m
x=1.2
k=1
N=25
s=x
sign=1.0
while k<N:
sign=-sign
k=k+2
term=sign*x**k/m.factorial(k)
s=s+term
print('sin(%g) = %g (approximation with %d terms)' % (x,s,N))
Now trying to calculate cos(1.2):
import math as m
x=1.2
k=1
N=25
s=x
sign=1.0
while k<N:
sign=-sign
k=k+1
term=sign*x**k/m.factorial(k)
s=s+term
print(s)
You shouldn't be setting your initial sum to 1.2, and your representation of the expansion
is a bit off - we need to account for the even-ness of the function, so increment k by 2. Also, without modifying your program structure, you'd have to set the initial variables so they are correctly put to their starting values at the beginning of the first loop. Re-ordering your loop control flow a bit, we have
import math as m
x=1.2
k=0
N=25
s=0
sign=1.0
while k<N:
term=sign*x**(k)/m.factorial(k)
s=s+term
k += 2
sign = -sign
print(s)
Gives
0.3623577544766735
I think you're using the wrong series for the cosine, the correct formula would be (I highlighted the important differences with ^):
sum_over_n [(-1)**n * x ** (2 * n) / (math.factorial(2 * n))]
# ^^^^ ^^^^
that means to add n-terms you have something like:
def cosine_by_series(x, terms):
cos = 0
for n in range(terms):
cos += ((-1)**n) * (x ** (2*n)) / (math.factorial(2 * n))
return cos
# or simply:
# return sum(((-1)**n) * (x ** (2*n)) / (math.factorial(2 * n)) for n in range(terms)
which gives:
>>> cosine_by_series(1.2, 30)
0.3623577544766735
I understand there is a erf (Wikipedia) function in python. But in this assignment we are specifically asked to write the error function as if it was not already implemented in python while using a while loop.
erf (x) is simplified already as : (2/ (sqrt(pi)) (x - x^3/3 + x^5/10 - x^7/42...)
Terms in the series must be added until the absolute total is less than 10^-20.
First of all - SO is not the place when people code for you, here people help you to solve particular problem not the whole task
Any way:
It's not too hard to implement wikipedia algorithm:
import math
def erf(x):
n = 1
res = 0
res1 = (2 / math.sqrt(math.pi)) * x
diff = 1
s = x
while diff > math.pow(10, -20):
dividend = math.pow((-1), n) * math.pow(x, 2 * n + 1)
divider = math.factorial(n) * (2 * n + 1)
s += dividend / divider
res = ((2 / math.sqrt(math.pi)) * s)
diff = abs(res1 - res)
res1 = res
n += 1
return res
print(erf(1))
Please read the source code carefully and post all questions that you don't understand.
Also you may check python sources and see how erf is implemented
I want to solve an equation which I am supposed to solve it recursively, I uploaded the picture of formula (Sorry! I did not know how to write mathematical formulas here!)
I wrote the code in Python as below:
import math
alambda = 1.0
rho = 0.8
c = 1.0
b = rho * c / alambda
P0 = (1 - (alambda*b))
P1 = (1-(alambda*b))*(math.exp(alambda*b) - 1)
def a(n):
a_n = math.exp(-alambda*b) * ((alambda*b)**n) / math.factorial(n)
return a_n
def P(n):
P(n) = (P0+P1)*a(n) + sigma(n)
def sigma(n):
j = 2
result = 0
while j <= n+1:
result = result + P(j)*a(n+1-j)
j += 1
return result
It is obvious that I could not finish P function. So please help me with this.
when n=1 I should extract P2, when n=2 I should extract P3.
By the way, P0 and P1 are as written in line 6 and 7.
When I call P(5) I want to see P(0), P(1), P(2), P(3), P(4), P(5), P(6) at the output.
You need to reorganize the formula so that you don't have to calculate P(3) to calculate P(2). This is pretty easy to do, by bringing the last term of the summation, P(n+1)a(0), to the left side of the equation and dividing through by a(0). Then you have a formula for P(n+1) in terms of P(m) where m <= n, which is solvable by recursion.
As Bruce mentions, it's best to cache your intermediate results for P(n) by keeping them in a dict so that a) you don't have to recalculate P(2) etc everytime you need it, and b) after you get the value of P(n), you can just print the dict to see all the values of P(m) where m <= n.
import math
a_lambda = 1.0
rho = 0.8
c = 1.0
b = rho * c / a_lambda
p0 = (1 - (a_lambda*b))
p1 = (1-(a_lambda*b))*(math.exp(a_lambda*b) - 1)
p_dict = {0: p0, 1: p1}
def a(n):
return math.exp(-a_lambda*b) * ((a_lambda*b)**n) / math.factorial(n)
def get_nth_p(n, p_dict):
# return pre-calculated value if p(n) is already known
if n in p_dict:
return p_dict[n]
# Calculate p(n) using modified formula
p_n = ((get_nth_p(n-1, p_dict)
- (get_nth_p(0, p_dict) + get_nth_p(1, p_dict)) * a(n - 1)
- sum(get_nth_p(j, p_dict) * a(n + 1 - j) for j in xrange(2, n)))
/ a(0))
# Save computed value into the dict
p_dict[n] = p_n
return p_n
get_nth_p(6, p_dict)
print p_dict
Edit 2
Some cosmetic updates to the code - shortening the name and making p_dict a mutable default argument (something I try to use only sparingly) really makes the code much more readable:
import math
# Customary to distinguish variables that are unchanging by making them ALLCAP
A_LAMBDA = 1.0
RHO = 0.8
C = 1.0
B = RHO * C / A_LAMBDA
P0 = (1 - (A_LAMBDA*B))
P1 = (1-(A_LAMBDA*B))*(math.exp(A_LAMBDA*B) - 1)
p_value_cache = {0: P0, 1: P1}
def a(n):
return math.exp(-A_LAMBDA*B) * ((A_LAMBDA*B)**n) / math.factorial(n)
def p(n, p_dict=p_value_cache):
# return pre-calculated value if p(n) is already known
if n in p_dict:
return p_dict[n]
# Calculate p(n) using modified formula
p_n = ((p(n-1)
- (p(0) + p(1)) * a(n - 1)
- sum(p(j) * a(n + 1 - j) for j in xrange(2, n)))
/ a(0))
# Save computed value into the dict
p_dict[n] = p_n
return p_n
p(6)
print p_value_cache
You could fix if that way:
import math
alambda = 1.0
rho = 0.8
c = 1.0
b = rho * c / alambda
def a(n):
# you might want to cache a as well
a_n = math.exp(-alambda*b) * ((alambda*b)**n) / math.factorial(n)
return a_n
PCache={0:(1 - (alambda*b)),1:(1-(alambda*b))*(math.exp(alambda*b) - 1)}
def P(n):
if n in PCache:
return PCache[n]
ret= (P(0)+P(1))*a(n) + sigma(n)
PCache[n]=ret
return ret
def sigma(n):
# caching this seems smart as well
j = 2
result = 0
while j <= n+1:
result = result + P(j)*a(n+1-j)
j += 1
return result
void displayP(n):
P(n) # fill cache :-)
for x in range(n):
print ("%u -> %d\n" % (x,PCache[x]))
Instead of managing the cache manually, you might want to use a memoize decorator (see http://www.python-course.eu/python3_memoization.php )
Notes:
not tested, but you should get the idea behind it
your recurrence won't work P(n) depends on P(n+1) on your equation... This will never end
It looks like I misunderstood P0 and P1 as being Both constants (big numbers) and results (small numbers, indices)... Notation is not the best choice I guess...
Trying to use recursion to solve a riemann sum.
def f(x):
import math
return 10*math.e**(math.log(0.5)/5.27 * x)
liTotal = 0
def radExpo(start, stop, step):
global liTotal
x = start
area = f(x)*step
liTotal += area
numOfRects = (stop - start) / step
if start > (stop - (2 *step)):
return liTotal
else:
return radExpo((start+step), stop, step)
radExpo(12, 16, 1)
If I change if return statement to
print liTotal
or if I call the function with
print radExpo
It works correctly but if I call/return it regularly it returns the wrong value so I can't use what is returned.
If this is a question about what is wrong with the code, I would refactor the code to remove the global reference and it will improve its reliability. I was not able to recreate your issue where the print liTotal is different that print radExpo(12,16,1)
A modified version of your code, that removes the global variable reference looks like this:
def f(x):
import math
return 10*math.e**(math.log(0.5)/5.27 * x)
def radExpoNew(start, stop, step):
x = start
area = f(x)*step
if start <= (stop - (2 *step)):
area += radExpoNew((start+step), stop, step)
return area
print radExpoNew(12,16,1) # prints 6.84864583554
Some simplifications:
from math import e, log
# rule #1:
# e ** (a*b) == (e ** a) ** b
# applying rule #1 twice:
# e ** (log(0.5) / 5.27 * x) == ((e ** log(0.5)) ** (1/5.27)) ** x
# rule #2:
# e ** log(k) == k
# applying rule #2:
# e ** log(0.5) == 0.5
# 0.5 ** (1/5.27) == 0.8767556206241964
# so we get:
def fn(x):
return 10 * 0.8767556206241964 ** x
Then radExpo is essentially doing tail recursion (calling itself once at the end of the function), so we can rewrite it non-recursively:
def integrate(fn, start, stop, step):
steps = int((stop - start) / step)
return sum(
fn(start + k*step) # calculate x directly for each step
for k in range(steps) # to prevent error accumulation
) * step
This gets rid of the global variable that was causing issues (because you did not reset it before calling the function again).
Then
>>> integrate(fn, 12, 16, 1)
6.848645835538626
and as a bonus you can integrate whatever function you like:
>>> from math import pi, sin
>>> integrate(sin, 0, pi, 0.001)
1.999999361387437 # pretty darn close to 2.0
I got this python code for FFT calculation of a sound signal:
from math import *
from cmath import exp, pi
def fft(x):
N = len(x)
if N <= 1: return x
even = fft(x[0::2])
odd = fft(x[1::2])
return ([even[k] + exp(-2j * pi * k / N) * odd[k] for k in xrange(N / 2)] +
[even[k] - exp(-2j * pi * k / N) * odd[k] for k in xrange(N / 2)])
N = 64
res = [sin(k) for k in xrange(N)]
# Window function
a = 2*pi/(N-1)
for k in xrange(N):
z = a * res[k]
res[k] = 0.42659 - 0.49656*cos(z) + 0.076849*cos(2*z)
res = fft(res)
for k in xrange(N/2):
# get the amplitude...
sqr = sqrt(res[k].real * res[k].real + res[k].imag * res[k].imag)
if sqr > 0:
print 20 * log10(sqr) # ...in decibels
else:
print "-INF"
I got the following results:
WITHOUT window function (commented-out):
-20.3017238269
-16.9192604108
-12.5089302395
-8.97999530657
-5.96033201086
-3.12975820108
-0.242090896634
2.97021879504
6.95134203457
12.8752188937
29.5096108632 <-- PEAK
17.1668404562
10.6485650284
7.24321329787
4.98448122464
3.3242079033
2.03154022635
0.987966110459
0.124898554197
-0.600705355004
-1.21748302238
-1.74534177237
-2.1985940834
-2.5878009699
-2.92091067118
-3.20399051424
-3.44171254421
-3.63768393032
-3.79467588076
-3.91478386211
-3.99953964778
-4.04998822971
WITH window function:
-6.55943077129
-65.8567720414
-65.7987645827
-65.7012678903
-65.5625673034
-65.380788761
-65.1529344157
-64.8750852394
-64.5420675211
-64.1470597764
-63.6810080181
-63.131731575
-62.4825087571
-61.7097419947
-60.7788888801
-59.6368610687
-58.1964601495
-56.3001921054
-53.6185951634
-49.2554491173
-38.3322646561 <-- PEAK
-43.3318138698
-52.0838904305
-56.7277347745
-60.2038755771
-62.9772322874
-65.442363488
-67.7550361967
-70.0212827894
-72.3056579688
-74.5822818952
-76.5522909937
The peak appears shifted for some reason. It is a 2x frequency shift!
To check the results, I tried this Java applet:
http://www.random-science-tools.com/maths/FFT.htm
And it appears that the results WITHOUT any window function are the correct ones (peak at 1 third of the spectrum). Instead, if I apply the window function in my python script the peak shows at 2/3 of the spectrum.
Is this supposed to happen? How do I fix it?
Ok, In the meanwhile I realized what was wrong. The window function as I wrote it in the question was totally meaningless.
This is the correct one:
a = 2*pi/(N-1)
for k in xrange(N):
z = a * k
res[k] *= 0.42659 - 0.49656*cos(z) + 0.076849*cos(2*z) # Blackman
Results:
-63.8888312044
-62.1859660802
-59.4560808775
-57.5235455007
-57.0010514385
-59.4284419437
-66.6535724743
-46.1441434426
-2.31562840406
16.0873761957
22.4136439765 <-- PEAK
19.5784749467
6.43274013629
-28.3842042716
-55.5273291654
-68.8982705127
-53.3843989911
-49.731974213
-48.3131204305
-47.6953570892
-47.4386151256
-47.361972079
-47.3787962267
-47.4434419084
-47.530228024
-47.6240076874
-47.7155325706
-47.799012933
-47.870764286
-47.9284264139
-47.9705003855
-47.9960714351
The peak is now exactly where it is supposed to be.
Some other windows you may want to try:
res[k] *= 0.355768 - 0.487396*cos(z) + 0.144232*cos(2*z) - 0.012604*cos(3*z)
res[k] *= 1 - 1.93*cos(z) + 1.29*cos(2*z) - 0.388*cos(3*z) + 0.028*cos(4*z)
res[k] *= 1 - 1.985844164102*cos(z) + 1.791176438506*cos(2*z) - 1.282075284005*cos(3*z) + 0.667777530266*cos(4*z) - 0.240160796576*cos(5*z) + 0.056656381764*cos(6*z) - 0.008134974479*cos(7*z) + 0.000624544650*cos(8*z) - 0.000019808998*cos(9*z) + 0.000000132974*cos(10*z)
In order: Nuttall, FTSRS, HFT248D.
https://holometer.fnal.gov/GH_FFT.pdf