how to "add" things together python - python

I wrote a function like this, the op gives a operation sign which like '+','-','*','/' or more, the code "adds" everything use the given operator,
Here is the code:
def arithmetic(op,*args):
result = args[0]
for x in args[1:]:
if op =='+':
result += x
elif op == '-':
result -= x
elif op == '*':
result *= x
elif op == '/':
result /= x
return result
Is there a way i can use the +,-,*,/ directly? So I don't have to write an If-Else statement?

You can use the corresponding operators:
import operator
def arithmetic(opname, *args):
op = {'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.div}[opname]
result = args[0]
for x in args[1:]:
result = op(result, x)
return result
or shorter, with reduce:
import operator,functools
def arithmetic(opname, arg0, *args):
op = {'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.div}[opname]
return functools.reduce(op, args, arg0)

I think you're looking for the builtin reduce function combined with operator:
import operator
a = range(10)
reduce(operator.add,a) #45
reduce(operator.sub,a) #-45
reduce(operator.mul,a) #0 -- first element is 0.
reduce(operator.div,a) #0 -- first element is 0.
Of course, if you want to do this using strings, you can map the strings to an operation using a dict:
operations = {'+':operator.add,'-':operator.sub,} # ...
then it becomes:
reduce(operations[your_operator],a)

For the + operator, you have the built-in sum function.

You can use exec:
def arithmetic(op, *args):
result = args[0]
for x in args[1:]:
exec('result ' + op + '= x')
return result

Related

Are there mathematical functions to add, substract, multiply, power, or, and that works on multiple elements passed to fuction?

The function should take multiple args and make certain mathematical operations on them (+, -, *, **, |, &). + is a deafult operator. Mathematical fuction is connected to dictionary. Below is what I,ve made so far. But i have problem with mathematical operations (dont take multiple args). Can anyone help?
Examples args: 1, 3, 5, operation='-' --> result: 1 - 3 - 5 = -7
def multi_calculator(*args: int, operation='+'):
import operator
ops = {
'+': sum,
'-': operator.sub,
'*': operator.mul,
'**': operator.pow,
'|': operator.or_,
'&': operator.and_,
}
if operation not in ops:
result = 'Unknown operator'
elif len(args) == 0:
result = 0
elif len(args) == 1:
result = args[0]
else:
result = ops[operation](args)
return result
print(multi_calculator(1, 2, 3, operation='-'))
You can use functools.reduce:
import operator
import functools
def multi_calculator(*args: int, operation='+'):
ops = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'**': operator.pow,
'|': operator.or_,
'&': operator.and_,
}
if operation not in ops:
result = 'Unknown operator'
elif len(args) == 0:
result = 0
elif len(args) == 1:
result = args[0]
else:
result = functools.reduce(ops[operation], args)
return result
print(multi_calculator(1, 2, 3, operation='-'))

converting infix to prefix in python

I am trying to write an Infix to Prefix Converter where e.g. I would like to convert this:
1 + ((C + A ) * (B - F))
to something like:
add(1, multiply(add(C, A), subtract(B, F)))
but I get this instead :
multiply(add(1, add(C, A), subtract(B, F)))
This is the code I have so far
postfix = []
temp = []
newTemp = []
def textOperator(s):
if s is '+':
return 'add('
elif s is '-':
return 'subtract('
elif s is '*':
return 'multiply('
else:
return ""
def typeof(s):
if s is '(':
return leftparentheses
elif s is ')':
return rightparentheses
elif s is '+' or s is '-' or s is '*' or s is '%' or s is '/':
return operator
elif s is ' ':
return empty
else :
return operand
infix = "1 + ((C + A ) * (B - F))"
for i in infix :
type = typeof(i)
if type is operand:
newTemp.append(i)
elif type is operator:
postfix.append(textOperator(i))
postfix.append(newTemp.pop())
postfix.append(', ')
elif type is leftparentheses :
newTemp.append(i)
elif type is rightparentheses :
next = newTemp.pop()
while next is not '(':
postfix.append(next)
next = newTemp.pop()
postfix.append(')')
newTemp.append(''.join(postfix))
while len(postfix) > 0 :
postfix.pop()
elif type is empty:
continue
print("newTemp = ", newTemp)
print("postfix = ", postfix)
while len(newTemp) > 0 :
postfix.append(newTemp.pop())
postfix.append(')')
print(''.join(postfix))
Can someone please help me figure out how I would fix this.
What I see, with the parenthetical clauses, is a recursive problem crying out for a recursive solution. The following is a rethink of your program that might give you some ideas of how to restructure it, even if you don't buy into my recursion argument:
import sys
from enum import Enum
class Type(Enum): # This could also be done with individual classes
leftparentheses = 0
rightparentheses = 1
operator = 2
empty = 3
operand = 4
OPERATORS = { # get your data out of your code...
"+": "add",
"-": "subtract",
"*": "multiply",
"%": "modulus",
"/": "divide",
}
def textOperator(string):
if string not in OPERATORS:
sys.exit("Unknown operator: " + string)
return OPERATORS[string]
def typeof(string):
if string == '(':
return Type.leftparentheses
elif string == ')':
return Type.rightparentheses
elif string in OPERATORS:
return Type.operator
elif string == ' ':
return Type.empty
else:
return Type.operand
def process(tokens):
stack = []
while tokens:
token = tokens.pop()
category = typeof(token)
print("token = ", token, " (" + str(category) + ")")
if category == Type.operand:
stack.append(token)
elif category == Type.operator:
stack.append((textOperator(token), stack.pop(), process(tokens)))
elif category == Type.leftparentheses:
stack.append(process(tokens))
elif category == Type.rightparentheses:
return stack.pop()
elif category == Type.empty:
continue
print("stack = ", stack)
return stack.pop()
INFIX = "1 + ((C + A ) * (B - F))"
# pop/append work from right, so reverse, and require a real list
postfix = process(list(INFIX[::-1]))
print(postfix)
The result of this program is a structure like:
('add', '1', ('multiply', ('add', 'C', 'A'), ('subtract', 'B', 'F')))
Which you should be able to post process into the string form you desire (again, recursively...)
PS: type and next are Python built-ins and/or reserved words, don't use them for variable names.
PPS: replace INFIX[::-1] with sys.argv[1][::-1] and you can pass test cases into the program to see what it does with them.
PPPS: like your original, this only handles single digit numbers (or single letter variables), you'll need to provide a better tokenizer than list() to get that working right.

int() can't convert non-string with explicit base

This is my code:
import easygui
from random import randint
Minimum = easygui.enterbox(msg = "Choose your minimum number")
Maximum = easygui.enterbox(msg = "Choose your maximum number")
operator = easygui.enterbox( msg="which operator would you like to use? X,/,+ or - ?",title="operator")
questions = easygui.enterbox(msg = "enter your desired amount of questions")
for a in range(int(questions)):
rn1 = randint(int(Minimum), int(Maximum))
rn2 = randint(int(Minimum), int(Maximum))
answer = easygui.enterbox("%s %s %s =?" %(rn1, operator, rn2))
realanswer = operator (int(rn1,rn2))
if answer == realanswer:
print "Correct"
else:
print 'Incorrect, the answer was' ,realanswer
When I try and run it, all the enterboxes come up fine, it is when it looks at line 13 that it produces this error:
int() can't convert non-string with explicit base
I tried running the code without the int(), and then it gives me:
'str' object is not callable
First: Your operator is a string, not a function. You can't call '/'(2,3), so if operator=='/', you still can't call operator(2,3).
Second: int(rn1), int(rn2) is how you convert two different numbers to integers, not int(rn1, rn2).
Third: Return values from randint() are already integers, and don't need to be converted again.
I'd suggest converting your numbers to integers as they're entered, only once, rather than doing so on each reference. Thus:
minimum = int(easygui.enterbox(msg="Choose your minimum number"))
maximum = int(easygui.enterbox(msg="Choose your maximum number"))
operator = easygui.enterbox(msg="which operator would you like to use? X,/,+ or - ?", title="operator")
questions = int(easygui.enterbox(msg="enter your desired amount of questions"))
# Select a function associated with the chosen operator
operators = {
'*': lambda a,b: a*b,
'/': lambda a,b: a/b,
'+': lambda a,b: a+b,
'-': lambda a,b: a-b,
}
operator_fn = operators.get(operator)
if operator_fn is None:
raise Exception('Unknown operator %r' % operator)
for a in range(questions):
rn1 = randint(minimum, maximum))
rn2 = randint(minimum, maximum))
answer = int(easygui.enterbox("%s %s %s = ?" % (rn1, operator, rn2)))
realanswer = operator_fn(rn1,rn2)
if answer == realanswer:
print "Correct"
else:
print 'Incorrect, the answer was', realanswer
Your operator variable hold a string. You have to use that string to determine the real operation to perform.
Something like that:
if operator == "+":
realanswer = rn1 + rn2
elif operator == "-":
realanswer = rn1 - rn2
elif operator == "/":
realanswer = rn1 / rn2
elif operator == "*":
realanswer = rn1 * rn2
else
raise Exception('Bad operator {}'.format(operator))
Or better using the operator module:
# top of your program
import operator
my_operators = { '+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.div }
# ...
# and later:
realanswer = my_operators[operator](rn1,rn2)
Of course, in a real application, you would somehow have to deal with "invalid" user input. For example using proper exception handling. But this is an other story...
operator is just a string, you still need to write the code that makes it mean something. You could do something like:
if operator in ('+', 'add'):
realanswer = rn1 + rn2
elif operator in ('-', 'subtract'):
realanswer = rn1 - rn2
else:
print operator, "is not valid"

Python & regular expressions

Hi i'm making a program that will take a command such as !math(5+5) from skype and return the result, i'm having trouble getting the regex expression right, I have been reading the docs and I just can't get it right.
I am trying to support all operators, so , * /, +, -, %, and **. the trouble comes when I try to use **, either I use one regex and lose the option for exponents or have the exponent only option.
Here's my expression:
expr = re.search(r'((\d+)(\s*.?|.*\**)(\d+))', 'math(500**1000)')
And then i'm parsing it using groups,
build_expr = {
'number1': int(expr.group(2)),
'operator': expr.group(3),
'number2': int(expr.group(4))
}
results for giving the reseach module the argument with exponents:
>>> expr.group()
'500**1000'
>>> expr.group(1)
'500**1000'
>>> expr.group(2)
'500'
>>> expr.group(3)
'**100'
And it works just fine and dandy with 1 character strings, such as math(500+1000)
>>> expr.group(1)
'500+1000'
>>> expr.group(2)
'500'
>>> expr.group(3)
'+'
>>> expr.group(4)
'1000'
Here's the entire function
def math_func(expr_arg):
expr = re.search(r'((\d+)(\s*.?|.*\**)(\d+))', expr_arg)
#parse_expr = ' '.join(expr.group()).split()
build_expr = {
'number1': int(expr.group(2)),
'operator': expr.group(3),
'number2': int(expr.group(4))
}
if build_expr['operator'] == '+':
operation = build_expr['number1'] + build_expr['number2']
return str(operation)
elif build_expr['operator'] == '-':
operation = build_expr['number1'] - build_expr['number2']
return str(operation)
elif build_expr['operator'] == '/':
operation = build_expr['number1'] / build_expr['number2']
return str(operation)
elif build_expr['operator'] == '%':
operation = build_expr['number1'] % build_expr['number2']
return str(operation)
elif build_expr['operator'] == '*':
operation = build_expr['number1'] * build_expr['number2']
return str(operation)
elif build_expr['operator'] == '**':
operation = build_expr['number1'] ** build_expr['number2']
return str(operation)
else:
return 'Invalid operator'
return 'shes all good son'
f = math_func('math(500+1000)')
Message.Chat.SendMessage('>> ' + f)
It can be matched using:
(\d+)\s*([-+*/%]+)\s*(\d+)
Breakdown:
(\d+) will match one or more digits
\s* will match the whitespaces, if there's any
([-+*/%]+) will match one or more operator characters
How about just using:
(\d+)\s*(\*\*|[+/%*-])\s*(\d+)
[+/%*-] means "one character, one from the list inside brackets".
No need to wrap everything inside a capturing group, the whole match is already stored in group(0).
I'm not sure how you got to .*\** so I can't tell you what's your mistake is here, but the new regex should do the job.
Assuming you only have trusted data, you could just replace your math_func with eval and be done with it.

Turn string into operator

How can I turn a string such as "+" into the operator plus?
Use a lookup table:
import operator
ops = { "+": operator.add, "-": operator.sub } # etc.
print(ops["+"](1,1)) # prints 2
import operator
ops = {
'+' : operator.add,
'-' : operator.sub,
'*' : operator.mul,
'/' : operator.truediv, # use operator.div for Python 2
'%' : operator.mod,
'^' : operator.xor,
}
def eval_binary_expr(op1, oper, op2):
op1, op2 = int(op1), int(op2)
return ops[oper](op1, op2)
print(eval_binary_expr(*("1 + 3".split())))
print(eval_binary_expr(*("1 * 3".split())))
print(eval_binary_expr(*("1 % 3".split())))
print(eval_binary_expr(*("1 ^ 3".split())))
How about using a lookup dict, but with lambdas instead of operator library.
op = {'+': lambda x, y: x + y,
'-': lambda x, y: x - y}
Then you can do:
print(op['+'](1,2))
And it will output:
3
You can try using eval(), but it's dangerous if the strings are not coming from you.
Else you might consider creating a dictionary:
ops = {"+": (lambda x,y: x+y), "-": (lambda x,y: x-y)}
etc... and then calling ops['+'] (1,2) or, for user input:
if ops.haskey(userop):
val = ops[userop](userx,usery)
else:
pass #something about wrong operator
There is a magic method corresponding to every operator
OPERATORS = {'+': 'add', '-': 'sub', '*': 'mul', '/': 'div'}
def apply_operator(a, op, b):
method = '__%s__' % OPERATORS[op]
return getattr(b, method)(a)
apply_operator(1, '+', 2)
Use eval() if it is safe (not on servers, etc):
num_1 = 5
num_2 = 10
op = ['+', '-', '*']
result = eval(f'{num_1} {op[0]} {num_2}')
print(result)
Output :
15
I understand that you want to do something like:
5"+"7
where all 3 things would be passed by variables,
so
example:
import operator
#define operators you wanna use
allowed_operators={
"+": operator.add,
"-": operator.sub,
"*": operator.mul,
"/": operator.truediv}
#sample variables
a=5
b=7
string_operator="+"
#sample calculation => a+b
result=allowed_operators[string_operator](a,b)
print(result)
I was bugged with the same problem, using Jupyter Notebook, I was unable to import the operator module. So the above code helped give me insight but was unable to run on the platform. I figured out a somehwhat primitive way to do so with all the basic funcs and here it is: (This could be heavily refined but it’s a start…)
# Define Calculator and fill with input variables
# This example "will not" run if aplha character is use for num1/num2
def calculate_me():
num1 = input("1st number: ")
oper = input("* OR / OR + OR - : ")
num2 = input("2nd number: ")
add2 = int(num1) + int(num2)
mult2 = int(num1) * int(num2)
divd2 = int(num1) / int(num2)
sub2 = int(num1) - int(num2)
# Comparare operator strings
# If input is correct, evaluate operand variables based on operator
if num1.isdigit() and num2.isdigit():
if oper is not "*" or "/" or "+" or "-":
print("No strings or ints for the operator")
else:
pass
if oper is "*":
print(mult2)
elif oper is "/":
print(divd2)
elif oper is "+":
print(add2)
elif oper is "-":
print(sub2)
else:
return print("Try again")
# Call the function
calculate_me()
print()
calculate_me()
print()

Categories

Resources