# python – Binomial Expansion Calculator

So i wrote a program with the documentation for my fx cg50 calculator’s micropython to calculate various items, each of which are:

1. Pascal Triangle Entry
2. Pascal Triangle Level/Entire Row
3. Binomial Expansion
4. Binomial Term Finder
5. First num of terms
6. Combinations

if you look at the code below, you’ll notice, I haven’t used any modules, and reinvented the wheel on some things. That is because, micropython’s python language and standard library is very limited, so I had to make do.

I would like some advice on optimizing, and compacting of my program, and other tips and tricks to improve how a task is done.

``````def float_integer(num):
"""
returns an integer if the float given, is a whole number.
otherwise returns the same value as the argument num.

Ex:
4.0 ---> 4
3.5 ---> 3.5
"""
if num == int(num):
return int(num)
return num

def seperate_to_pairs(iterator):
"""
changes it so that each item in the list pairs with its neighbor items.
Ex:
(1, 2, 1)       ---> ((1, 2), (2, 1))
(1, 2, 3, 1)    ---> ((1, 2), (2, 3), (3, 1))
(1, 2, 3, 2, 1) ---> ((1, 2), (2, 3), (3, 2), (2, 1))
"""
return (iterator(i:i+2) for i in range(0, len(iterator)-1))

def factorial(n, endpoint=1):
"""
acquires the factorial of n
Ex:
5 ---> 120
"""
res = 1
for i in range(endpoint, n+1):
res *= i
return res

def combinations(n, r):
"""
nCr - combination or number of ways of picking r items from n

OR

nCr = n!/r!(n-r)!
Ex:
4C2 ---> 6
6C3 ---> 20
"""
return (factorial(n, n-r+1) // factorial(r))

def pascal_triangle_entry(nth, rth):
"""
acquires the entry in the pascal's triangle at the nth row and rth term
Ex:
4th row, 2nd term ---> 3
"""
return combinations(nth-1, rth-1)

def pascal_triangle_level(level):
"""
acquires an entire row in the pascal triangle designated by the level number, where 0 is (1), and 1 is (1, 1)
Ex:
5 ---> (1, 5, 10, 10, 5, 1)
6 ---> (1, 6, 15, 20, 15, 6, 1)
"""
if level == 0:
return (1)

layer = (1, 1)
for _ in range(level-1):
current_layer = ()
for pair in seperate_to_pairs(layer):
current_layer.append(sum(pair))
layer = (1) + current_layer + (1)
return layer

def binomial_expand(a, b, n):
"""
(a + bx)^n = a^n + (nC1) a^(n-1) bx + (nC2) a^(n-2) (bx)^2 + ... + (nCr) a^(n-r) (bx)^r + ... + (bx)^n

Ex:
a = 3, b = 2, n = 4 # example values for (3 + 2x)^4
OUTPUT FORMAT:

(4C0) --> 81.0
(3.0)^4
...
(nCr) --> Term_Value
nCr_value (a)^(n-r) (b)^(r)
...
(4C4) --> 16.0
(2.0)^4

"""
terms = ()
coefficients = pascal_triangle_level(n)(1:-1)

for r, coefficient in zip(range(1, len(coefficients)+1), coefficients):
term_value = binomial_term_finder(a, b, n, r, coefficient)
terms.append("({5}C{4}) --> {6}n{0} ({1})^({2}) ({3})^({4})".format(coefficient, a, n-r, b, r, n, term_value))
return "n".join(("({1}C0) --> {2}n({0})^{1}".format(a, n, a**n)) + terms + ("({1}C{1}) --> {2}n({0})^{1}".format(b, n, b**n)))

def binomial_term_finder(a, b, n, r, coefficient=None):
"""
calculates the coefficient of the rth term in (a + bx)^n

if coefficient is given, it skips calculating it.
Ex:
a = 3, b = 2, n = 4, r = 2 # example values for (3 + 2x)^4
---> 216

"""
if coefficient:
return coefficient * a**(n - r) * b**r
return combinations(n, r) * a**(n - r) * b**r

def first_rth_terms(a, b, n, rth):
"""
calculates the coefficients of x for the first rth terms in (a + bx)^n
Ex:
a = 3, b = 2, n = 4, rth = 3 # example values for (3 + 2x)^4
---> (81, 216, 216)
"""
return (binomial_term_finder(a, b, n, r) for r in range(rth))

class BIOS:
"""
responsible for input and output operations
Hence called BIOS - Basic Input and Output System
"""

prompt = "n".join(("a: pascal tri. entry", "b: pascal tri. row", "c: binomial expand", "d: binomial term finder", "e: first rth terms", "f: combinations"))

def __init__(self):
self.running = True
self.choices = {'a': self.pascal_triangle_entry, 'b': self.pascal_triangle_level, 'c': self.binomial_expand, 'd': self.binomial_term_finder, 'e': self.first_rth_terms, 'f': self.combinations}

def stop_decorator(func):
"""
Decorator for stopping certain functions, after they're done by asking with a prompt
"""
def wrapper(self):
func(self)
command = input("Enter nothing to stop: ")
if command == '':
self.running = False
return wrapper

def INPUT_a_b(self):
"""
input a and b for (a + bx)^n, using only one line
"""
return float_integer(float(input("Enter a: "))), float_integer(float(input("Enter b: ")))

@stop_decorator
def pascal_triangle_entry(self):
nth = int(input("Enter row number(n): "))
rth = int(input("Enter entry number(r): "))
print(pascal_triangle_entry(nth, rth))

@stop_decorator
def pascal_triangle_level(self):
level = int(input("Enter level: "))
print(pascal_triangle_level(level))

def binomial_expand(self):
a, b = self.INPUT_a_b()
nth = int(input("Enter nth: "))
self.running = False
print(binomial_expand(a, b, nth))

@stop_decorator
def binomial_term_finder(self):
a, b = self.INPUT_a_b()
nth = int(input("Enter nth: "))
rth = int(input("Enter rth: "))
print(binomial_term_finder(a, b, nth, rth))

@stop_decorator
def first_rth_terms(self):
a, b = self.INPUT_a_b()
nth = int(input("Enter nth: "))
rth = int(input("Enter first num terms: "))
print("First {} terms:".format(rth))
print(first_rth_terms(a, b, nth, rth))

@stop_decorator
def combinations(self):
nth = int(input("Enter nth: "))
rth = int(input("Enter rth: "))
print(combinations(nth, rth))

def main(self):
"""
main program loop, uses a dictionary as an alternative for a switch case
"""
while self.running:
print(self.prompt)
self.choices.get(input(">> "), lambda: None)()

program = BIOS()
program.main()
$$```$$
``````

Posted on Categories Articles