I made a sequence and series solver just for helping me solve homework, and im in dire need of ways to make it further compact and efficient, since i used brute force.
If you want to see what this is supposed to do, then i have it on the read me in github : https://github.com/MahdeenSky/MicroPythonCalculator/tree/master/MY%20PROJECTS/Sequence%20%26%20Series%20Solver
This python code is meant for the fx-cg50 calculator's micropython, where there are a lot of functions that don't work including fractions, some mathematical functions such as math.gcd and math.isclose. So I really require some advice or coding tricks to simplify my program.
Disclaimer: I'm only an A-Level student of 16 years; consider me a beginner. I know eval is insecure, but I'm not planning on uploading this online; it's only for my personal use.
# just to make the input_checker function smaller and to eliminate repeated code, responsible for iterating through a list of inputs
def three_variables_looper_arithmetic():
count_list = [input("enter a1: "), input("enter n: "), input("enter d: ")]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
# just to make the input_checker function smaller and to eliminate repeated code, responsible for iterating through a list of inputs
def three_variables_looper_geometric():
count_list = [input("enter a1: "), input("enter r: "), input("enter n: ")]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
# loops through all the inputs of a given situation based on whether its arithmetic
# or not, and checks whether the input is string like "6/2" so it could evaluate it, allows input of fractions
def input_checker(choice_main, choice_sub, L):
if choice_main == 'arithmetic':
if choice_sub == 'a_nth':
return three_variables_looper_arithmetic()
elif choice_sub == 'sum_to_nth_without_L':
return three_variables_looper_arithmetic()
elif choice_sub == 'sum_to_nth_with_L':
count_list = [input("enter a1: "), input("enter n: "), L]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
elif choice_sub == "a_nth_exceed":
count_list = [input("enter a1: "), input("enter r/d: ")]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
elif choice_sub == "sum_to_nth_without_L_exceed":
count_list = [input("enter a1: "), input("enter r/d: ")]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
elif choice_sub == "sum_to_nth_with_L_exceed":
count_list = [input("enter a1: "), L]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
elif choice_main == 'geometric':
if choice_sub == 'a_nth':
return three_variables_looper_geometric()
elif choice_sub == 'sum_to_nth':
return three_variables_looper_geometric()
elif choice_sub == 'sum_to_infinity':
count_list = [input("enter a1: "), input("enter r: ")]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
elif choice_sub == "a_nth_exceed":
count_list = [input("enter a1: "), input("enter r/d: ")]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
elif choice_sub == "sum_to_nth_without_L_exceed":
count_list = [input("enter a1: "), input("enter r/d: ")]
count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
return count_list
# checks if L is an x or not, also based on whether its on the exceed or normal path, and
# an x means L is not present, while a value of L represents it is present and used in calculation
def L_evaluator(L, option, choice_n, value):
if option == "normal":
if L == "x":
a1, n, d = input_checker(choice_main, choice_n, L)
result = (n/2)*(2*a1+(n-1)*d)
return result
else:
choice_n = choice_map_sub['x']
a1, n, L = input_checker(choice_main, choice_n, L)
result = (n/2)*(a1+L)
return result
if option == "exceed":
if L == "x":
a1, d = input_checker(choice_main, choice_n, 0)
a1, d = float(a1), float(d)
n = 1
while True:
result = (n/2)*(2*a1+(n-1)*d)
if (result >= float(value)):
break
n += 1
return n
else:
choice_n = choice_map_exceed['c']
a1, L = input_checker(choice_main, choice_n, L)
n = 1
while True:
result = (n/2)*(a1+L)
if (result >= float(value)):
break
n += 1
return n
# finds the first n to exceed a certain value, by using brute force method
def minimum_n_finder(choice_main, choice_map_exceed):
choice_n_input = None
if choice_main == "arithmetic":
while choice_n_input not in ['a', 'b']:
choice_n_input = input("Enter a for nth\nEnter b for sum\n>> ")
choice_n = choice_map_exceed[choice_n_input]
print("enter x in n")
if choice_n == "a_nth_exceed":
print("a1+(n-1)d > Value")
a1, d = input_checker(choice_main, choice_n, 0)
n = 1
value = input("Enter the value to exceed: ")
while True:
result = a1+(n-1)*d
if (result >= float(value)):
break
n += 1
print("The minimum n to exceed is " + str(n))
if choice_n == "sum_to_nth_without_L_exceed":
n = 1
print("Sn=(n/2)(2a1+(n-1)d)>Value\nSn=(n/2)(a1+L)>Value\nEnter x if L is unknown")
L = input("Enter L: ")
value = input("Enter the value to exceed: ")
result = L_evaluator(L, "exceed", choice_n, value)
print("The minimum n to exceed is " + str(result))
elif choice_main == 'geometric':
while choice_n_input not in ['a', 'b']:
choice_n_input = input("Enter a for nth\nEnter b for sum_to_nth\n>> ")
choice_n = choice_map_exceed[choice_n_input]
if choice_n == "a_nth_exceed":
print("a1(r)^(n-1)>Value")
a1, r = input_checker(choice_main, choice_n, 0)
if a1 == 0:
print("a cannot be 0")
raise SystemExit
n = 1
value = input("Enter the value to exceed: ")
while True:
result = a1*(r)**(n-1)
if (result >= float(value)):
break
n += 1
print("The minimum n to exceed is " + str(n))
elif choice_n == "sum_to_nth_without_L_exceed":
print("Sn=(a1(1-(r)^n))/(1-r)")
a1, r = input_checker(choice_main, choice_n, 0)
if a1 == 0:
print("a cannot be 0")
raise SystemExit
n = 1
value = input("Enter the value to exceed: ")
while True:
result = (a1*(1-(r)**n))/(1-r)
if (result >= float(value)):
break
n += 1
print("The minimum n to exceed is " + str(n))
# as this code is for a calculator the x button is very easily accessible to shut the whole program.
def stopper():
stop_or_continue = input("Stop?: enter x then\n>>> ")
if stop_or_continue == "x":
raise SystemExit
print("Sequence & Series Solver")
# asks whether you want to solve arithmetically or geometrically, depends on the sequence/series
while True:
choice_main , choice_input_main = None, None
choices_main_options = ['a','b']
choice_map_main ={"a": 'arithmetic', "b": 'geometric'}
while choice_input_main not in choices_main_options:
choice_input_main = input("a for arithmetic\nb for geometric\n>> ")
choice_main = choice_map_main[choice_input_main]
if choice_main == "arithmetic":
print("Arithmetic: ")
choice_sub, choice_input_sub = None, None
choices_sub_options = ['a', 'b', 'c']
choice_map_sub = {'a': 'a_nth', 'b': 'sum_to_nth_without_L', 'x': 'sum_to_nth_with_L', 'c':'minimum_number_of_terms_to_exceed'}
while choice_input_sub not in choices_sub_options:
choice_input_sub = input("a for a_nth term\nb for sum\nc for min_term_to_exceed\n>> ")
choice_sub = choice_map_sub[choice_input_sub]
# the variable choice_main refers to whether the choice is arithmetic or geometric
# choice_sub refers to the types of formulas you'll use in sequences/series
if choice_sub == "a_nth":
print("a_nth=a1+(n-1)d")
a1, n, d = input_checker(choice_main, choice_sub, 0)
result = a1+(n-1)*d
print(round(result,4))
elif choice_sub == "sum_to_nth_without_L":
print("Sn=(n/2)(2a1+(n-1)d)\nSn=(n/2)(a1+L)\nEnter x if L is unknown")
L = input("Enter L: ")
print(round(L_evaluator(L, "normal", choice_sub, 0), 4))
elif choice_sub == "minimum_number_of_terms_to_exceed":
choice_map_exceed = {'a': 'a_nth_exceed', 'b': 'sum_to_nth_without_L_exceed', 'c': 'sum_to_nth_with_L_exceed'}
minimum_n_finder("arithmetic", choice_map_exceed)
elif choice_main == "geometric":
print("Geometric: ")
choice_sub, choice_input_sub = None, None
choices_sub_options = ['a', 'b', 'c', 'd']
choice_map_sub = {'a': 'a_nth', 'b': 'sum_to_nth', 'c': 'sum_to_infinity', 'd': 'minimum_number_of_terms_to_exceed'}
while choice_input_sub not in choices_sub_options:
choice_input_sub = input("a for a_nth term\nb for sum\nc for sum to infinity\nd for min_terms_exceed\n>> ")
choice_sub = choice_map_sub[choice_input_sub]
if choice_sub == "a_nth":
print("a_nth=a1(r)^(n-1)")
a1, r, n = input_checker(choice_main, choice_sub, 0)
result = a1*(r)**(n-1)
print(round(result,4))
elif choice_sub == "sum_to_nth":
print("Sn=(a1(1-(r)^n))/(1-r)")
a1, r, n = input_checker(choice_main, choice_sub, 0)
try:
result = (a1*(1-(r)**n))/(1-r)
print(round(result,4))
except (ZeroDivisionError, NameError):
print("r cannot be 1!")
elif choice_sub == "sum_to_infinity":
print("S_inf=a1/(1-r)")
a1, r = input_checker(choice_main, choice_sub, 0)
if (r > 1):
print("r cannot be greater than 1")
raise SystemExit
try:
result = a1/(1-r)
print(round(result,4))
except (ZeroDivisionError, NameError):
print("r cannot be 1!")
elif choice_sub == "minimum_number_of_terms_to_exceed":
choice_map_exceed = {'a': 'a_nth_exceed', 'b': 'sum_to_nth_without_L_exceed', 'c': 'sum_to_nth_with_L_exceed'}
minimum_n_finder("geometric", choice_map_exceed)
stopper()