Python: Using find function not in order - python

So the code below takes a string of inputted information (A math expression), and uses the find function to find one of the operators in "*/+-" and separates the string accordingly.
def splitting1(z):
for operators in "*/+-":
if operators in z:
position1= z.find(operators)
position2= z.rfind(operators)
text_before_operators= (z[:position1]).strip()
text_after_operators= (z[(position1+1):(position2)]).strip()
return text_before_operators,text_after_operators
My problem is that if I have an inputted expression such as 3/5*7 then position1 will first find * before finding /. I want the code to associate 'position1' with the left most operator. Is there a way to omit operator precedence when using the for/in functions? If not, is there a better string manipulator that can omit the order of precedence.
Note z is the input. And the input is limited to two operators in case that created ambiguity.

You're iterating over */+-, so the first character that's found is the first one that's returned.
You basically want to find the indexes of all of these operators and then find the largest or the smallest. Try re-writing this function to work for other side of the string:
def find_operator_right(text):
position = -1
for oper in '*/+-':
index = text.rfind(oper)
if index > position:
position = index
return position
A slightly more Pythonic solution would be something like this:
right_index = max(map(text.rfind, '+-/*'))

It looks like you are trying to lex, so I suggest you look into modules designed especially for this purpose, for example ply.
.
Saying that, I think you are on the right track for this example, but you are missing some recursion (to make a more general lexer for these):
def splitting1(z):
for char in "*/+-":
if char in z:
position = z.find(char)
text_before_operator= (z[:position]).strip()
text_after_operator= (z[position+1:]).strip()
return (char, splitting1(text_before_operator), splitting1(text_after_operator))
return ("number", z)
One way to find the left-most operator regardless of precedence i.e. omit operator precedence, is to rearrange what you iterate over:
def splitting2(z):
for char in z:
if char in "*/+-":
position = z.find(char)
text_before_operator= (z[:position]).strip()
text_after_operator= (z[position+1:]).strip()
return (char, splitting2(text_before_operator), splitting2(text_after_operator))
return ("number", z)
Note these function return a different result to your original function.

Related

Why does `n1 if eval("n1<=n2") else n2` always return `n1`?

I'm trying to write a function smaller_num(n1, n2) which returns the smaller value of two parameters. In the snippet below, although I expect the function to return "16", actually "1500" is returned for some reason. What's wrong with the logic?
def smaller_num(n1, n2):
return n1 if eval("n1<=n2") else n2
print(smaller_num("1500", "16"))
Your use of eval() is redundant. Try simply
def smaller_num(n1, n2):
return n1 if n1<=n2 else n2
It's now clear that
print(smaller_num("1500", "16"))
amounts to
"1500"<="16"
i.e. you are really comparing strings. This is done lexicographically (i.e. according to their position in the ASCII/Unicode table), character by character. So though the first character are the same ("1" and "1"), the second character ("5" vs. "6") is not "smaller or equal" for the first variable. The remaining two characters ("00") are disregarded, as the other string has run out of characters. An equivalent comparison is then "15"<="16", which also happens to be equivalent to 15<=16 as integers appear consecutively on the ASCII/Unicode table.
To do what you want, just use
print(smaller_num(1500, 16))
You may even keep your original eval() in smaller_num(), though I don't see the point.

Python - Need help understanding () vs [] when used with length

