I'm trying to evaluate this string. "1+2^4*4*(4+4*9)-10"
My strategy is to take each element, put it in a list, convert to the correct data type (int) or operator, concatenate and then evaluate. I'm trying to avoid using eval() and ast.literal_eval() was throwing a "malformed string error." I'm currently stuck at the point where I need to convert my operators from strings into operators.
Here's what I've done so far:
equation = ("1+2^4*4*(4+4*9)-10")
listint1 = 0
listint2 = 1
finallist = []
for elements in equation:
finallist.append(equation[listint1:listint2])
listint1 = listint1 + 1
listint2 = listint2 + 1
finalfinallist = []
for element in finallist:
if element.isdigit() == True:
finalfinallist.append(int(element))
else:
finalfinallist.append(element)
for element in finalfinallist:
if element == str:
if element == "+":
element = +
elif element == "^":
element = ^
elif element == "*":
element = *
elif element == "("
element = (
elif element == ")":
element = )
elif element == "-"
element = -
print finalfinallist
Thoughts?
What you are trying to build is a parser. You can have a look at https://en.wikipedia.org/wiki/Comparison_of_parser_generators. Parsers are used to implement context free grammars, see https://en.wikipedia.org/wiki/Context-free_grammar
I assume that by 2^4you mean exponentiation, and not bitwise-xor (as per python operators).
There may be an ambiguity when trying to parse 2^4*4, as it may be (2^4)*4 = 16 * 4 = 64, or 2^(4*4) = 2^16 = 65536. I do not know ast, but try looking at "associativity rules".
You'd probably want to start with building an expression tree, for this kind of thing!
Wikipedia: Expression Trees
This would make handling the operators somewhat easier, this way you'll know when to expect an operator, and can do a string comparison to determine what operator to use on the operands in the expression tree!
Bear in mind, I've never had to do this in Python, only in C. So if there's a more Pythonic way to do this, I'm currently unaware, and would love to hear it.
Related
Wrote this code in comp sci class and I cant get it to work, it always returns as false every time I run it. Its supposed to be a recursive binary search method... Any idea why it only returns false?
arr = [1,10,12,15,16,122,132,143,155]
def binarysearch(arr,num):
arr2 = []
if (len(arr) == 1):
if (arr[0] == num):
return 1
else:
return 0
for i in range (len(arr)/2):
arr2.append(0)
if (arr[len(arr)/2]>num):
for x in range (len(arr)/2,len(arr)):
arr2[x-(len(arr)/2)]=arr[x]
return binarysearch(arr2,num)
if(arr[len(arr)/2]<num):
for x in range(0, len(arr) / 2 ):
arr2[x] = arr[x]
return binarysearch(arr2, num)
num = raw_input("put number to check here please: ")
if(binarysearch(arr,num)==1):
print "true"
else:
print "false"
You're doing vastly more work than you need to on things that Python can handle for you, and the complexity is masking your problems.
After your base case, you have two if statements, that don't cover the full range—you've overlooked the possibility of equality. Use if/else and adjust the ranges being copied accordingly.
Don't create a new array and copy stuff, use Python's subranges.
Don't keep repeating the same division operation throughout your program, do it once and store the result.
If you want to print True/False, why not just return that rather than encoding the outcome as 0/1 and then decoding it to do the print?
Recall that raw_input returns a string, you'll need to convert it to int.
The end result of all those revisions would be:
def binary_search(arr,num):
if (len(arr) == 1):
return (arr[0] == num)
mid = len(arr) / 2
if (arr[mid] > num):
return binary_search(arr[:mid], num)
else:
return binary_search(arr[mid:], num)
num = int(raw_input("put number to check here please: "))
print binary_search(arr,num)
I'm trying to find the largest digit in a string of texts with alpha and numeric characters.
The source works in Python v2 but not in Python v3. When I run the module in Python 3 it returns with an error "TypeError: unorderable types: str() > int()
largestdigit = 0
n = 5000
with open('pg76.txt') as file:
sentence = file.read()
#FIND LARGEST DIGIT FOR SPECIFIED N SIZE
for i in range(0,n):
if sentence[i].isdigit():
if sentence[i] > largestdigit:
largestdigit = sentence[i]
#OUTPUT
print ("loaded \"pg76.txt\" of length", len(sentence))
print ("n =", n)
if largestdigit == 0:
print ("largest digit = None")
else:
print ("Largest digit =", largestdigit )
The TypeError that you see was part of a deliberate change. Python3 offers more complex and precise comparison operators and, as a result, the older "unnatural" comparisons have been removed. This is documented as part of What's New for Python3:
Python 3.0 has simplified the rules for ordering comparisons:
The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering.
Thus, expressions like 1 < '', 0 > None or len <= len are no longer
valid, and e.g. None < None raises TypeError instead of returning
False. A corollary is that sorting a heterogeneous list no longer
makes sense – all the elements must be comparable to each other. Note
that this does not apply to the == and != operators: objects of
different incomparable types always compare unequal to each other.
So, you need to either stick with characters or convert all the digits to integers. If you choose conversion:
if int(sentence[i]) > largestdigit:
largestdigit = int(sentence[i])
In the statement
if sentence[i] > largestdigit:
you are trying to compare a string value with an integer value. Python does not automatically convert a string to an integer, so even though Python 2 doesn't show you an error, the code is not doing what you assume it is.
In Python 2, when you try to compare a string and an integer, the string ALWAYS evaluates to greater than the integer. So, in your code, sentence[i] will ALWAYS be greater than largestdigit, even if you set sentence[i] to '1' and largestinteger to 9.
In Python 3, instead of assuming that strings are always greater than integers, Python throws an error, which is what you are seeing.
You need to manually convert the string to an integer using the int() method. So, that line of code will become:
if int(sentence[i]) > largestdigit:
largestdigit = int(sentence[i])
EDIT: As user falsetru mentioned in the comments, another alternative is to make everything strings, in which case Python will evaluate them based on their ASCII code, and your digits comparison will work correctly. In this case, all you need to do is modify the line where you initialize largestdigit:
largestdigit = '0'
and also the comparision you make in the OUTPUT section:
if largestdigit == '0':
I am fairly new to Python and am trying to create my own small program. Im having trouble with the replace function. I want to replace every even position in a string with its position number, and a problem occurs when the position becomes greater than 10; it just keeps replacing every character after 10 with an even number. Here is my code
def replaceEvenUntil(st,n):
for i in range(len(st)):
if i % 2 == float(0):
st = st.replace(st[i], str(i), n)
return st
>>> replaceEvenUntil("abcdefghijklmnop", 100)
'0b2d4f6h8j101214161820'
Where in my code have I made my error?
A few things:
float and str are functions in Python. You don't need to write int(0) or str('foo').
str.replace('a', 'b') replaces all occurrences of a with b. You don't really want that.
You're re-assigning st in the loop, but the size of st may change (10 is two characters), so you'll get off-by-one errors as the strings grow larger than 10 characters long.
I would construct a temporary string instead:
def replaceEvenUntil(s, n):
result = ''
for i in range(min(n, len(s))):
if i % 2 == 0:
result += str(i)
else:
result += s[i]
return result
Or with enumerate():
def replaceEvenUntil(s, n):
result = ''
for i, c in enumerate(s):
if i <= n and i % 2 == 0:
result += str(i)
else:
result += s[i]
return result
What would be the most efficient algorithm to solve a linear equation in one variable given as a string input to a function? For example, for input string:
"x + 9 – 2 - 4 + x = – x + 5 – 1 + 3 – x"
The output should be 1.
I am considering using a stack and pushing each string token onto it as I encounter spaces in the string. If the input was in polish notation then it would have been easier to pop numbers off the stack to get to a result, but I am not sure what approach to take here.
It is an interview question.
Solving the linear equation is (I hope) extremely easy for you once you've worked out the coefficients a and b in the equation a * x + b = 0.
So, the difficult part of the problem is parsing the expression and "evaluating" it to find the coefficients. Your example expression is extremely simple, it uses only the operators unary -, binary -, binary +. And =, which you could handle specially.
It is not clear from the question whether the solution should also handle expressions involving binary * and /, or parentheses. I'm wondering whether the interview question is intended:
to make you write some simple code, or
to make you ask what the real scope of the problem is before you write anything.
Both are important skills :-)
It could even be that the question is intended:
to separate those with lots of experience writing parsers (who will solve it as fast as they can write/type) from those with none (who might struggle to solve it at all within a few minutes, at least without some hints).
Anyway, to allow for future more complicated requirements, there are two common approaches to parsing arithmetic expressions: recursive descent or Dijkstra's shunting-yard algorithm. You can look these up, and if you only need the simple expressions in version 1.0 then you can use a simplified form of Dijkstra's algorithm. Then once you've parsed the expression, you need to evaluate it: use values that are linear expressions in x and interpret = as an operator with lowest possible precedence that means "subtract". The result is a linear expression in x that is equal to 0.
If you don't need complicated expressions then you can evaluate that simple example pretty much directly from left-to-right once you've tokenised it[*]:
x
x + 9
// set the "we've found minus sign" bit to negate the first thing that follows
x + 7 // and clear the negative bit
x + 3
2 * x + 3
// set the "we've found the equals sign" bit to negate everything that follows
3 * x + 3
3 * x - 2
3 * x - 1
3 * x - 4
4 * x - 4
Finally, solve a * x + b = 0 as x = - b/a.
[*] example tokenisation code, in Python:
acc = None
for idx, ch in enumerate(input):
if ch in '1234567890':
if acc is None: acc = 0
acc = 10 * acc + int(ch)
continue
if acc != None:
yield acc
acc = None
if ch in '+-=x':
yield ch
elif ch == ' ':
pass
else:
raise ValueError('illegal character "%s" at %d' % (ch, idx))
Alternative example tokenisation code, also in Python, assuming there will always be spaces between tokens as in the example. This leaves token validation to the parser:
return input.split()
ok some simple psuedo code that you could use to solve this problem
function(stinrgToParse){
arrayoftokens = stringToParse.match(RegexMatching);
foreach(arrayoftokens as token)
{
//now step through the tokens and determine what they are
//and store the neccesary information.
}
//Use the above information to do the arithmetic.
//count the number of times a variable appears positive and negative
//do the arithmetic.
//add up the numbers both positive and negative.
//return the result.
}
The first thing is to parse the string, to identify the various tokens (numbers, variables and operators), so that an expression tree can be formed by giving operator proper precedences.
Regular expressions can help, but that's not the only method (grammar parsers like boost::spirit are good too, and you can even run your own: its all a "find and recourse").
The tree can then be manipulated reducing the nodes executing those operation that deals with constants and by grouping variables related operations, executing them accordingly.
This goes on recursively until you remain with a variable related node and a constant node.
At the point the solution is calculated trivially.
They are basically the same principles that leads to the production of an interpreter or a compiler.
Consider:
from operator import add, sub
def ab(expr):
a, b, op = 0, 0, add
for t in expr.split():
if t == '+': op = add
elif t == '-': op = sub
elif t == 'x': a = op(a, 1)
else : b = op(b, int(t))
return a, b
Given an expression like 1 + x - 2 - x... this converts it to a canonical form ax+b and returns a pair of coefficients (a,b).
Now, let's obtain the coefficients from both parts of the equation:
le, ri = equation.split('=')
a1, b1 = ab(le)
a2, b2 = ab(ri)
and finally solve the trivial equation a1*x + b1 = a2*x + b2:
x = (b2 - b1) / (a1 - a2)
Of course, this only solves this particular example, without operator precedence or parentheses. To support the latter you'll need a parser, presumable a recursive descent one, which would be simper to code by hand.
I just want a function that returns true if all the elements of a List[Integer] follow each other, i.e.
noGaps(List(3,4,5)) // true
noGaps(List(4,3,5)) // false
noGaps(List(3,4,6)) // false
I have something that works but it's a bit verbose - what's the most elegant solution?
How about this?
def noGaps(xs: Seq[Int]) =
xs.size < 2 || xs.sliding(2).forall { case Seq(x, y) => y == x + 1 }
def noGaps(xs: Seq[Int]) = xs.isEmpty||xs.tail == xs.map(_+1).init
You can make it explicit that you compare the List to a Range:
def noGaps(l: Seq[Int]): Boolean =
l.isEmpty || l.sameElements(l.head to l.last)
Note that, although elegant, this is slightly less efficient than the sliding solution, due to l.last which is O(n). If n is the size of the list and i the first element for which there is a gap (or n if no gap), then the sliding solution would be performed in i steps whereas this one is performed in n + i steps.