I am trying to make a simple calculator with an input of the whole equation, but the catch is that i can not use eval() or anything similar to it. I wrote something and is probably not the best solution but this is what i came up with. The problem is that if i enter "2 + 5" as an input the final output is an error saying that it can not int() "2+"
Here is the code:
print("Calculator 2.0")
while True:
equation = input(": ")
# Remove spaces
calculate = equation.replace(" ", "")
# Converting to list
calculate = list(calculate)
# Merging numbers next to one another
i = 0
startingIndex = -1
numCounter = 1
num = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]
while i < len(calculate):
if calculate[i] in num:
if startingIndex == -1:
startingIndex = i
numCounter += 1
else:
calculate[startingIndex : numCounter] = [''.join(calculate[startingIndex : numCounter])]
startingIndex = -1
numCounter = 1
i += 1
solved = False
answer = 0
while solved == False:
# Check for multiplication and division
i = 0
while i < len(calculate):
divideIndex = -1
multiplyIndex = -1
j = 0
while j < len(calculate):
if calculate[j] == "*":
multiplyIndex = j
elif calculate[j] == "/":
divideIndex = j
j += 1
# Solve the multiplication and division
if multiplyIndex != -1:
calculate[multiplyIndex] = str(int(calculate[multiplyIndex - 1]) * int(calculate[multiplyIndex + 1]))
del calculate[multiplyIndex - 1]
del calculate[multiplyIndex + 1]
if divideIndex != -1:
calculate[divideIndex] = str(int(calculate[divideIndex - 1] / int(calculate[divideIndex + 1])))
del calculate[divideIndex - 1]
del calculate[divideIndex + 1]
i += 1
# Check for addition and subtraction
i = 0
while i < len(calculate):
sumIndex = -1
subtractIndex = -1
j = 0
while j < len(calculate):
if calculate[j] == "+":
sumIndex = j
elif calculate[j] == "-":
subtractIndex = j
j += 1
# Solve the addition and subtraction
if sumIndex != -1:
calculate[sumIndex] = str(int(calculate[sumIndex - 1]) + int(calculate[sumIndex + 1]))
del calculate[sumIndex - 1]
del calculate[sumIndex + 1]
if subtractIndex != -1:
calculate[subtractIndex] = str(int(calculate[subtractIndex - 1]) - int(calculate[subtractIndex + 1]))
del calculate[subtractIndex - 1]
del calculate[subtractIndex + 1]
i += 1
answer = int(calculate[0])
print(answer)
solved = True
Give this a shot:
def Numbers(var):
return (
var == "0"
or var == "1"
or var == "2"
or var == "3"
or var == "4"
or var == "5"
or var == "6"
or var == "7"
or var == "8"
or var == "9"
)
def Test4Num(varstr):
n = 0
var = ""
try:
while Numbers(varstr[n]):
var += varstr[n]
n += 1
except:
pass
return (int(var), n)
def operation(string, num1, num2):
if string == "+":
return num1 + num2
if string == "-":
return num1 - num2
if string == "*":
return num1 * num2
if string == "/":
return num1 / num2
if string == "^":
return num1**num2
def operator(operato):
return (
operato == "+"
or operato == "-"
or operato == "*"
or operato == "/"
or operato == "^"
)
def eval_math_expr(expr):
negate = False
expr = expr.replace(" ", "")
while True:
try:
if expr[0] == "-": # for negative numbers
negate = True # because here the numbers are string format
expr = expr[1:]
number1 = Test4Num(expr)[0]
if negate == True:
number1 = -number1
negate = False
end_number1 = Test4Num(expr)[1]
expr = expr[end_number1:]
if expr == "":
return number1
op = expr[0]
expr = expr[1:]
number2 = Test4Num(expr)[0]
end_number2 = Test4Num(expr)[1]
result = operation(op, number1, number2)
number1 = result
expr = str(number1) + expr[end_number2:]
except Exception as e:
print(e)
break
return number1
if __name__ == "__main__":
expr = input("Enter your expression:")
print(expr + "=")
print(eval_math_expr(expr))
i'm making expression parsing algorithm using stack by python and when i input equation without whitespaces like this "1+2*3+10" it doesn't work properly,sometimes give error result and sometimes it give an error , it should be entered like "1 + 2 * 3 + 10" to work
def applyOp(a, b, op):
if op == '+': return a + b
if op == '-': return a - b
if op == '*': return a * b
if op == '/': return a // b
def evaluate(tokens):
values = Stack()
ops = Stack()
i = 0
while i < len(tokens):
if tokens[i] == ' ':
i += 1
continue
elif tokens[i] == '(':
ops.push(tokens[i])
elif tokens[i].isdigit():
val = 0
while (i < len(tokens) and
tokens[i].isdigit()):
val = (val * 10) + int(tokens[i])
i += 1
values.push(val)
elif tokens[i] == ')':
while ops.peek() != None and ops.peek() != '(':
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
# print(val2 , val1 , op)
values.push(applyOp(val1, val2, op))
ops.pop()
else:
while (ops.peek() != None and
precedence(ops.peek()) >= precedence(tokens[i])):
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
values.push(applyOp(val1, val2, op))
ops.push(tokens[i])
i += 1
while ops.peek() != None:
val2 = values.pop()
val1 = values.pop()
op = ops.pop()
values.push(applyOp(val1, val2, op))
return values.peek()
I'm not sure if this is the only problem, but
elif tokens[i].isdigit():
val = 0
while (i < len(tokens) and
tokens[i].isdigit()):
val = (val * 10) + int(tokens[i])
i += 1
values.push(val)
advances i too far. It stops when i is already pointing to something that's not a digit, and then when you advance i again at the end of the outer while loop you will miss whatever was there, which doesn't matter if it's a space - so that's why spaces fix it.
EDIT: Okay so I tried it out, swapping the mentioned elif statement with this should work:
elif tokens[i].isdigit():
val = int(tokens[i])
while i+1 < len(tokens) and tokens[i+1].isdigit():
i += 1
val = (val * 10) + int(tokens[i])
values.append(val)
I am following Cormen Leiserson Rivest Stein (clrs) book and came across "kmp algorithm" for string matching. I implemented it using Python (as-is).
However, it doesn't seem to work for some reason. where is my fault?
The code is given below:
def kmp_matcher(t,p):
n=len(t)
m=len(p)
# pi=[0]*n;
pi = compute_prefix_function(p)
q=-1
for i in range(n):
while(q>0 and p[q]!=t[i]):
q=pi[q]
if(p[q]==t[i]):
q=q+1
if(q==m):
print "pattern occurs with shift "+str(i-m)
q=pi[q]
def compute_prefix_function(p):
m=len(p)
pi =range(m)
pi[1]=0
k=0
for q in range(2,m):
while(k>0 and p[k]!=p[q]):
k=pi[k]
if(p[k]==p[q]):
k=k+1
pi[q]=k
return pi
t = 'brownfoxlazydog'
p = 'lazy'
kmp_matcher(t,p)
This is a class I wrote based on CLRs KMP algorithm, which contains what you are after. Note that only DNA "characters" are accepted here.
class KmpMatcher(object):
def __init__(self, pattern, string, stringName):
self.motif = pattern.upper()
self.seq = string.upper()
self.header = stringName
self.prefix = []
self.validBases = ['A', 'T', 'G', 'C', 'N']
#Matches the motif pattern against itself.
def computePrefix(self):
#Initialize prefix array
self.fillPrefixList()
k = 0
for pos in range(1, len(self.motif)):
#Check valid nt
if(self.motif[pos] not in self.validBases):
self.invalidMotif()
#Unique base in motif
while(k > 0 and self.motif[k] != self.motif[pos]):
k = self.prefix[k]
#repeat in motif
if(self.motif[k] == self.motif[pos]):
k += 1
self.prefix[pos] = k
#Initialize the prefix list and set first element to 0
def fillPrefixList(self):
self.prefix = [None] * len(self.motif)
self.prefix[0] = 0
#An implementation of the Knuth-Morris-Pratt algorithm for linear time string matching
def kmpSearch(self):
#Compute prefix array
self.computePrefix()
#Number of characters matched
match = 0
found = False
for pos in range(0, len(self.seq)):
#Check valid nt
if(self.seq[pos] not in self.validBases):
self.invalidSequence()
#Next character is not a match
while(match > 0 and self.motif[match] != self.seq[pos]):
match = self.prefix[match-1]
#A character match has been found
if(self.motif[match] == self.seq[pos]):
match += 1
#Motif found
if(match == len(self.motif)):
print(self.header)
print("Match found at position: " + str(pos-match+2) + ':' + str(pos+1))
found = True
match = self.prefix[match-1]
if(found == False):
print("Sorry '" + self.motif + "'" + " was not found in " + str(self.header))
#An invalid character in the motif message to the user
def invalidMotif(self):
print("Error: motif contains invalid DNA nucleotides")
exit()
#An invalid character in the sequence message to the user
def invalidSequence(self):
print("Error: " + str(self.header) + "sequence contains invalid DNA nucleotides")
exit()
You might want to try out my code:
def recursive_find_match(i, j, pattern, pattern_track):
if pattern[i] == pattern[j]:
pattern_track.append(i+1)
return {"append":pattern_track, "i": i+1, "j": j+1}
elif pattern[i] != pattern[j] and i == 0:
pattern_track.append(i)
return {"append":pattern_track, "i": i, "j": j+1}
else:
i = pattern_track[i-1]
return recursive_find_match(i, j, pattern, pattern_track)
def kmp(str_, pattern):
len_str = len(str_)
len_pattern = len(pattern)
pattern_track = []
if len_pattern == 0:
return
elif len_pattern == 1:
pattern_track = [0]
else:
pattern_track = [0]
i = 0
j = 1
while j < len_pattern:
data = recursive_find_match(i, j, pattern, pattern_track)
i = data["i"]
j = data["j"]
pattern_track = data["append"]
index_str = 0
index_pattern = 0
match_from = -1
while index_str < len_str:
if index_pattern == len_pattern:
break
if str_[index_str] == pattern[index_pattern]:
if index_pattern == 0:
match_from = index_str
index_pattern += 1
index_str += 1
else:
if index_pattern == 0:
index_str += 1
else:
index_pattern = pattern_track[index_pattern-1]
match_from = index_str - index_pattern
Try this:
def kmp_matcher(t, d):
n=len(t)
m=len(d)
pi = compute_prefix_function(d)
q = 0
i = 0
while i < n:
if d[q]==t[i]:
q=q+1
i = i + 1
else:
if q != 0:
q = pi[q-1]
else:
i = i + 1
if q == m:
print "pattern occurs with shift "+str(i-q)
q = pi[q-1]
def compute_prefix_function(p):
m=len(p)
pi =range(m)
k=1
l = 0
while k < m:
if p[k] <= p[l]:
l = l + 1
pi[k] = l
k = k + 1
else:
if l != 0:
l = pi[l-1]
else:
pi[k] = 0
k = k + 1
return pi
t = 'brownfoxlazydog'
p = 'lazy'
kmp_matcher(t, p)
KMP stands for Knuth-Morris-Pratt it is a linear time string-matching algorithm.
Note that in python, the string is ZERO BASED, (while in the book the string starts with index 1).
So we can workaround this by inserting an empty space at the beginning of both strings.
This causes four facts:
The len of both text and pattern is augmented by 1, so in the loop range, we do NOT have to insert the +1 to the right interval. (note that in python the last step is excluded);
To avoid accesses out of range, you have to check the values of k+1 and q+1 BEFORE to give them as index to arrays;
Since the length of m is augmented by 1, in kmp_matcher, before to print the response, you have to check this instead: q==m-1;
For the same reason, to calculate the correct shift you have to compute this instead: i-(m-1)
so the correct code, based on your original question, and considering the starting code from Cormen, as you have requested, would be the following:
(note : I have inserted a matching pattern inside, and some debug text that helped me to find logical errors):
def compute_prefix_function(P):
m = len(P)
pi = [None] * m
pi[1] = 0
k = 0
for q in range(2, m):
print ("q=", q, "\n")
print ("k=", k, "\n")
if ((k+1) < m):
while (k > 0 and P[k+1] != P[q]):
print ("entered while: \n")
print ("k: ", k, "\tP[k+1]: ", P[k+1], "\tq: ", q, "\tP[q]: ", P[q])
k = pi[k]
if P[k+1] == P[q]:
k = k+1
print ("Entered if: \n")
print ("k: ", k, "\tP[k]: ", P[k], "\tq: ", q, "\tP[q]: ", P[q])
pi[q] = k
print ("Outside while or if: \n")
print ("pi[", q, "] = ", k, "\n")
print ("---next---")
print ("---end for---")
return pi
def kmp_matcher(T, P):
n = len(T)
m = len(P)
pi = compute_prefix_function(P)
q = 0
for i in range(1, n):
print ("i=", i, "\n")
print ("q=", q, "\n")
print ("m=", m, "\n")
if ((q+1) < m):
while (q > 0 and P[q+1] != T[i]):
q = pi[q]
if P[q+1] == T[i]:
q = q+1
if q == m-1:
print ("Pattern occurs with shift", i-(m-1))
q = pi[q]
print("---next---")
print("---end for---")
txt = " bacbababaabcbab"
ptn = " ababaab"
kmp_matcher(txt, ptn)
(so this would be the correct accepted answer...)
hope that it helps.
I need to evaluate an expression from a string given such as "(19 + ((91 -96)-13))" but I have to make te algorithm myself, which I can't use eval() or something similar.
I've been tried alot with this code but it gives me problems with negative numbers:
while counter < 1:
chunks = []
counter2 = 1
for character in operation:
if character.isdigit():
if chunks[-1].isdigit(): # If the last chunk is already a number
chunks[-1] += character # Add onto that number
else:
chunks.append(character) # Start a new number chunk
elif character in '+-/*()':
chunks.append(character) # This doesn't account for `1 ++ 2`.
for e in reversed(chunks):
if e == '(':
counter2 = len(chunks) - counter2
break
else:
counter2 = counter2 + 1
if chunks[counter2+2] == '+':
result2 = int (chunks[counter2+1]) + int (chunks[counter2+3])
elif chunks[counter2+2] == '-':
result2 = int (chunks[counter2+1]) - int (chunks[counter2+3])
elif chunks[counter2+2] == '*':
result2 = int (chunks[counter2+1]) * int (chunks[counter2+3])
elif chunks[counter2+2] == '/':
result2 = int (chunks[counter2+1]) / int (chunks[counter2+3])
chunks[counter2] = ''
chunks[counter2 + 1] = ''
chunks[counter2 + 2] = str (result2)
chunks[counter2 + 3] = ''
chunks[counter2 + 4] = ''
operation = ''.join(chunks)
Don't pay attention to the while condition, I'm updating it as I need just to check
You should try to debug code more on your own. The problem you have is the int conversion is being done on "-" and not "-5". You need to combine "-" and integer next in the sequence and convert that to int and use.
temp = str(chunks[counter2+3]) + str(chunks[counter2+4])
I want to make a binary calculator and I have a problem with the subtraction part. Here is my code (I have tried to adapt one for sum that I've found on this website).
maxlen = max(len(s1), len(s2))
s1 = s1.zfill(maxlen)
s2 = s2.zfill(maxlen)
result = ''
carry = 0
i = maxlen - 1
while(i >= 0):
s = int(s1[i]) - int(s2[i])
if s <= 0:
if carry == 0 and s != 0:
carry = 1
result = result + "1"
else:
result = result + "0"
else:
if carry == 1:
result = result + "0"
carry = 0
else:
result = result + "1"
i = i - 1
if carry>0:
result = result + "1"
return result[::-1]
The program works fine with some binaries subtraction but it fails with others.
Can someone please help me because I can't find the mistake? Thanks a lot.
Short answer: Your code is wrong for the case when s1[i] == s2[i] and carry == 1.
Longer answer: You should restructure your code to have three separate cases for s==-1, s==0, and s==1, and then branch on the value of carry within each case:
if s == -1: # 0-1
if carry == 0:
...
else:
...
elif s == 0: # 1-1 or 0-0
if carry == 0:
...
else:
...
else: # 1-0
if carry == 0:
...
else:
...
This way you have a separate block for each possibility, so there is no chance of overlooking a case like you did on your first attempt.
I hope the answer below it helps.
def binarySubstration(str1,str2):
if len(str1) == 0:
return
if len(str2) == 0:
return
str1,str2 = normaliseString(str1,str2)
startIdx = 0
endIdx = len(str1) - 1
carry = [0] * len(str1)
result = ''
while endIdx >= startIdx:
x = int(str1[endIdx])
y = int(str2[endIdx])
sub = (carry[endIdx] + x) - y
if sub == -1:
result += '1'
carry[endIdx-1] = -1
elif sub == 1:
result += '1'
elif sub == 0:
result += '0'
else:
raise Exception('Error')
endIdx -= 1
return result[::-1]
normalising the strings
def normaliseString(str1,str2):
diff = abs((len(str1) - len(str2)))
if diff != 0:
if len(str1) < len(str2):
str1 = ('0' * diff) + str1
else:
str2 = ('0' * diff) + str2
return [str1,str2]