I'm new to Python and I'm messing around with this and I don't really know why when I change the brackets to parenthesis I get an error, or why I can't just use len(text - 1).
I'm looking at this code:
def reverse(text):
result = ""
length = len(text)
for i in text:
result += text[length - 1]
length -= 1
return result
Any help with understanding this is greatly appreciated!
Thanks!
You can't use text - 1 because that doesn't make sense; you cannot take 1 from a string.
Now, as for len(...) this is a function so has () for the call rather than []. You pass it the thing you want the length of.
text[length - 1] is indexing into the string, at a position, and follows the list syntax for indexing or sub-scripting.
When you use len(text - 1) you try to subtract int (1) from str (text). It is insupported operation in python (and moreover, impossible). To get a part of string you need you must use text[length - 1].
Python Parentheses
Parentheses play many different roles in Python these are some of the main roles they play:
The mathematical role:
Python parentheses act like parentheses in math as they are at the top of the Python Priority Precedence
This means that this:
>>> 3 + 4 * 2
returns:
12
Whereas with parentheses:
>>> (3 + 4) * 2
returns:
14
But that's not all, their priority also expands to Boolean expressions:
for example:
False and False or True and True
evaluates to True as and is executed before or. However, if you add some parentheses:
False and (False or True) and True
It evaluates to False as the or is executed before the and
Tuple
In python, when you put something in a tuple you use () notation.
Functions
When you declare or call a function you always need to add the parentheses after the function name. Think of them as a basket to put the arguments in. If you forget them the Python interpreter will think that you are calling a variable for example:
list
This is a variable called list and does nothing special
list() #Empty basket
This, however, is a call to a function as there is a "basket"
Square Brackets
Square Brackets also have quite a few roles:
Lists
In python, you use square brackets if you want to declare a list instead of a tuple.
List comprehension
List comprehension is actually pretty complicated so read this for more information but just know that it uses square brackets
Looking up
The main use of square brackets is to look up a value inside a list, tuple, or dictionary. Think of it like the google search bar: you write what you want and it tells you what it has. For example:
tuple = (2, 4)
if you want to get 4 you will need to look up the 2nd value of the tuple:
tuple[1] #The first value is 0
Slicing
Slicing is simply the idea of taking only certain parts of a list (or tuple, dictionary or even string). Here is an explanation by Greg Hewgill (https://stackoverflow.com/a/509295/7541446):
There is also the step value, which can be used with any of the above:
a[start:end:step] # start through not past end, by step
The key point to remember is that the :end value represents the first
value that is not in the selected slice. So, the difference beween end
and start is the number of elements selected (if step is 1, the
default).
The other feature is that start or end may be a negative number, which
means it counts from the end of the array instead of the beginning.
So:
a[-1] # last item in the array a[-2:] # last two items in the
array a[:-2] # everything except the last two items
Python is kind to the programmer if there are fewer items than you ask
for. For example, if you ask for a[:-2] and a only contains one
element, you get an empty list instead of an error. Sometimes you
would prefer the error, so you have to be aware that this may happen.
I hope this provided useful insight to explaining the difference between parentheses and square brackets.
This means that in your question len() is a function where you are putting text inside the basket. However, when you call text[length-1] you are looking up the value at position length-1
The python builtin function len() returns the length in numbers of the object in argument e.g
temp = [1, 2, 3, 4]
length = len(temp)
then the len() will return 4 in this case. but if someone write
length = len(temp-1)
then
temp-1
is not a valid object, therefor you cannot use it.
The reason you can't do len(text-1) is because text is a string type you are trying to reverse, and being a string you cannot combine it with numbers(unless they are a string, but thats a different story) without getting an error. Therefore you do len(text)-1 because len(text) would equal the length of whatever the text is(lets say four), and then you can subtract 1 from 4 because 4 is an integer.
The reason you need brackets and not parentheses when you are doing text[length-1] is because in python trying to get a single value out of a string requires the use of string[] and putting a position in the string inside the []. You use partakes to call functions like print(string) or len(text), so putting text(length-1) would create an error that basically says the program doesn't have a function named "text" and it doesn't know what to do.
Hope this helps. Tell me if you have any more questions.

Using Python, How can I evaluate an expression in the form of prefix notation compacted?

I am currently working on the python problemsets on a website called singpath. The question is:
Prefix Evaluation
Create a function that evaluates the arithmetic expression in the form of prefix notation without spaces or syntax errors. The expression is given as a string, all the numbers in the expression are integer 0~9, and the operators are +(addition), -(subtraction), *(multiplication), /(division), %(modulo), which operate just the same as those in Python.
Prefix notation, also known as Polish notation, is a form of notation for logic, arithmetic, and algebra. it places operators to the left of their operands. If the arity of the operators is fixed, the result is a syntax lacking parentheses or other brackets that can still be parsed without ambiguity.
This seems simple enough but the string is condensed with no spaces in the input to splice out the data. How could I separate the data from the string without importing modules? Furthermore how could I use the results of the data to solve the given equation? Also please keep in minf that Singpath solutions must be in ONE function that cannot use methods that couldn't be found in the standard python library. This also includes functions declared within the solution :S
Examples:
>>> eval_prefix("+34")
7
>>> eval_prefix("*−567")
-7
>>> eval_prefix("-*33+2+11")
5
>>> eval_prefix("-+5*+1243")
14
>>> eval_prefix("*+35-72")
40
>>> eval_prefix("%3/52")
1
See my point no spaces D:
OK, not as snazzy as alex jordan's lamba/reduce solution, but it doesn't choke on garbage input. It's sort of a recursive descent parser meets bubble sort abomination (I'm thinking it could be a little more efficient when it finds a solvable portion than just jumping back to the start. ;)
import operator
def eval_prefix(expr):
d = {'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.div, # for 3.x change this to operator.truediv
'%': operator.mod}
for n in range(10):
d[str(n)] = n
e = list(d.get(e, None) for e in expr)
i = 0
while i + 3 <= len(e):
o, l, r = e[i:i+3]
if type(o) == type(operator.add) and type(l) == type(r) == type(0):
e[i:i+3] = [o(l, r)]
i = 0
else:
i += 1
if len(e) != 1:
print 'Error in expression:', expr
return 0
else:
return e[0]
def test(s, v):
r = eval_prefix(s)
print s, '==', v, r, r == v
test("+34", 7)
test("*-567", -7)
test("-*33+2+11", 5)
test("-+5*+1243", 14)
test("*+35-72", 40)
test("%3/52", 1)
test("****", 0)
test("-5bob", 10)
I think the crucial bit here is "all the numbers in the expression are integer 0~9". All numbers are single digit. You don't need spaces to find out where one number ends and the next one starts. You can access the numbers directly by their string index, as lckknght said.
To convert the characters in the string into integers for calculation, use ord(ch) - 48 (because "0" has the ASCII code 48). So, to get the number stored in position 5 of input, use ord(input[5]) - 48.
To evaluate nested expressions, you can call your function recursively. The crucial assumption here is that there are always exactly two operants to an operator.
Your "one function" limitation isn't as bad as you think. Python allows defining functions inside functions. In the end, a function definition is nothing more than assigning the function to a (usually new) variable. In this case, I think you will want to use recursion. While that can also be done without an extra function, you may find it easier to define an extra recursion function for it. This is no problem for your limits:
def eval_prefix (data):
def handle_operator (operator, rest):
# You fill this in.
# and this, too.
That should be enough of a hint (if you want to use a recursive approach).
Well, one-liner fits in? Reduce in python3 is hidden in functools
Somewhat lispy :)
eval_prefix = lambda inp:\
reduce(lambda stack, symbol:\
(
(stack+[symbol]) if symbol.isdigit() \
else \
(
stack[:-2]+\
[str(
eval(
stack[-1]+symbol+stack[-2]
)
)
]
)
), inp[::-1], [])[0]
The hint that you are most likely looking for is "strings are iterable":
def eval_prefix(data):
# setup state machine
for symbol_ in data:
# update state machine
Separating the elements of the string is easy. All elements are a single character long, so you can directly iterate over (or index) the string to get at each one. Or if you want to be able to manipulate the values, you could passing the string to the list constructor.
Here are some examples of how this can work:
string = "*-567"
# iterating over each character, one at a time:
for character in string:
print(character) # prints one character from the string per line
# accessing a specific character by index:
third_char = string[2] # note indexing is zero-based, so 3rd char is at index 2
# transform string to list
list_of_characters = list(string) # will be ["*", "-", "5", "6", "7"]
As for how to solve the equation, I think there are two approaches.
One is to make your function recursive, so that each call evaluates a single operation or literal value. This is a little tricky, since you're only supposed to use one function (it would be much easier if you could have a recursive helper function that gets called with a different API than the main non-recursive function).
The other approach is to build up a stack of values and operations that you're waiting to evaluate while taking just a single iteration over the input string. This is probably easier given the one-function limit.

