Infinite continued Fraction in Python - python

I am currently trying to implement a function that approximate the e constant in Python.
from fractions import Fraction
def fractionalSum(number, array):
def inside(index, place):
if place >= 0:
return Fraction(1, index + place)
else:
return Fraction(1, index)
if number == 0:
return 0
elif number == 1:
return inside(array[number - 1], 0)
elif number == 2:
return inside(1, fractionalSum(number - 1, array))
elif number == 88:
return inside(array[0], inside(array[1], inside(array[2], inside(array[3], inside(array[4], 0)))))
else:
return inside(fractionalSum(number - 2, array), inside(fractionalSum(number - 1, array), 0))
expansion = [1]
it = 1
clock = 0
for i in range(1, 110):
if clock == 0:
expansion.append(2 * it)
it += 1
clock = 2
if clock != 0:
expansion.append(1)
clock -= 1
print(expansion)
print(2 + fractionalSum(3, expansion))
I am currently trying recursion to calculate it but the code is not producing the correct results.
In the fractionalsum function having number 2 should call the same function with number-1 but the results is wrong.
number = 88 produces the correct value for number 5. I am trying to implement it recursively to approximate it with numbers > 50.

I haven't investigated what exactly you may have done wrong, but a recursive implementation of Continued Fraction should be fairly simple, so I'm suggesting this instead:
ONE = Fraction(1, 1)
def continuedFraction(array):
return _continuedFraction(array, 0)
def _continuedFraction(array, index):
result = Fraction(array[index], 1)
if index + 1 < len(array):
return result + ONE / _continuedFraction(array, index + 1)
return result

Related

Asserting that a number is in binary

