Evaluate mathematical expression from String - Python - python

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])

Related

Why I cannot change index inside the while loop?

I want to implement basic calculator only includes numbers, '+' and '-' in Python. But I found that I cannot change index i inside the while loop.
def basicCalculator(expression):
res = 0
sign = 1
i = 0
while i < len(expression): # using while loop here
if expression[i] == '+':
sign = 1
elif expression[i] == '-':
sign = -1
elif '0' <= expression[i] <= '9':
temp = int(expression[i])
while i + 1 < len(expression) and '0' <= expression[i + 1] <= '9':
i += 1 # want to increase i, but failed
temp = temp * 10 + int(expression[i])
res += sign * temp
return res
s = "2+3-999"
print(basicCalculator(s)) # ouput should be -994, but infinite
Then I tried another way: using for loop instead of while loop, get incorrect answer.
def basicCalculator(expression):
res = 0
sign = 1
for i in range(len(expression)): # using for loop
if expression[i] == '+':
sign = 1
elif expression[i] == '-':
sign = -1
elif '0' <= expression[i] <= '9':
temp = int(expression[i])
while i + 1 < len(expression) and '0' <= expression[i + 1] <= '9':
i += 1 # increase i
temp = temp * 10 + int(expression[i])
res += sign * temp
return res
s = "2+3-999"
print(basicCalculator(s)) # ouput should be -994, but got -1102
I don't know why I cannot change the index inside the while loop or for loop. It is not a good idea to change i in for loop. What is the best way to fix the bug?
(I wrote the same code in Java using approach 2, everything is good, any difference?)
Rather than incrementing the index in a loop within the loop, I suggest just accumulating the current number in the main loop so you have less to keep track of:
def basicCalculator(expression):
res = 0
sign = 1
num = ""
for c in expression:
if c.isdecimal():
num += c
continue
res += int(num) * sign
num = ""
if c == "+":
sign = 1
elif c == "-":
sign = -1
else:
raise ValueError(f"Invalid operator {c}")
return res + int(num) * sign
print(basicCalculator("2+3-999")) # -994

Type error: function() missing 1 required positional argument: 's'

Im new to python and im trying to write algorithm to find the longest sub string without repeating characters. I keep getting this Error: " lengthOfLongestSubstring() missing 1 required positional argument: 's' ", when i obviously call the function with the argument. why is it heppening? Thanks for any help.
class Solution:
def lengthOfLongestSubstring(self, s):
arr = [char1 for char1 in s]
help_arr = [i*0 for i in range(26)]
sub_strings = []
sub = ""
for char in s:
index = ord(char) - ord('a')
if help_arr[index] == 0:
help_arr[index] = int(1)
sub += char
else:
sub_strings.append(sub)
sub = ""
sub += char
help_arr = [i * 0 for i in range(26)]
help_arr[index] = int(1)
max(sub_strings)
def max(arr):
max = 0
index = -1
for i in range(len(arr)):
if len(arr[i]) > max:
max = len(arr[i])
index= i
return print("The answer is '{}', with the length of {}.".format(arr[index], max))
#call to function
lengthOfLongestSubstring("aabcdefffgges")
Error: " lengthOfLongestSubstring() missing 1 required positional argument: 's' "
Look at how you define this function:
def lengthOfLongestSubstring(self, s):
This requires two arguments, but when you call it, you only pass one:
lengthOfLongestSubstring("aabcdefffgges")
In this case, you can solve the problem by not using a class. It isn't needed for what you are doing. This also means you need to remove the self parameter from lengthOfLongestSubstring():
def lengthOfLongestSubstring(s):
arr = [char1 for char1 in s]
help_arr = [i*0 for i in range(26)]
sub_strings = []
sub = ""
for char in s:
index = ord(char) - ord('a')
if help_arr[index] == 0:
help_arr[index] = int(1)
sub += char
else:
sub_strings.append(sub)
sub = ""
sub += char
help_arr = [i * 0 for i in range(26)]
help_arr[index] = int(1)
max(sub_strings)
def max(arr):
max = 0
index = -1
for i in range(len(arr)):
if len(arr[i]) > max:
max = len(arr[i])
index= i
print("The answer is '{}', with the length of {}.".format(arr[index], max))
#call to function
lengthOfLongestSubstring("aabcdefffgges")
On a side note, you should not do return print(...). return here doesn't do anything useful, so I removed id.

Convert between str and int without using built-in typecasting

NB: You may not use built-in typecasting: code this yourself.
def str2int(s):
result = 0
if s[0] == '-':
sign = -1
i = 1
while i < len(s):
num = ord(s[i]) - ord('0')
result = result * 10 + num
i += 1
result = sign * result
return result
else:
i = 0
while i < len(s):
num = ord(s[i]) - ord('0')
result = result * 10 + num
i += 1
return result
NB: You may not use built-in str() or string template. Code this yourself.
def int2str(i):
strng = ""
if i > 0:
while i != 0:
num = i % 10
strng += chr(48+num)
i = i / 10
return strng[::-1]
else:
while i != 0:
num = abs(i) % 10
strng += chr(48+num)
i = abs(i) / 10
return '-' + strng[::-1]
I am a newbie and I have to write code based on basic. I write these function by myself but these look weird. Can you help me to improve code? Thank you
This maybe a better question for https://codereview.stackexchange.com/.
Not withstanding there is no error checking, one obvious comment is you have common code that can be factored out. Only capture in the if, else what is unique rather than repeat the while loop:
def str2int(s):
if s[0] == '-':
sign = -1
i = 1
else:
sign = 1
i = 0
result = 0
while i < len(s):
num = ord(s[i]) - ord('0')
result = result * 10 + num
i += 1
return sign * result
It is generally considered better form in python to iterate over list rather than indices:
def str2int(s):
sign = 1
if s[0] == '-':
sign = -1
s = s[1:]
result = 0
for c in s:
num = ord(c) - ord('0')
result = result * 10 + num
return sign * result
These last lines are equivalent to a standard map and reduce (reduce is in functools for py3). Though some would argue against it:
from functools import reduce # Py3
def str2int(s):
sign = 1
if s[0] == '-':
sign = -1
s = s[1:]
return sign * reduce(lambda x,y: x*10+y, map(lambda c: ord(c) - ord('0'), s))
There are similar opportunities to do the same for int2str().

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.

Binary Subtraction - Python

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]

Categories

Resources