Python converting nested loops to simple line

In Python 2.7.x I have two lists I would like a function that returns the first value (not index) as shown below
def first_incorrect_term(polynomial, terms):
for index in range(len(polynomial), len(terms)):
if evaluate(polynomial, index) != terms[index-1]:
return evaluate(polynomial, index)
Let us assume evaluate is a function that works. I would like to replace these three lines which looks Object Oriented into something that uses the "find" or some such function in Python.
Basically I am iterating through the indices of the second list beyond the number terms in the polynomial (as I am confident the first X terms will match), evaluating it and comparing with the expected terms. For the first instance where the terms do not match I would like the evaluated polynomial returned.
I am looking for a replacement of these 3 lines using a Python find/lambda or some such thing, this is because I can definitely see I am not using the Python power as described for example in the link
PS: This is somewhat related to a Project Euler problem, however I have solved it using the snippet above and would like to improve my "Python" skills :)
Firstly, use yield to make a generator version of your function:
def incorrect_terms(polynomial, terms):
for index in range(len(polynomial), len(terms)):
eval = evaluate(polynomial,index)
if eval != terms[index-1]:
yield (polynomial, index, eval)
Then the first result is the first mismatch:
mismatches = incorrect_terms(polynomial, terms)
first_mismatch = mismatches.next()
I think you actually want to iterate over all the values of terms, not the values after polynomial's length, in which case you can zip:
results = (evaluate(polynomial,index) for index in count(0))
pairsToCompare = itertools.izip(results, terms)
mismatches = (pair for pair in pairsToCompare if pair[0] != pair[1])
first_mismatch = mismatches.next()
Assuming here that evaluate(polynomial, n) is calculating the nth term for a given polynomial, and that these are being compared with the values in terms.
I would do it using generator expressions, but they don't fit in one line as well:
def first_incorrect_term(polynomial, terms):
evaled = ((index, evaluate(polynomial, index)) for index in range(len(polynomial), len(terms)))
return next((val for index, val in evaled if val != terms[index-1]), None)

