How would this be written without using yield? - python

I've tried and failed multiple times trying to replace yield, but I don't seem to be successful, the goal is to have the same function, without yield.
def calcPi(limit): # Generator function
"""
Prints out the digits of PI
until it reaches the given limit
"""
q = 1
r = 0
t = 1
k = 1
n = 3
l = 3
decimal = limit
counter = 0
while counter != decimal + 1:
if 4 * q + r - t < n * t:
# yield digit
yield n
# insert period after first digit
if counter == 0:
yield '.'
# end
if decimal == counter:
print('')
break
counter += 1
nr = 10 * (r - n * t)
n = ((10 * (3 * q + r)) // t) - 10 * n
q *= 10
r = nr
else:
nr = (2 * q + r) * l
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
q *= k
t *= l
l += 2
k += 1
n = nn
r = nr
Added the full function as people were asking for it in the comments,

Just define a list and collect the digits:
def calcPi(limit): # Generator function
"""
Collects the digits of PI
until it reaches the given limit
"""
pi = []
...
while ...:
...
# yield n
pi.append(n)
...
#break
return pi

Related

How do i convert the Maclaurin Series for tan x equation to python code?

I'm trying to calculate the nth term but its giving me wrong answers
import math
def bernoulli(m):
if m == 0:
return 1
else:
t = 0
for k in range(0, m):
t += math.comb(m, k) * bernoulli(k) / (m - k + 1)
return 1 - t
def pn(n, x):
sum = 0
for i in range(n):
sum += ((bernoulli(2 * i)) / math.factorial(2 * i)) * (-4**i) * (1 - (4**i)) * (x**((2 * i) - 1))
Equation:
Here are a few comments:
In python, the convention is to include the start, and exclude the end. list(range(1,4)) is only [1, 2, 3], not [1,2,3,4]. Thus your Bernouilli loop should be for k in range(0, m+1) and your pn loop should be for i in range(1, n+1).
Exponentiation has a higher precedence than most operators. -4**i is parsed as -(4**i), not as (-4)**i.
sum is already the name of a builtin function in python. It is very strongly advised not to shadow the names of builtins. Call that variable s or total or something else, not sum.
Finally, the code becomes:
import math
def bernoulli(m):
if m == 0:
return 1
else:
t = 0
for k in range(0, m+1):
t += math.comb(m, k) * bernoulli(k) / (m - k + 1)
return 1 - t
def pn(n, x):
s = 0
for i in range(1, n+1):
s += ((bernoulli(2 * i)) / math.factorial(2 * i)) * ((-4)**i) * (1 - (4**i)) * (x**(2 * i - 1))
return s
And, using builtin function sum:
import math
def bernoulli(m):
if m == 0:
return 1
else:
return 1 - sum(math.comb(m, k) * bernoulli(k) / (m - k + 1)
for k in range(0, m+1))
def pn(n, x):
return sum((bernoulli(2 * i)) / math.factorial(2 * i)) * ((-4)**i) * (1 - (4**i)) * (x**(2 * i - 1)
for i in range(1, n+1))

How can I save integers displayed in the console?

I created a Python program that calculates the digits of pi and displays them in the console as the calculation is running. Eventually, it starts deleting numbers that were first displayed. How could I save the numbers as they're being displayed? Here is the code:
def calcPi(limit):
q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
decimal = limit
counter = 0
while counter != decimal + 1:
if 4 * q + r - t < n * t:
yield n
if counter == 0:
yield '.'
if decimal == counter:
print('')
break
counter += 1
nr = 10 * (r - n * t)
n = ((10 * (3 * q + r)) // t) - 10 * n
q *= 10
r = nr
else:
nr = (2 * q + r) * l
nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
q *= k
t *= l
l += 2
k += 1
n = nn
r = nr
def main():
pi_digits = calcPi(int(input(
"Enter the number of decimals to calculate to: ")))
i = 0
for d in pi_digits:
print(d, end='')
i += 1
if i == 55:
print("")
i = 0
if __name__ == '__main__':
main()
You can write to a txt file instead of printing. For example:
with open("output.txt", "a") as f:
instead of printing,
print(d, end='')
do
f.write(str(d))
and instead of printing,
print('')
do
f.write('\n')
On most UNIX operating systems you can use the tee command:
python calculate_pi.py | tee output.txt
This will let you see the output in your terminal and write it to the file at the same time.

Sum of range(1,n,2) values using recursion

I'm trying to translate a loop to a recursive algorithm. Fairly simple, I've just hadn't been able to make it ignore the n value when summing up the values, like range does.
This is the iterative function:
def function(n):
total=0
for i in range(1,n,2):
total += i
print(total)
function(5) # Output: 4
This is the recursive I've tried:
def function1(n):
if n==1:
return n
else:
return n+function1(n-2)
function(5) # Output: 9
So function1 does sum the n when it should be ignored. Cause range() does not include the stop number.
Then, I tried:
def f1(n):
def f_recursive(n):
if n==1 or n==2:
return 1
elif n==0:
return 0
else:
return n + f_recursive(n - 2)
return f_recursive(n) - n
print(f1(5)) # Output: 4 Yeiii!!
But then I realised, that only works for odd numbers. Not for even. If f1(6) then you get 4 when it should be 9, because it ends up being 11-6= 9.
So silly me I tried:
def f1(n):
def f_recursive(n):
if n==1 or n==2:
return 1
elif n==0:
return 0
elif n%2 == 0:
return n + f_recursive(n - 3)
elif n%2 == 1:
return n + f_recursive(n - 2)
return f_recursive(n) - n
print(f1(6))
Which of course also did not work. Am I not understanding recursion properly here?
The tricky part is excluding the upper bound. If the upper bound is your only parameter n, you have to know when it's the first call, and when it's an intermediate (recursive) call. Alternatively, if inner functions are okay, you could instead just count from 1 up until you hit n:
def function1(n):
def inner(i):
return 0 if i >= n else i + inner(i + 2)
return inner(1)
You want to compute the sum of all odd integers from 1 up to, but not including, n.
This leaves 2 possibilities:
If n is <= 1, there are no numbers to sum, so the sum is 0.
The highest number that might be included in the list is n-1, but only if it is odd. Either way, the rest of the sum is "the sum of all odd integers from 1 up to, but not including, n-1" (sound familiar?)
This translates to:
def f1(n):
if n <= 1:
return 0
else:
isOdd = (n-1)%2==1
return f1(n-1) + (n-1 if isOdd else 0)
The problem with your recursion is that you're returning n rather than the value in the range (list) that you're currently on, this poses a problem since n is not inclusive within the range and should not be added to the final total
Ideally you need to reverse the logic and traverse it the same way your range does
def func(start,end, step):
if(start >= end):
return 0
return start + func(start + step, end, step)
You just have to recognize the three types of ranges you might be adding up.
range(1, n, 2) where n <= 1: The empty range, so the sum is 0
range(1, n, 2) where n > 1 and n is even: the range is 1, ..., n-1. (E.g. range(1, 6, 2) == [1, 3, 5])
range(1, n, 2) where n > 1 and n is odd: the range is 1, ..., n-2 (E.g., range(1, 5, 2) == [1, 3]
Translating this to code is straightforward:
def f_recursive1(n):
if n <= 1:
return 0
elif n % 2 == 0:
return n - 1 + f_recursive1(n-2)
else: # n odd
return n - 2 + f_recursive1(n-2)
However, this does more work than is strictly necessary, since subtracting 2 from n will never change its parity; you don't need to check n is even or odd in every recursive call.
def f_recursive2(n):
def f_helper(x):
if x <= 0:
return 0
return x + f_helper(x-2)
if n % 2 == 0:
return f_helper(n-1)
else:
return f_helper(n-2)
If we are allowed multiplication and division, I hope you realise that this particular task does not require more than just a base case.
Python code:
def f(n):
total=0
for i in range(1,n,2):
total += i
return total
def g(n):
half = n // 2
return half * half
for n in xrange(100):
print f(n), g(n)
Since
*
* * *
* * * * *
* * * * * * *
can be seen as nested, folded rows. Here are the top two folded rows:
*
* * *
* * * *
* * * *
Let's rotate counterclockwise 45 degrees
* * * *
* * * *
* *
* *
and add the other two folded rows,
*
* *
* * * *
* * * *
* * * *
* * *
and
*
to get
* * * *
* * * *
* * * *
* * * *
the area of a square.

Calculating factorials with Python

EDIT: I know I can import factorials but I'm doing this as an exercise
Trying to get the factor of a given number with a function in Python.
For example:
factorial(4) = 4 * 3 * 2 * 1 = 24
def factorial(x):
n = x
while n >= 0:
x = n * (n - 1)
n -= 1
return x
try like this: to make your code work
def factorial(x):
n = 1 # this will store the factorial value
while x > 0:
n = n*x
x -= 1
return n
you got many advice on comments follow it
A good way of approaching this would be using recursion where a function calls itself. See Function for Factorial in Python
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
But in your case your return statement actually breaks out of the while loop. So if you pass in 5 you get 20 back which is obviously not 5! (5 factorial).
Instead, try this:
def factorial(x):
n = 1
while x > 1:
n *= x
x -= 1
return n
print (factorial(5))
But do have a go at the recursive approach.
If you really want to cheat try:
import math
math.factorial(n)
I present an even shorter code for recursive factorial calculation. Not sure if it is faster or slower than other approaches:
def fac(n):
return 1 if n==1 else n*fac(n-1)
fac(10)
3628800
def factorial(n):
total = 1
for num in range(2,n+1):
total *= num
return total
input:
n = 10
print(str(n) + "! = ", end = '')
def factorial(n):
'''
print factorial number in human way
'''
if n < 0:
return 'factorial() not defined for negative values'
if n == 0:
return 1
if n == 1:
print('', n, ' =', end = ' ')
return 1
else:
print('', n, '*', end = '')
return n * factorial(n - 1)
print(factorial(n))
output:
10! = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3628800

Recursive nesting in equation building

I want to code an "application" that will plot the nth reagent's concentration in time function of a chain reaction: A->B->C->D->...
The thing is, c_n(t) contains 2^n - 1 exponential functions - which are nested based on a pattern I've found:
c_1(t) = c_0_1 * exp(-k_1 * t)
c_2(t) = c_0_2 * exp(-k_2 * t) + c_0_1 * k_1 * {[exp(-k_1 * t) - exp(-k_2 * t)]/[k_2 - k_1]}
c_3(t) = c_0_3 * exp(-k_3 * t) + c_0_2 * k_2 * {[exp(-k_2 * t) - exp(-k_3 * t)]/[k_3 - k_2]} + c_0_1 * k_1 * k_2 * [1/(k_2-k_1)] * <{[exp(-k_1 * t) - exp(-k_3 * t)]/[k_3 - k_1]} - {[exp(-k_2 * t) - exp(-k_3 * t)]/[k_3 - k_2]}>
As you can see, each equation is a sum of reappearing elements. The number of nestings is dependent on the degree of relationship: 0-th degree (A to A) - simple exponential function, 1st degree (A to B, B to C, etc.) - 1 nesting, 2nd degree (A to C, B to D, etc.) - 2 nestings, etc.
Each equation can be divided into reappearing parts:
the 'independent' unit: c_0_n * exp(-k_n * t),
the basic unit: f(a,b) = (exp(- k_n[b - 1] * t) - exp(- k_n[a - 1] * t)) / (k_n[a - 1] - k_n[b - 1]),
the nested unit based on the basic unit,
the product of the multiplication of constants (parameters) before each nested unit.
Each nested unit of the nth equation derives from the nested units of the (n-1)th equation. The equations themselves can be obtained through iterated integration. The number of possible equations (based on the number of independent kinetic constants k) for the nth reagent is given by Bell number B(n).
Each such equation can be obtained from the equation with n independent kinetic constants for the nth reagent (all are independent of one another). One simply has to find the limes of such equation. E.g. if k_3 = k_4 and k_7 = k_2, then we are looking for lim k_4->k_3 [lim k_7->k_2 (f(t))].
The working code:
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
n = 0
import matplotlib.pyplot as plt
import numpy as np
def komendy(): # displays the list of commands
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
return
def zakres(): # number of reagents query
global n, zakres_n, c_0_n, k_n
n = int(raw_input("Define the number of n reagents: "))
zakres_n = range(1, n + 1)
c_0_n = [int(0)] * n
k_n = [int(0)] * n
return
def stez(): # initial concentrations query
while True:
y = int(raw_input("Define the value of c_0_n for n equal to (press 0 to break): "))
if y == 0:
break
x = raw_input("Define the value of c_0_" + str(y) + ": ")
if "." in x:
c_0_n[y - 1] = float(x)
else:
c_0_n[y - 1] = int(x)
return
def kin(): # kinetic constants query
while True:
q = int(raw_input("Define the value of k_n for n equal to (press 0 to break): "))
if q == 0:
break
p = raw_input("Define the value of k_" + str(q) + ": ")
if "." in p:
k_n[q - 1] = float(p)
else:
k_n[q - 1] = int(p)
return
def tabela(): # displays the table with the initial data
if n == 0:
zakres()
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
else:
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
return
def wykres(): # plots the basic unit
global f_t, t_k, t, t_d
a = int(raw_input("a = "))
b = int(raw_input("b = "))
reag = map(int, raw_input("Provide the reagents to plot (separate with spacebar): ").split(" "))
t_k = float(raw_input("Define time range from 0 to: "))
t_d = float(raw_input("Set the precision of the time axis: "))
t = np.arange(0,t_k,t_d)
p = []
def f_t(t):
return (np.exp(- k_n[b - 1] * t) - np.exp(- k_n[a - 1] * t)) / (k_n[a - 1] - k_n[b - 1])
f_t = f_t(t)
for i in reag:
p += plt.plot(t,i*f_t)
And the code that doesn't work [yet] (the only difference is the new wykres() function I'm trying to build):
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
n = 0
import matplotlib.pyplot as plt
import numpy as np
def komendy(): # displays the list of commands
print
print ("Commands: komendy() - list of commands, test() - sets initial parameters, zakres() - asks for the number of reagents, tabela() - displays the table, stez() - asks for the initial concentrations, kin() - asks for the kinetic constants.")
print
return
def zakres(): # number of reagents query
global n, zakres_n, c_0_n, k_n
n = int(raw_input("Define the number of n reagents: "))
zakres_n = range(1, n + 1)
c_0_n = [int(0)] * n
k_n = [int(0)] * n
return
def stez(): # initial concentrations query
while True:
y = int(raw_input("Define the value of c_0_n for n equal to (press 0 to break): "))
if y == 0:
break
x = raw_input("Define the value of c_0_" + str(y) + ": ")
if "." in x:
c_0_n[y - 1] = float(x)
else:
c_0_n[y - 1] = int(x)
return
def kin(): # kinetic constants query
while True:
q = int(raw_input("Define the value of k_n for n equal to (press 0 to break): "))
if q == 0:
break
p = raw_input("Define the value of k_" + str(q) + ": ")
if "." in p:
k_n[q - 1] = float(p)
else:
k_n[q - 1] = int(p)
return
def tabela(): # displays the table with the initial data
if n == 0:
zakres()
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
else:
print
print "n: ", zakres_n
print "c_0_n: ", c_0_n
print "k_n: ", k_n
print
return
def wykres(): # plots the requested functions
global t_k, t, t_d, f, constans
reag = map(int, raw_input("Provide the reagents to plot (separate with spacebar): ").split(" "))
t_k = float(raw_input("Define the time range from 0 to: "))
t_d = float(raw_input("Define the precision of the time axis: "))
t = np.arange(0,t_k,t_d)
p = []
def f(a,b): # basic unit
return (np.exp(- k_n[b - 1] * t) - np.exp(- k_n[a - 1] * t)) / (k_n[a - 1] - k_n[b - 1])
def const(l,r): # products appearing before the nested parts
const = 1
constans = 1
for h in range(l,r):
const = const * k_n[h]
constans = c_0_n[l] * const
return
def czlonF(g): # nested part
czlonF = 0
for u in range(g):
czlonF = czlonF + npoch(f(a,b),g)
if g == 1:
czlonF(g) = 0
return
def npoch(f(a,b),n):
f = f(a,b)
for x in range(b+1, n+1):
f = npoch(f(a,b),x)
return
def c(j): # final result, concentration in time function
return
def czlon0(m): # 'independent' part
return (c_0_n[m - 1] * np.exp(- k_n[m - 1] * t))
for i in reag: # the actual plot command
p += plt.plot(t,c(i))
plt.show()
return
def test():
global n, zakres_n, k_n, c_0_n
n = 5
zakres_n = range(1, n + 1)
k_n = [1,2,3,4,5]
c_0_n = [2,3,4,5,6]
return
plt.show()
return
def test():
global n, zakres_n, k_n, c_0_n
n = 5
zakres_n = range(1, n + 1)
k_n = [1,2,3,4,5]
c_0_n = [2,3,4,5,6]
return
How do I fix the wykres() function so that it plots c(n)? How do I build it so that it can be plotted? I want Python to automatically build c_n(t) for whichever n I desire and plot all of them.

Categories

Resources