If I enter input with parentheses it resolves only what is inside the parentheses and not what is after or before, if I enter two expressions with parentheses it returns None.
you can see it in the code.
def divide(a, b):
return a/b
def pow(a, b):
return a**b
def addA(a, b):
return a+b
def subA(a, b):
return a-b
def mul (a, b):
return a*b
operators = {
'+': addA,
'-': subA,
'*': mul,
'/': divide,
'^' : pow,
}
def calculate(s):
if s.isdigit():
return float(s)
elif '[' in s:
start = s.index('[')
end = s.rindex(']')
return calculate(s[start + 1:end])
for c in operators.keys():
left, operator, right = s.partition(c)
if operator in operators:
return operators[operator](calculate(left), calculate(right))
calc = input("Type calculation:\n")
print("Answer: " + str(calculate(calc)))
input: [2+2]+[2+2]
output: None
input [2+3]*2
output 5
Nice idea.
elif '[' in s:
...
return calculate(s[start + 1:end])
Beautifully simple.
But, alas, wrong.
Consider 1+1+1+[8+9]+2+2+2.
Is there a [ bracket in there? Yes.
And the recursive call correctly computes 17.
But we're ignoring the 1's and the 2's.
Also, when the for finishes and we fall of the
end of the function we return None.
Consider doing something else in that case,
perhaps raise a fatal error.
You probably want to invert the order of operations,
so higher priority ops will bind more tightly.
You will find you can iterate through the edit - debug
cycle much more quickly if you write some simple
unit tests
that lock in "working" behavior. Only the last test fails ATM.
class CalculateTest(unittest.TestCase):
def test_addition(self):
self.assertEqual(5, calculate("2+3"))
self.assertEqual(5, calculate("[2+3]"))
self.assertEqual(9, calculate("2+3+4"))
self.assertEqual(9, calculate("2+[3+4]"))
I found it convenient to have the function always return a float.
Once you have this function in better shape, please
let us know
how it turned out.
The calculate function took into account the first and last parenthesis, skipping the middle ones.
Try the following:
def extract_expression(s):
start = s.rindex('[')
end = s.rindex(']')
return s[start + 1:end]
def calculate(expr):
for c in operators.keys():
left, operator, right = expr.partition(c)
if operator in operators:
return operators[operator](float(left), float(right))
def solution(s):
while '[' in s:
sub_expression = extract_expression(s)
result = calculate(sub_expression)
s = s.replace('[' + sub_expression + ']', str(result))
if s.isdigit():
return float(s)
return calculate(s)
calc = input("Type calculation:\n")
print("Answer: " + str(solution(calc)))
input: [2+2]+[2+2],
output: 8.0
input: [2+3]*2,
output: 10.0
input: 2+[2+2],
output: 6.0
Related
I'm relatively new to Python programming so please forgive me for a noob question. I am trying to see if it is at all possible to call the operation methods (add, sub, mul, div).
The program is a simple calculator which takes a series of integers and operators and performs the calculation once "=" is pressed.
A few noted for clarity;
comb is a user generated list of numbers and operators as shown in the dictionary opsymbols.
the line beginning with comb[0] is a test, eventually I'll replace this with a more complete way of performing a calculation based on the comb length
The code I'm having trouble with is as follows:
def calculator():
opsymbols = {'+':add, '-':sub, '*':mul, '/':div}
for sym in opsymbols:
if sym == comb[1]:
opsymbols[sym]
print(sym) # check to see whether the IF logic works.
a = comb[0]
print(a) # check to see if assignment of "a" works
b = comb[2]
print(b) # check to see if assignment of "b" works
def add():
a = int()
b = int()
result = a + b
print("result =" + str(result))
def sub():
a = int()
b = int()
result = a - b
print("result =" + str(result))
def mul():
a = int()
b = int()
result = a * b
print("result =" + str(result))
def div():
a = int()
b = int()
result = a / b
print("result =" + str(result))
Do you mean that call?
opsymbols[sym]()
You have also problem with shadowing variables. But still you are looking for the solution mentioned above. You need to call func in dictionary using key sym and function operator ().
Just create a second dictionary with function pointers to each one of those functions. Alternatively, you can just run eval() and add the operation code in at runtime.
Method 1:
op_dict = {'+': add, '-': sub, '*': mult, '/': div } # dict with function pointers
op_dict[op]() # call the function
Method 2:
return eval('{num1}{op}{num2}'.format(num1=num1, op=op, num2=num2))
If you're only going to have these 4 operations and there's only 2 nums you're calculating, it might be easier to use Method 2 and have all of this done in the calculate function. It would look something like:
def calculate(input):
for op in ['+', '-', '*', '/']:
if op in input:
num1 = input.rsplit(op)[0]
num2 = input.rsplit(op)[-1]
return eval('{num1}{op}{num2}'.format(num1=num1, op=op, num2=num2))
Even if you have multiple operations with multiple input numbers, you can just do a split at each operation delimiter, and run the list of those calculations through the calculate function recursively
I've stumbled upon some pretty powerful looking code. I had some trouble understanding the use of get() in a return statement and could use some guidance.
def operation(a, b):
return {a+b: "added", a-b: "subtracted", a*b: "multiplied", a/b: "divided"}.get(24)
The function returns: through what mathematical operation the result 24 can be reached from the 2 arguments a and b.
For example, calling operation(20, 4) will return 'added' while calling operation(26, 2) will return 'subtracted'.
Don't let the fact that it is all in one line confuse you. You can write any valid Python expression in a return statement. Let's look at a simplified version:
def operation(a, b):
d = {a+b: "added", a-b: "subtracted", a*b: "multiplied", a/b: "divided"}
res = d.get(24)
return res
What this does is:
On the 2 arguments given, build a dictionary with the result of different mathematical operations on those 2 arguments.
Then, try to get the result 24 from that dictionary.
if it is present, return the name of the operation it was achieved through. If not, return None.
In general in Python, dicts are a nice way of breaking down if/elif structurese to a more readable code. For example your function is equivalent to:
def operation(a, b):
if a+b == 24:
res = "added"
elif a-b == 24:
res = "subtracted"
elif a*b == 24:
res = "multiplied"
elif a/b == 24:
res = "divided"
else:
res = None
return res
As you can see, the original code is much neater.
I have two string list:
A = ['YELLOW']
B = ['BA']
I want to combine these two string using a recursive function to get
['YBAEBALBALBAOBAWBA']
HERE IS my function :
def Combine(A, B):
if len(A) > 0:
return str(A[0]) + str(B) + Combine(A[:0], B)
--
I have no idea how recursive works?
Could someone please help me!
You were very close!
def Combine(A, B):
if len(A) > 0:
return str(A[0]) + str(B) + Combine(A[1:], B) # <-- fix 1
else:
return '' # <-- fix 2
in order to call recursively with the rest of A you should call A[1:]
you took care of the case that len(A) > 0 but forgot to take care of the case that A ran out of characters (the else)
Running
A = 'YELLOW'
B = 'BA'
print(Combine(A, B))
OUTPUT
YBAEBALBALBAOBAWBA
def binary(n):
if n>0:
return binary(n//2)*10 + (n%2)
else:
return 0
The answer is 10000000 but it have to be "10000000". How can I put str on the answer?
In python, to change the type of anything, the only thing you have to do is wrap that in str(), int(), float()... or whatever type you want to change it to.
more details: http://usingpython.com/python-casting/
edit: sorry, didn't realize the recursive problem, still, I don't see why you can't just change the type after the function returns, seems the easiest thing to do.
if you insist though:
def binary(n):
if int(n)>0:
return str( int(binary(str(int(n)//2)))*10 + (int(n)%2))
else:
return str(0)
I will suggest that you use nested/inner functions as shown below to solve you problem. This allows you to compute the result using integers, and then convert the result to a string, or any other type, before returning it.
def binary(n):
def inner(m):
if m>0:
return inner(m//2)*10 + (m%2)
else:
return 0
return str(inner(n))
Alternatively you can cast n to the correct type whenever you use it. This is, in my opinion, a horrible to solve the problem, but it should still do the trick.
def binary(n):
if int(n) > 0:
return str(int(binary(n//2))*10 + n%2)
else:
return "0"
The problem with simply wrapping your return in a cast to str(), is that the subsequent calls to binary() will be affected, not just the top-level call. After the deepest recursive call to binary has finished, it will return its result - which is a string - to the next deepest recursive call to the expression:
binary(n // 2) * 10 + (n % 2)
But since the return value is a string, it fails when used in the expression.
The obvious solution is to simply cast the return value of binary() to a string from wherever it's being called. However, if for some reason you cannot do this, you can make a second function nested under binary, call this function inside of binary(), and cast its result to a string:
>>> def binary(n):
def _binary(n):
if n > 0:
return _binary(n // 2) * 10 + (n % 2)
else:
return 0
return str(_binary(n))
>>> binary(128)
'10000000'
>>> binary(64)
'1000000'
>>> binary(32)
'100000'
>>> binary(16)
'10000'
>>> binary(8)
'1000'
>>> binary(4)
'100'
>>> binary(2)
'10'
>>>
As #StefanPochmann pointed out, this method would also work:
def binary(n):
return binary(n // 2) + str(n % 2) if n > 1 else str(n)
Recently, I got an interview question which says to convert string expressions like "1+2-3" and "-2+4" to 0 and 2 respectively. Assuming the inputs are single digits numbers followed by signs and no NULL input. I tried this output but the interviewer said I am close but not perfect solution. Please help me here. Thanks.
def ans(input):
result, j = 0, 0
for i in input:
if i == '+' or i == '-':
j = i
else:
i = int(i)
result = result j i
return result
ans("1+2-3")
ans("-2+4")
I am making some silly mistake but I am learning. Thanks in advance.
Two things need fixing to work at all:
You need to handle the initial value properly; when the initial value is non-negative, this fails. Before the loop, set j = '+' so a non-sign prefixed value is added (also, for style points, j is a terrible name, could you use op or something?).
You can't use variables as operators.
Replace:
result = result j i
with:
if j == '+':
result += i
else:
result -= i
Note: If modules are allowed, a generalization can be used to handle operators the "nice" way (though more work would be needed to obey operator precedence). You'd define:
import operator
ops = {'+': operator.add, '-': operator.sub, ...}
then make the initial value of op operator.add and change the test for operators to:
if i in ops:
op = ops[i]
else:
result = op(result, int(i))
which scales to many more operators, dynamically selecting the operation to perform without cascading if/elif checks.
Side-note: While violating the spirit of the challenge, ast.literal_eval (at least as of Python 3.5, and this may change, see bug #22525) will actually safely parse strings like this (eval is unsafe, since it can execute arbitrary code, but ast.literal_eval can only parse Python literals and apparently some basic compile-time math). So you could just do:
import ast
ans = ast.literal_eval
Sure, it handles many other literals too, but we never defined the failure case behavior anyway. :-)
Using eval() is the simplest solution. Like
eval("1+2-3")
The following code give another solution without using built-in eval
import operator
class Parse(object):
def __init__(self, input):
self.input = input
self.pos = 0
self.end = len(input)
def eval(self):
result = self.match_digits()
while self.pos < self.end:
op = self.match_operator()
operand = self.match_digits()
result = op(result, operand)
return result
def match_operator(self):
look_ahead = self.input[self.pos]
self.advance()
return operator.add if look_ahead == '+' else operator.sub
def match_digits(self):
look_ahead = self.input[self.pos]
positive = 1
if look_ahead == '-':
positive = -1
self.advance()
digits, s = 0, self.pos
while s < self.end and self.input[s].isdigit():
digits = digits * 10 + int(self.input[s])
s += 1
self.advance(s-self.pos)
return digits * positive
def advance(self, offset=1):
self.pos += offset
For testing
p = Parse(input='2+1+0-3')
print p.eval()
p = Parse(input='-2+-13+3')
print p.eval()
I think the most flexible solution (not using eval and able to handle any operations) is to parse the string into a binary (red-black) tree, where leafs are numbers and branches operators (+,-,/,*,etc).
For example, "1+(5*12)/17" would be parsed into following structure:
"+"
/ \
1 "/"
/ \
"()" 17
/
"*"
/ \
5 12
Once you've parsed a string into this structure, it's easy to compute by traversing branches depth-first, right to left.
If you need to handle variables, then you'd have to get locals() and replace accordingly, either as you parse the string, or as you traverse the tree.
EDIT:
I created a working example to illustrate this, you can find the source on github: https://github.com/MJWunderlich/py-math-expression-evaluator
what about:
def f(s):
s = s.strip()
for i, c in enumerate(s):
if c == '+':
return f(s[:i]) + f(s[i+1:])
if c == '-':
return f(s[:i]) - f(s[i+1:])
for i, c in enumerate(s):
if c == '*':
return f(s[:i]) * f(s[i+1:])
if c == '/':
return f(s[:i]) / f(s[i+1:])
return 0 if s == '' else int(s)
? Doesn't work with parenthesis