Missing Operators Calculator In Python
Question:
I’m trying to write a program to find all the results of a mathematical expression and 4 missing operators which are +,*,-
and /
. for example all the results for 2?3
will be something like this:
(2+3) = 5
(2-3) = -1
(2*3) = 6
(2/3) = 0.6666666666666666
These are my codes
import itertools
expression='1?2?3'
def operation_counter(expression):
count = 0
for i in expression:
if (i == '?'):
count += 1
else:
pass
return count
def parenthesize(expression):
operators = ['?']
depth = len([s for s in expression if s in operators])
if depth == 0:
return [expression]
if depth== 1:
return ['('+ expression + ')']
answer = []
for index, symbol in enumerate(expression):
if symbol in operators:
left = expression[:index]
right = expression[(index+1):]
expressions = ['(' + lt + ')' + symbol +'(' + rt + ')'
for lt in parenthesize(left)
for rt in parenthesize(right) ]
answer.extend(expressions)
return answer
def operation_replacer(expression):
spare = expression
opr = ['+', '-', '*', '/']
operation_numbers = operation_counter(expression)
products = list(itertools.product(opr, repeat=operation_numbers))
for i in products:
pair_of_operators = str(i)
length = len(pair_of_operators)
z = []
for i in range(0,length):
s = pair_of_operators.find("'",i,length)
e = pair_of_operators.find("'",s+1,length)
x = pair_of_operators[s+1:e]
if (x != ""):
pair_of_operators = pair_of_operators[e:length]
z.append(x)
for i in z:
expression = expression.replace('?',i,1)
try:
evaluation = str(eval(expression))
except ZeroDivisionError:
evaluation = 'Division By Zero!'
print(expression + ' = ' + evaluation)
expression = spare
for i in parenthesize(expression):
result = operation_replacer(i)
print(result)
The problem is that the program works correctly for five numbers and less like: 1?2?3?4?5
but I get an error when I apply it to more complex expressions more than five numbers like: 3?6?1?5?12?6
. I tried a lot but never found the solution to this issue
This is the full traceback message:
Traceback (most recent call last):
File "C:UsersMuhammadAppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packagesIPythoncoreinteractiveshell.py", line 3417, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-14-790301a5c9b0>", line 64, in <module>
result = operation_replacer(i)
File "<ipython-input-14-790301a5c9b0>", line 55, in operation_replacer
evaluation = str(eval(expression))
File "<string>", line 1
(1)+((2)+((3)+((4)+((5?6)))))
^
SyntaxError: invalid syntax
The expected output to 6 and more numbers is too long and I can’t write all the possibilities since it exceeds the maximum characters allowed in this question
Also, I get a None
value in the results and i don’t know where is that coming from, for example see this result for 1?2?3
(1)+((2+3)) = 6
(1)+((2-3)) = 0
(1)+((2*3)) = 7
(1)+((2/3)) = 1.6666666666666665
(1)-((2+3)) = -4
(1)-((2-3)) = 2
(1)-((2*3)) = -5
(1)-((2/3)) = 0.33333333333333337
(1)*((2+3)) = 5
(1)*((2-3)) = -1
(1)*((2*3)) = 6
(1)*((2/3)) = 0.6666666666666666
(1)/((2+3)) = 0.2
(1)/((2-3)) = -1.0
(1)/((2*3)) = 0.16666666666666666
(1)/((2/3)) = 1.5
None
((1+2))+(3) = 6
((1+2))-(3) = 0
((1+2))*(3) = 9
((1+2))/(3) = 1.0
((1-2))+(3) = 2
((1-2))-(3) = -4
((1-2))*(3) = -3
((1-2))/(3) = -0.3333333333333333
((1*2))+(3) = 5
((1*2))-(3) = -1
((1*2))*(3) = 6
((1*2))/(3) = 0.6666666666666666
((1/2))+(3) = 3.5
((1/2))-(3) = -2.5
((1/2))*(3) = 1.5
((1/2))/(3) = 0.16666666666666666
None
Answers:
-
First the easy one – None
issue. You get None
because the operation_replacer
function does not return anything and that result you’re printing in the loop at the end.
-
This parser works works only for <5 values because there is a bit clumsy piece of code – preparing operation in the pair_operators
loop. I really don’t get it – from a tuple you get (the operators product) you stringify it and then parse it only to get list… You may use tuple without that entire parsing thing.
Example without paarsing
def operation_replacer(expression):
spare = expression
ops = ['+', '-', '*', '/']
ops_count = len([ch in ch in experssion if ch == '?'])
products = list(itertools.product(ops, repeat=ops_count))
for op_set in products:
for op in op_set:
expression = expression.replace('?', op, 1)
try:
evaluation = str(eval(expression))
except ZeroDivisionError:
evaluation = 'Division By Zero!'
print(expression + ' = ' + evaluation)
expression = spare
Not a real answer, but the code is too big to post as a comment. You can shorter a lot your code with the split
built-in function. You will find below a working example with 6 numbers (without parenthesis). I guess the below code can be optimized a little more by using itertools
:
import itertools
expression='1?2?3?4?5?6'
opr = ['+', '-', '*', '/']
sp = expression.split('?')
products = list(itertools.product(opr, repeat=len(sp)-1))
for product in products:
expression = [ sp[i]+product[i] for i in range(0,len(product))]
expression.append(sp[len(sp)-1])
expression = ''.join(expression)
print(expression)
I have rewritten the code and changed a lot of things, the code may not be perfect but it does the job
import itertools
string='1?2?3'
def operation_counter(string):
count = 0
for i in string:
if (i == '?'):
count += 1
else:
pass
return count
def q_positions(string):
positions = []
for i in range(len(string)):
if (string[i] == '?'):
positions.append(i)
return positions
def string_char_replacer(string,newstring,index):
string = string[:index] + newstring + string[index + 1:]
return string
def parenthesize(string):
operators = ['?']
depth = len([s for s in string if s in operators])
if depth == 0:
return [string]
if depth== 1:
return ['('+ string + ')']
answer = []
for index, symbol in enumerate(string):
if symbol in operators:
left = string[:index]
right = string[(index+1):]
strings = ['(' + lt + ')' + symbol +'(' + rt + ')'
for lt in parenthesize(left)
for rt in parenthesize(right) ]
answer.extend(strings)
return answer
def operation_replacer(string):
opr = ['+', '-', '*', '/']
operation_numbers = operation_counter(string)
products = list(itertools.product(opr, repeat=operation_numbers))
#print(products)
return products
def single_operation_list(string):
single_operators = []
for i in range(len(string)):
char = string[i]
if (char == "'" and string[i+1] != "," and string[i+1] != ")"):
single_operator = string[i+1:i+2]
single_operators.append(single_operator)
return single_operators
exp= parenthesize(string)
opr_tuple = operation_replacer(string)
opr = []
for i in opr_tuple:
tuple = str(i).replace(' ', '')
opr.append(tuple)
for i in exp:
for j in opr:
h = single_operation_list(j)
spare = i
for l in h:
i = i.replace('?',l,1)
find_q = i.find('?')
if (find_q == -1):
try:
evaluation = str(eval(i))
except ZeroDivisionError:
evaluation = 'Division By Zero!'
print(i + ' = ' + evaluation)
else:
pass
i = spare
I’m trying to write a program to find all the results of a mathematical expression and 4 missing operators which are +,*,-
and /
. for example all the results for 2?3
will be something like this:
(2+3) = 5
(2-3) = -1
(2*3) = 6
(2/3) = 0.6666666666666666
These are my codes
import itertools
expression='1?2?3'
def operation_counter(expression):
count = 0
for i in expression:
if (i == '?'):
count += 1
else:
pass
return count
def parenthesize(expression):
operators = ['?']
depth = len([s for s in expression if s in operators])
if depth == 0:
return [expression]
if depth== 1:
return ['('+ expression + ')']
answer = []
for index, symbol in enumerate(expression):
if symbol in operators:
left = expression[:index]
right = expression[(index+1):]
expressions = ['(' + lt + ')' + symbol +'(' + rt + ')'
for lt in parenthesize(left)
for rt in parenthesize(right) ]
answer.extend(expressions)
return answer
def operation_replacer(expression):
spare = expression
opr = ['+', '-', '*', '/']
operation_numbers = operation_counter(expression)
products = list(itertools.product(opr, repeat=operation_numbers))
for i in products:
pair_of_operators = str(i)
length = len(pair_of_operators)
z = []
for i in range(0,length):
s = pair_of_operators.find("'",i,length)
e = pair_of_operators.find("'",s+1,length)
x = pair_of_operators[s+1:e]
if (x != ""):
pair_of_operators = pair_of_operators[e:length]
z.append(x)
for i in z:
expression = expression.replace('?',i,1)
try:
evaluation = str(eval(expression))
except ZeroDivisionError:
evaluation = 'Division By Zero!'
print(expression + ' = ' + evaluation)
expression = spare
for i in parenthesize(expression):
result = operation_replacer(i)
print(result)
The problem is that the program works correctly for five numbers and less like: 1?2?3?4?5
but I get an error when I apply it to more complex expressions more than five numbers like: 3?6?1?5?12?6
. I tried a lot but never found the solution to this issue
This is the full traceback message:
Traceback (most recent call last):
File "C:UsersMuhammadAppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packagesIPythoncoreinteractiveshell.py", line 3417, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-14-790301a5c9b0>", line 64, in <module>
result = operation_replacer(i)
File "<ipython-input-14-790301a5c9b0>", line 55, in operation_replacer
evaluation = str(eval(expression))
File "<string>", line 1
(1)+((2)+((3)+((4)+((5?6)))))
^
SyntaxError: invalid syntax
The expected output to 6 and more numbers is too long and I can’t write all the possibilities since it exceeds the maximum characters allowed in this question
Also, I get a None
value in the results and i don’t know where is that coming from, for example see this result for 1?2?3
(1)+((2+3)) = 6
(1)+((2-3)) = 0
(1)+((2*3)) = 7
(1)+((2/3)) = 1.6666666666666665
(1)-((2+3)) = -4
(1)-((2-3)) = 2
(1)-((2*3)) = -5
(1)-((2/3)) = 0.33333333333333337
(1)*((2+3)) = 5
(1)*((2-3)) = -1
(1)*((2*3)) = 6
(1)*((2/3)) = 0.6666666666666666
(1)/((2+3)) = 0.2
(1)/((2-3)) = -1.0
(1)/((2*3)) = 0.16666666666666666
(1)/((2/3)) = 1.5
None
((1+2))+(3) = 6
((1+2))-(3) = 0
((1+2))*(3) = 9
((1+2))/(3) = 1.0
((1-2))+(3) = 2
((1-2))-(3) = -4
((1-2))*(3) = -3
((1-2))/(3) = -0.3333333333333333
((1*2))+(3) = 5
((1*2))-(3) = -1
((1*2))*(3) = 6
((1*2))/(3) = 0.6666666666666666
((1/2))+(3) = 3.5
((1/2))-(3) = -2.5
((1/2))*(3) = 1.5
((1/2))/(3) = 0.16666666666666666
None
-
First the easy one –
None
issue. You getNone
because theoperation_replacer
function does not return anything and that result you’re printing in the loop at the end. -
This parser works works only for <5 values because there is a bit clumsy piece of code – preparing operation in the
pair_operators
loop. I really don’t get it – from a tuple you get (the operators product) you stringify it and then parse it only to get list… You may use tuple without that entire parsing thing.
Example without paarsing
def operation_replacer(expression):
spare = expression
ops = ['+', '-', '*', '/']
ops_count = len([ch in ch in experssion if ch == '?'])
products = list(itertools.product(ops, repeat=ops_count))
for op_set in products:
for op in op_set:
expression = expression.replace('?', op, 1)
try:
evaluation = str(eval(expression))
except ZeroDivisionError:
evaluation = 'Division By Zero!'
print(expression + ' = ' + evaluation)
expression = spare
Not a real answer, but the code is too big to post as a comment. You can shorter a lot your code with the split
built-in function. You will find below a working example with 6 numbers (without parenthesis). I guess the below code can be optimized a little more by using itertools
:
import itertools
expression='1?2?3?4?5?6'
opr = ['+', '-', '*', '/']
sp = expression.split('?')
products = list(itertools.product(opr, repeat=len(sp)-1))
for product in products:
expression = [ sp[i]+product[i] for i in range(0,len(product))]
expression.append(sp[len(sp)-1])
expression = ''.join(expression)
print(expression)
I have rewritten the code and changed a lot of things, the code may not be perfect but it does the job
import itertools
string='1?2?3'
def operation_counter(string):
count = 0
for i in string:
if (i == '?'):
count += 1
else:
pass
return count
def q_positions(string):
positions = []
for i in range(len(string)):
if (string[i] == '?'):
positions.append(i)
return positions
def string_char_replacer(string,newstring,index):
string = string[:index] + newstring + string[index + 1:]
return string
def parenthesize(string):
operators = ['?']
depth = len([s for s in string if s in operators])
if depth == 0:
return [string]
if depth== 1:
return ['('+ string + ')']
answer = []
for index, symbol in enumerate(string):
if symbol in operators:
left = string[:index]
right = string[(index+1):]
strings = ['(' + lt + ')' + symbol +'(' + rt + ')'
for lt in parenthesize(left)
for rt in parenthesize(right) ]
answer.extend(strings)
return answer
def operation_replacer(string):
opr = ['+', '-', '*', '/']
operation_numbers = operation_counter(string)
products = list(itertools.product(opr, repeat=operation_numbers))
#print(products)
return products
def single_operation_list(string):
single_operators = []
for i in range(len(string)):
char = string[i]
if (char == "'" and string[i+1] != "," and string[i+1] != ")"):
single_operator = string[i+1:i+2]
single_operators.append(single_operator)
return single_operators
exp= parenthesize(string)
opr_tuple = operation_replacer(string)
opr = []
for i in opr_tuple:
tuple = str(i).replace(' ', '')
opr.append(tuple)
for i in exp:
for j in opr:
h = single_operation_list(j)
spare = i
for l in h:
i = i.replace('?',l,1)
find_q = i.find('?')
if (find_q == -1):
try:
evaluation = str(eval(i))
except ZeroDivisionError:
evaluation = 'Division By Zero!'
print(i + ' = ' + evaluation)
else:
pass
i = spare