# Sequence and Series Solver

I made a sequence and series solver just for helping me solve homework, and I'm 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, please see my github.

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()

• What would the user enter when asked for enter a1:? A mathematical expression? Commented Mar 11, 2020 at 17:13
• yeah i set the prints before the input to show the formula so youd know what you are entering to calculate Commented Mar 11, 2020 at 20:14
• and each input like a1, r/d, is one value not an expression, tho the expression could be 1/2 for example or generally something that isnt whole and could be expressed using only fractions Commented Mar 11, 2020 at 20:14

First, you can just return the list comprehension instead of first overwriting count_list. That should save you a few lines without affecting readability.
For all of your if-cases, you could use a dictionary instead. So that if choice_sub in dict.keys(): dict[choice_sub].