Im working on my homework and encountered a problem. I had to string numbers in binary back to back.
Lets say we have joined(1, 3) - 1 is the starting number and 3 says that Im gonna work with 2 more numbers (if i had joined(5, 4), id work with 5, 6, 7 and 8)
1 1
2 10
3 11
result 11011
def num_to_2(number):
num2 = 0
exp = 0
while number >= 1:
num2 += (number % 2) * (10 ** exp)
number = number // 2
exp += 1
return num2
def num_lenght(number):
if number == 0:
return 0
lenght = 0
while number >= 1:
number /= 10
lenght += 1
return lenght
def joined(start, count):
result = 0
end = start + count - 1
for i in range(end, start - 1, -1):
number = num_to_2(i)
res_lenght = num_lenght(result)
result += number * (10 ** res_lenght)
return result
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111
The function works properly but it gives me results without the 0b prefix, which i need in order to pass the asserts. How do i add it there? and also: i cant use strings.
Thanks in advance!
Edit: i added the rest of my code so it makes more sense
I already solved my problem, what i had to do was "manually" convert the pseudo-binary number into base 10 number. this is my code now:
def convert_to_2(number):
num2 = 0
exp = 0
while number >= 1:
num2 += (number % 2) * (10 ** exp)
number = number // 2
exp += 1
return num2
def num_lenght(number):
if number == 0:
return 0
lenght = 0
while number >= 1:
number /= 10
lenght += 1
return lenght
def joined(start, count):
result = 0
end = start + count - 1
for i in range(end, start - 1, -1):
number = convert_to_2(i)
res_lenght = num_lenght(result)
result += number * (10 ** res_lenght)
result = convert_to_10(result)
return result
def convert_to_10(number):
num10 = 0
exp = 0
while number >= 1:
num10 += (number % 10) * (2 ** exp)
number = number // 10
exp += 1
return num10
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111
if __name__ == "__main__":
main()
thank you so much for your help(:
Here is a bit-shifting version which passes all assertions:
from math import ceil, log2
from functools import reduce
def join2(a,b):
n = ceil(log2(b+1))
return (a<<n) | b
def joined(start, count):
return reduce(join2,range(start,start+count))
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111
Well, it's unclear what your teachers mean with "don't use strings". I found this a very strange homework, so I did it, without strings.
I'm not sure what you are supposed to learn from it, but here it is:
def to_binary(number):
b = 0
while number >= 2**(b+1):
b += 1
while True:
if number >= 2**b:
yield 1
number -= 2**b
else:
yield 0
b -= 1
if b < 0:
return
def joined(start, count):
result = 0
for i in range(start, start + count):
for digit in to_binary(i):
result = (result << 1) + digit
return result
def main():
assert joined(1, 3) == 0b11011
assert joined(10, 4) == 0b1010101111001101
assert joined(8, 5) == 0b10001001101010111100
assert joined(99, 2) == 0b11000111100100
assert joined(999, 3) == 0b111110011111111010001111101001
assert joined(1111, 1) == 0b10001010111
It implements a to_binary() function that will yield a sequence of integers. Then the join function will binary shift the result to the left, and add that one or zero.
No strings attached...
You don't need to worry about the 0b prefix, it is merely a way to express numeric literals in Python source code. They could have written 27 or 0x1b instead of 0b11011 but the binary form makes it clearer what bit pattern is expected in the integer value returned by joined().
You can use the integer's .bit_length() method to know how many bits are used to represent a number. This should make the function a bit simpler.
def joined(start,count):
result = 0
for n in range(start,start+count):
result <<= n.bit_length() # offset by the number of bits
result |= n # add the number's bits
return result
if you're not allowed to use that method, you can write your own function to do it:
def bitLength(N): return 0 if not N else bitLength(N//2)+1
If you're also not allowed to use bit-wise operators, you can do it with multiplications and additions:
def joined(start,count):
result = 0
for n in range(start,start+count):
result *= 2**bitLength(n) # offset by the number of bits
result += n # add the number's bits
return result

How can i make this factorial function recursive?

A function that calculates (n-1)! , but with steps.
def function1(n, step):
result = 1
for i in range(1, n, step):
result *= i
return result
I'm not allowed to add any more parameters and I need to make it recursive.
I've tried this:
def function2(n, step):
if n < 0:
return 1
return n * function2(n-step, step)
But for let's say:
function2(6,3)
it wouldn't work, the first function will give me 1 * 4
and the second one would give me 6 * 3 * 1
I don't know how to make it work with the step argument.
Edit:
Some more samples:
First function
function1(13, 3) == 280
function1(11, 3) == 280
function1(6, 3) == 4
function1(11, 2) == 945
function1(8, 2) == 105
function1(4, 2) == 3
More sample:
function1(12, 3) == 280
function1(5, 2) == 3
function1(5, 3) == 4
Second function (same values):
function2(13, 3) == 3640
function2(11, 3) == 880
function2(6, 3) == 0
function2(11, 2) == 10395
function2(8, 2) == 0
function2(4, 2) == 0
Edit2: Some more clarifications: The function computes (n-1)!, but with steps. The step argument would just "step over" or "skip" some numbers (e.g.: function1(12, 3) should compute 1*4*7*10, like with the step argument from range(), cause it's used in the first function)
Thank you!
The obvious difference is that you are building range starting at 1 and counting up to n by step, and in the recursive example you are starting at n and counting down by step. This will result in different numbers being multiplied.
Because you are required not to use any additional function parameters, I would suggest an inner helper function, loop -
def fact (n, step):
def loop (m):
if m >= n:
return 1
else:
return m * loop(m + step)
return loop(1)
If you don't want to use a helper function like loop above, you are constrained to complex modulus arithmetic -
def fact (n, step):
if n % step != 1:
return fact(n + 1, step)
elif n < step:
return 1
else:
return (n - step) * fact(n - step, step)
No matter which way you shake it, the modulus operation for this problem is messy -
def fact (n, step):
q = (n - 1) % step
if q:
return fact(n + step - q, step)
elif n < step:
return 1
else:
return (n - step) * fact(n - step, step)
Once academic constraints like "do not use additional parameters" go away, you can multiply the ascending series in a more familiar way -
def fact (n, step, m = 1):
if m >= n:
return 1
else:
return m * fact(n, step, m + step)
All variations of fact above produce identical output -
print(fact(13, 3) == 280) # True
print(fact(11, 3) == 280) # True
print(fact(6, 3) == 4) # True
print(fact(11, 2) == 945) # True
print(fact(8, 2) == 105) # True
print(fact(4, 2) == 3) # True
print(fact(5, 2) == 3) # True
print(fact(5, 3) == 4) # True
Because the steps is calculated beginnig with 1 You have to normalize n to be a multiple of step plus 1 before you begin
And you can cheat the number of arguments by setting the steps negative on recursive calls.
def function2(n, step):
if n <= 1:
return 1
if step > 0:
n = n - 2
n = n - n % step + 1
step = -step
return n * function2(n + step, step)

Can't get out of While loop(Python 3.9)

I'm a new at programming, I like solving this euler questions and I know there are solutions for this problem but it's not about the problem at all actually.
So, i managed to create a working function for finding example: 33. triangular number. It works but i couldn't manage to properly desing my while loop. I wanted to make it like, it starts from first triangular checks it's divisors make list of it's divisors, checks the length of the divisors, because problem wants "What is the value of the first triangle number to have over five hundred divisors?" . But i never managed to work the while loop. Thank you for reading.
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n!=0:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if x == len(triangles):
n = 0
return triangles[-1]
counter = 1
while True:
for i in range(1, triangularcreator(counter) + 1):
if triangularcreator(counter) % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangularcreator(counter))
break
counter +=1
divisors.clear()
You should try to change a few things, starting with calculating just once the value of triangularcreator(counter) and assigning this value to a variable that you can use in different points of your code.
Second, you create a loop which will be calculate always triangularcreator(1). At the end of each iteration you increase the value of counter+=1, but then at the beginign of the new iteration you assignt it again value 1, so it will not progress as you expect. Try this few things:
counter = 1
while True:
triangle = triangularcreator(counter)
for i in range(1, triangle + 1):
if triangle % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangle )
break
counter +=1
Also these two arrays nums = [1], triangles = [1] should be declared and initialized inside the def triangularcreator. Otherwise you would be appending elements in each iteration
Edit: I believe it is better to give you my own answer to the problem, since you are doing some expensive operations which will make code to run for a long time. Try this solution:
import numpy as np
factor_num = 0
n = 0
def factors(n):
cnt = 0
# You dont need to iterate through all the numbers from 1 to n
# Just to the sqrt, and multiply by two.
for i in range(1,int(np.sqrt(n)+1)):
if n % i == 0:
cnt += 1
# If n is perfect square, it will exist a middle number
if (np.sqrt(n)).is_integer():
return (cnt*2)-1
else:
return (cnt*2)-1
while factor_num < 500:
# Here you generate the triangle, by summing all elements from 1 to n
triangle = sum(list(range(n)))
# Here you calculate the number of factors of the triangle
factor_num = factors(triangle)
n += 1
print(triangle)
Turns out that both of your while loop are infinite either in triangularcreatorin the other while loop:
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if len(triangles) >= x:
return triangles[-1]
return triangles[-1]
counter = 1
while True:
check = triangularcreator(counter)
for i in range(1, check + 1):
if check % i == 0:
divisors.append(i)
if len(divisors) >= 500:
tr = triangularcreator(counter)
print(tr)
break
counter +=1
Solution
Disclaimer: This is not my solution but is #TamoghnaChowdhury, as it seems the most clean one in the web. I wanted to solve it my self but really run out of time today!
import math
def count_factors(num):
# One and itself are included now
count = 2
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
count += 2
return count
def triangle_number(num):
return (num * (num + 1) // 2)
def divisors_of_triangle_number(num):
if num % 2 == 0:
return count_factors(num // 2) * count_factors(num + 1)
else:
return count_factors((num + 1) // 2) * count_factors(num)
def factors_greater_than_triangular_number(n):
x = n
while divisors_of_triangle_number(x) <= n:
x += 1
return triangle_number(x)
print('The answer is', factors_greater_than_triangular_number(500))

Given two functions, find a threshold such that one is always bigger than the other

I've implemented the following two functions in Python:
def c(m, n):
if m == 0:
return 0
elif m == 1 and n >= 0:
return n**2+n+1
elif m > 1 and n == 0:
return c(m-1, 1)
elif m > 1 and n > 0:
return c(m-1, c(m, n-1))
def d(n):
exp_num = n-1
result = 2
while exp_num != -1:
result = result**2
exp_num -= 1
final_result = 2**result
return final_result
Where the inputs m and n are both natural numbers. I'm asked to find an x, such that for all numbers y >= x, c(y,y) > d(y).
Some inputs and outputs:
c(1, 1) = 3
c(2, 2) = 183
d(1) = 16
d(2) = 65536
d(3) = 115792089237316195423570985008687907853269984665640564039457584007913129639936
As you can see d grows extremely faster than c. How can I approach this problem? Any help would be much appreciated.
The function c is a variant of Ackermann–Péter function.
It claims to fame is that it is not Primitive Recursive which for purposes here means it quickly runs out of stack space in its computation as the numbers become very large.
The problem is to find min x, such that c(y, y) > d(y), for y >= x.
We believe this is c(3, 3) but it can't be computed. We did compute for 1 & 2:
d(1) = 16, d(2) = 65536, d(3) = 115792089237316195423570985008687907853269984665640564039457584007913129639936
c(1) = 3, c(2, 2) = 183, c(3, 3) = ?
Because it's not primitively-recursive, c(3, 3) is difficult to compute (i.e. run out of stack space). However, rather than an exact number, we can obtain a lower-bound by
by limiting the recursions in the function definition.
This is done as follows.
# Will use Memoization which eliminates repeated calculations in recursive functions
class Memoize:
def __init__(self, fn):
self.fn = fn
self.memo = {}
def __call__(self, *args):
if args not in self.memo:
self.memo[args] = self.fn(*args)
return self.memo[args]
#Memoize
def c(m, n, cnt = 0, MAX_RECURSION = 20):
" Refactor function c to have a max recursion depth "
if cnt > MAX_RECURSION:
return 0 # We know the return value is always >= 0, but normally
# much larger. By quitting early and returning zero we are
# ensuring our final computation will be smaller than it would
# otherwise if we had not limited the recurison depth
#
if m == 0:
return 0
elif m == 1 and n >= 0:
return n**2+n+1
elif m > 1 and n == 0:
return c(m-1, 1, cnt+1)
elif m > 1 and n > 0:
return c(m-1, c(m, n-1, cnt+1), cnt+1)
def d(n):
exp_num = n-1
result = 2
while exp_num != -1:
result = result**2
exp_num -= 1
final_result = 2**result
return final_result
value_d = d(3)
value_c = c(3, 3)
print('Number of digits in d(3) is {}'.format(len(str(value_d))))
#>>> Number of digits in d(3) is 78
print('Number of digits in c(3, 3) is {}'.format(len(str(value_c))))
#>>>Number of digits in c(3, 3) is 74176
Thus, we see that c(3, 3) has ~1K more digits than d(3). It will be even more since we stopped the recursion early in computing c(3, 3).

How to write 2**n - 1 as a recursive function?

I need a function that takes n and returns 2n - 1 . It sounds simple enough, but the function has to be recursive. So far I have just 2n:
def required_steps(n):
if n == 0:
return 1
return 2 * req_steps(n-1)
The exercise states: "You can assume that the parameter n is always a positive integer and greater than 0"
2**n -1 is also 1+2+4+...+2n-1 which can made into a single recursive function (without the second one to subtract 1 from the power of 2).
Hint: 1+2*(1+2*(...))
Solution below, don't look if you want to try the hint first.
This works if n is guaranteed to be greater than zero (as was actually promised in the problem statement):
def required_steps(n):
if n == 1: # changed because we need one less going down
return 1
return 1 + 2 * required_steps(n-1)
A more robust version would handle zero and negative values too:
def required_steps(n):
if n < 0:
raise ValueError("n must be non-negative")
if n == 0:
return 0
return 1 + 2 * required_steps(n-1)
(Adding a check for non-integers is left as an exercise.)
To solve a problem with a recursive approach you would have to find out how you can define the function with a given input in terms of the same function with a different input. In this case, since f(n) = 2 * f(n - 1) + 1, you can do:
def required_steps(n):
return n and 2 * required_steps(n - 1) + 1
so that:
for i in range(5):
print(required_steps(i))
outputs:
0
1
3
7
15
You can extract the really recursive part to another function
def f(n):
return required_steps(n) - 1
Or you can set a flag and define just when to subtract
def required_steps(n, sub=True):
if n == 0: return 1
return 2 * required_steps(n-1, False) - sub
>>> print(required_steps(10))
1023
Using an additional parameter for the result, r -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r * 2)
for x in range(6):
print(f"f({x}) = {required_steps(x)}")
# f(0) = 0
# f(1) = 1
# f(2) = 3
# f(3) = 7
# f(4) = 15
# f(5) = 31
You can also write it using bitwise left shift, << -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r << 1)
The output is the same
Have a placeholder to remember original value of n and then for the very first step i.e. n == N, return 2^n-1
n = 10
# constant to hold initial value of n
N = n
def required_steps(n, N):
if n == 0:
return 1
elif n == N:
return 2 * required_steps(n-1, N) - 1
return 2 * required_steps(n-1, N)
required_steps(n, N)
One way to get the offset of "-1" is to apply it in the return from the first function call using an argument with a default value, then explicitly set the offset argument to zero during the recursive calls.
def required_steps(n, offset = -1):
if n == 0:
return 1
return offset + 2 * required_steps(n-1,0)
On top of all the awesome answers given earlier, below will show its implementation with inner functions.
def outer(n):
k=n
def p(n):
if n==1:
return 2
if n==k:
return 2*p(n-1)-1
return 2*p(n-1)
return p(n)
n=5
print(outer(n))
Basically, it is assigning a global value of n to k and recursing through it with appropriate comparisons.

Categories

Resources