I'm trying to write a python program that is going to encrypt the user's input message by using an equation that is also given by the user. This is going to be my first program (except "hello world" and "number guesser"). I'll try to be more specific. I think the first thing to do is, creating a list and writing all the letters and their corresponding numbers. asking for string input, and asking the user write an equation like 3x+2. What I am trying to do is, for each letter of the string input find the corresponding number from the list and use the equation to produce another output. I think I should split the message that is going to be encrypted and find the each number values, but how am I gonna make the python put those numbers into the equation? Thank you for any help
Asked
Active
Viewed 148 times
0
-
you could use `eval()` but it is not prefered method (for security reason). You could create universal function like `ax^2+bx+c` and only ask user for `a`, `b`, `c` then you can easily define `def fun(a,b,c,x): return a*x**2 + b*x + c`. Or you could try [sympy](http://www.sympy.org/en/index.html) module for symbolic mathematics. – furas Jan 11 '17 at 22:43
-
@Emre Could you give an example? It will be much easier to help this way.. – Ofer Arial Jan 11 '17 at 22:49
-
Thank you so much for the explanation! I guess I understood the way 'rednammoc' did. – Emre Çakır Jan 12 '17 at 17:32
1 Answers
0
You can go char-by-char within a for-loop and use ord() to get the ordinal number of a ascii-character. To evaluate arithmetic expressions you might use ast (see Evaluating a mathematical expression in a string). Before that you need to replace "x" with the previously gathered ordinal number.
Here's a minimal example which hopefully does exactly that.
Usage:
$ python mycrypt.py "Stack Overflow is Awesome!" "3x+2"
:251:350:293:299:323:98:239:356:305:344:308:326:335:359:98:317:347:98:197:359:305:347:335:329:305:101:
Code:
#!/usr/bin/python
import sys
import ast
import operator as op
# supported operators
operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul,
ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor,
ast.USub: op.neg}
def eval_expr(expr):
"""
>>> eval_expr('2^6')
4
>>> eval_expr('2**6')
64
>>> eval_expr('1 + 2*3**(4^5) / (6 + -7)')
-5.0
"""
return eval_(ast.parse(expr, mode='eval').body)
def eval_(node):
if isinstance(node, ast.Num): # <number>
return node.n
elif isinstance(node, ast.BinOp): # <left> <operator> <right>
return operators[type(node.op)](eval_(node.left), eval_(node.right))
elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1
return operators[type(node.op)](eval_(node.operand))
else:
raise TypeError(node)
# Your first argument (e.g. "Stack Overflow is Awesome!")
text = sys.argv[1]
# Your second argument (e.g. "3x+2")
calc = sys.argv[2]
# Print beginning
sys.stdout.write(":")
# For each character in text do your calculation
for c in text:
# Generate expression by replacing x with ascii ordinal number
# prefixed with a multiplicator.
# -> character "a" has ordinal number "97"
# -> expression "3x+2" will be changed to "3*97+2"
# likewise the expression "3*x+2" will be changed to "3**97+2"
# which might not be the expected result.
expr = calc.replace("x", "*" + str(ord(c)))
# Evaluate expression
out = eval_expr(expr)
# Print cipher with trailing colon and without newline
sys.stdout.write(str(out) + ":")
# Print ending newline
print("")
-
This one exactly what I was looking for. I'll try this and let you know. Thank you so much! – Emre Çakır Jan 12 '17 at 17:36