Storing and evaluating nested string elements

Given the exampleString = "[9+[7*3+[1+2]]-5]"
How does one extract and store elements enclosed by [] brackets, and then evaluate them in order?
1+2 --+
|
7*3+3 --+
|
9+24-5
Does one have to create somekind of nested list? Sorry for this somewhat broad question and bad English.
I see, this question is really too broad... Is there a way to create a nested list from that string? Or maybe i should simply do regex search for every element and evaluate each? The nested list option (if it exists) would be a IMO "cleaner" approach than looping over same string and evaluating until theres no [] brackets.
Have a look at pyparsing module and some examples they have (four function calculator is something you want and more).
PS. In case the size of that code worries you, look again: most of this can be stripped. The lower half are just tests. The upper part can be stripped from things like supporting e/pi/... constants, trigonometric funcitons, etc. I'm sure you can cut it down to 10 lines for what you need.
A good starting point is the the shunting-yard algorithm.
There are multiple Python implementations available online; here is one.
The algorithm can be used to translate infix notation into a variety of representations. If you are not constrained with regards to which representation you can use, I'd recommend considering Reverse Polish notation as it's easy to work with.
Here is a regex solution:
import re
def evaluatesimple(s):
return eval(s)
def evaluate(s):
while 1:
simplesums=re.findall("\[([^\]\[]*)\]",s)
if (len(simplesums) == 0):
break
replacements=[('[%s]' % item,str(evaluatesimple(item))) for item in simplesums]
for r in replacements:
s = s.replace(*r)
return s
print evaluate("[9+[7*3+[1+2]]-5]")
But if you want to go the whole hog and build a tree to evaluate later, you can use the same technique but store the expressions and sub expressions in a dict:
def tokengen():
for c in 'abcdefghijklmnopqrstuvwyxz':
yield c
def makeexpressiontree(s):
d=dict()
tokens = tokengen()
while 1:
simplesums=re.findall("\[([^\]\[]*)\]",s)
if (len(simplesums) == 0):
break
for item in simplesums:
t = tokens.next()
d[t] = item
s = s.replace("[%s]"% item,t)
return d
def evaltree(d):
"""A simple dumb way to show in principle how to evaluate the tree"""
result=0
ev={}
for i,t in zip(range(len(d)),tokengen()):
ev[t] = eval(d[t],ev)
result = ev[t]
return result
s="[9+[7*3+[1+2]]-5]"
print evaluate(s)
tree=makeexpressiontree(s)
print tree
print evaltree(tree)
(Edited to extend my answer)

Categories

Resources