Python for loop iterating an already iterated item - python

So I was trying to solve this leetcode problem:
Input: command = "G()(al)"
Output: "Goal"
Explanation: The Goal Parser interprets the command as follows:
G -> G
() -> o
(al) -> al
The final concatenated result is "Goal".
This is my code:
def interpret(command: str) -> str:
res = ''
for i in command:
if i == 'G':
res += i
if i == '(':
ind = command.index(i)
if command[ind + 1] == ')':
res += 'o'
if command[ind + 1] == 'a':
res += 'al'
return res
The problem is, instead of returning 'Goal', the function returns 'Goo'. So I changed the function to the following to see what's going on:
for i in command:
if i == '(':
print(command.index(i))
And the above code prints out this
1
1
which means the loop is iterating an element twice?
What did I do wrong and how can I fix the function to return the correct output?

command.index() gives you the first occurrence of '('.
Rewrite your function as follows:
def interpret(command: str) -> str:
res = ""
for c, i in enumerate(command):
if i == "G":
res += i
if i == "(":
ind = c
if command[ind + 1] == ")":
res += "o"
if command[ind + 1] == "a":
res += "al"
return res

Related

my pop( ) function does not delete the top element of a list, but rather a random one

I have created the following pop function:
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
And it worked correctly until I used it in order to reverse order of a stack of numbers and operators:
"3 6 2 + * 14 3 4 + + /"
into
"/ + + 4 3 14 * + 2 6 3".
In first iteration of while loop shown below it pushed "/" operator to the auxiliary stack and deleted it from the top of entry, which is OK - but in the second iteration it deleted "+" sign from the middle of the entry instead of the plus sign with the highest index.
def evaluation(eq):
entryunsplit = errpostfix(eq)
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
Could someone please explain me why didn't it delete the last element and how can I avoid that error?
I am putting the whole code below in case some other element turns out to be significant.
stack1 = []
max_size = 30
def push(arr,a):
if len(arr) < max_size:
arr.append(a)
def isempty(arr):
if len(arr) == 0:
return True
else:
return False
def top(arr):
if not isempty(arr):
return arr[len(arr)-1]
def pop(arr):
if not isempty(arr):
topelement = arr[len(arr)-1]
arr.remove(topelement)
return topelement
def errpostfix(eq):
entry = eq.split()
opstack = []
exit = []
priorities = { "+": 1, "-": 1, "*": 0, "/": 0 }
for token in entry:
if token == "(":
push(opstack,token)
elif token == "*" or token == "/" or token == "+" or token == "-":
if top(opstack) == "*" or top(opstack) == "/" or top(opstack) == "+" or top(opstack) == "-":
while not isempty(opstack) and priorities[top(opstack)] >= priorities[token]:
push(exit,pop(opstack))
isempty(opstack)
push(opstack,token)
elif token == ")":
while top(opstack) != "(":
push(exit,pop(opstack))
pop(opstack)
else:
push(exit,token)
while not isempty(opstack):
push(exit, pop(opstack))
output = " ".join(exit)
return output
def isop(ch):
if ch == "+" or ch == "-" or ch == "*" or ch == "/":
return True
else:
return False
def evaluation(eq):
entryunsplit = "3 6 2 + * 14 3 4 + + /"
entry = entryunsplit.split()
lengthofentry = len(entry)
stack = []
while len(stack) != lengthofentry:
push(stack,pop(entry))
The remove() operation on a list will delete the first occurrence of an item in that list, is not "random" (check the docs). If there are several repeated elements, the first one encountered will be the one that gets deleted. To delete the last element, simply use the built-in pop() method:
def pop(arr):
if not isempty(arr):
topelement = arr[-1]
arr.pop()
return topelement

Calculate by using Reverse Polish Notation (Python)

I learn about Reverse Polish Notation (:RPN).
I want to calculate Numerical formula by using RPN.
I managed to write following Program.
At a glance, this code work properly.
But, when I submitted this code to Programming Contest Site, (
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0109
) I got Wrong Answer.
What is wrong with my code?
# coding: utf-8
# Convert String to List
def String2List(s):
L = []
flag = True
l = len(s)
for i in range(l):
if s[i].isdigit() and flag:
t = ""
j = 0
while s[i+j].isdigit():
t += s[i+j]
if i+j == l-1:
break
j += 1
L.append(t)
flag = False
elif not s[i].isdigit():
L.append(s[i])
flag = True
return L
# generate Reverse Polish Notation
def RPN_list(L):
S, L2 = [], []
table = {"*": 1, "/": 1, "+": 0, "-": 0, "(": -1, ")": -1}
for i in L:
if i.isdigit():
L2.append(i)
elif i == "(":
S.append(i)
elif i == ")":
while S[-1] != "(":
L2.append(S.pop())
S.pop()
else:
if len(S) != 0 and (table[S[-1]] >= table[i]):
L2.append(S.pop())
S.append(i)
while len(S) != 0:
L2.append(S.pop())
return L2
# calculate Reverse Polish Notation
def RPN_cul(L):
St = []
for i in L:
if i == '+':
St.append(int(St.pop()) + int(St.pop()))
elif i == '-':
St.append(-int(St.pop()) + int(St.pop()))
elif i == '*':
St.append(int(St.pop()) * int(St.pop()))
elif i == '/':
a = int(St.pop())
b = float(St.pop())
St.append(b/a)
else:
St.append(i)
return St[0]
N = int(raw_input())
for i in range(N):
s = raw_input()
L = String2List(s[:-1])
L = RPN_list(L)
print int(RPN_cul(L))
Result
$ python reverse_polish_notation.py
2
4-2*3=
-2
4*(8+4+3)=
60
when I fixed as follows, It was accepted. Thanks to help me.
Before:
def RPN_list(L):
...
if len(S) != 0 and (table[S[-1]] >= table[i]):
L2.append(S.pop())
S.append(i)
...
After:
def RPN_list(L):
...
while len(S) != 0 and (table[S[-1]] >= table[i]):
L2.append(S.pop())
S.append(i)
...
polish_str="123*+4-"
#scan from left to right once you got the operator make the operation save the result again perform the operation
#result=3
polish_list=[]
for i in polish_str:
polish_list.append(i)
print(polish_list)
####
temp=[]
operator=['*',"+","/","-"]
def operation(o,a,b):
if o=="+":
result=a+b
if o=="-":
result=a-b
if o=="*":
result=a*b
if o=="/":
result=a/b
return result
for i,v in enumerate(polish_list):
if v in operator:
print(temp)
leng=len(temp)
arg1=temp.pop()
print("arg1==>",arg1)
arg2=temp.pop()
print("arg2==>",arg2)
result=operation(v,arg1,arg2)
print("result==>",result)
temp.append(result)
print("temp in iteration==>",temp)
else:
temp.append(i)
print("***final temp***",temp)

How to handle functions call in RPN

I'm having a lot of trouble converting infix notation to postfix.
For instance, I want to convert this
test(a(b+c), d()) - 3
into this
b c + a , d test 3 -
I tried this solution,
def composition(s):
i = 0
rpnstack = []
stack = []
ret = []
count = 0
while i < len(s) :
if i + 1 < len(s) and s[i + 1] == "(":
stack.append([count, rpnstack, s[i]])
i += 2
count = 1
rpnstack = []
elif s[i] == "(":
count += 1
rpnstack.append(s[i])
i += 1
elif s[i] == ")":
count -= 1
if count == 0:
for a in rpn(rpnstack):
ret.append(a)
a = stack.pop()
count = a[0]
rpnstack = a[1]
ret.append(a[2])
else:
rpnstack.append(s[i])
i += 1
else:
rpnstack.append(s[i])
i += 1
for a in rpn(rpnstack):
ret.append(a)
return ret
where RPN is the standard algorithm for the reverse polish notation and is is the infix string splitted with this regex
(\+|\-|\*|\/|\>|\<|\(|\)|\,)
But it only works sometimes.
This is the full implementation of the rpn function
operator = -10
operand = -20
leftparentheses = -30
rightparentheses = -40
empty = -50
operands = ["+", "-", "*", "/", ">", "<", "=", ","]
def precedence(s):
if s is '(':
return 0
elif s is '+' or '-':
return 1
elif s is '*' or '/' or '%':
return 2
else:
return 99
def typeof(s):
if s is '(':
return leftparentheses
elif s is ')':
return rightparentheses
elif s in operands:
return operator
elif s is ' ':
return empty
else :
return operand
def rpn(infix):
postfix = []
temp = []
for i in infix :
type = typeof(i)
if type is leftparentheses :
temp.append(i)
elif type is rightparentheses :
next = temp.pop()
while next is not '(' or skip > 0:
postfix.append(next)
next = temp.pop()
elif type is operand:
postfix.append(i)
elif type is operator:
p = precedence(i)
while len(temp) is not 0 and p <= precedence(temp[-1]) :
postfix.append(temp.pop())
temp.append(i)
elif type is empty:
continue
while len(temp) > 0 :
postfix.append(temp.pop())
return postfix
if i try to use the code against this infix expression:
i < test.func()
i get:
[' test.func', 'i ', '<']
and against this
i < 10
i get:
['i ', ' 10', '<']
How can I fix this?

nesting a string and printing deepest nest

What I have is a string that looks for example like this {[]}{([])}()and I loop it through to find if it is an open or a close bracket and append it to the list.
What I wanna do now is to find which is the deepest nasting and print it out. So in this example i would print the middle {([ but I am confused how to do it. I can append the beginning of the open brackets and then reset it but how to compare couple of them though, and printing the biggest one
my code:
def is_nested(str):
stack = []
deepest =[]
index=1
open=0
for c in str:
if c == "{" or c == "(" or c == "[" or c =="<":
stack.append(c) # this is push
deepest.append(c)
open +=1
index +=1
elif c == "}":
x = stack.pop()
index +=1
if x != "{":
index -=1
x2=parens(x)
return "False: expected %s at character index %d, but received } instead." %(x2,index)
elif c == "]":
x = stack.pop()
index +=1
if x != "[":
index -=1
x2=parens(x)
return "False: expected %s at character index %d, but received ] instead." %(x2,index)
elif c == ">":
x = stack.pop()
index +=1
if x != "<":
index -=1
x2=parens(x)
return "False: expected %s at character index %d, but received > instead." %(x2,index)
elif c == ")":
x = stack.pop()
index +=1
if x != "(":
index -=1
x2=parens(x)
return "False: expected %s at character index %d, but received ) instead." %(x2,index)
check(str)
return True
def check(str):
deepest =[]
for c in str:
if c == "{" or c == "(" or c == "[" or c =="<":
deepest.append(c)
print deepest
def parens(x):
if x == "<":
return ">"
elif x =="(":
return ")"
elif x == "{":
return "}"
elif x == "[":
return "]"
print is_nested("{[()}")
print is_nested("([)")
print is_nested("{[]({})}")
print is_nested("<()>")
print is_nested("{(<)}")
Not sure if I understand your wishes correctly, but this finds the longest sequence of successive opening brackets:
In [20]: import re
In [21]: s = '{[]}{([])}()'
In [22]: max(re.findall("[\(\[\{]+",s),key=len)
Out[22]: '{(['
You should iterate and update the current number of open brackets and keep the max value that you had while looping. You can put all open brackets on a string that you use as a stack and update max with this string if the lenght is bigger than curren length of max.
OPEN = "<[({"
CLOSED = ">])}"
def is_nested(str):
stack = []
deepest =[]
for c in str:
if c in OPEN:
stack.append(c)
if len(stack)>len(deepest):
deepest.append(c)
elif c in CLOSED:
x = stack.pop()
if OPEN.index(x) != CLOSED.index(c):
return "Error"
return ''.join(deepest)
Something like this?
def is_nested(nested_str):
opening = ['(', '{', '[', '<']
closing = {'(':')','{':'}', '[':']', '<':'>'}
braces = []
depth = 0
max_depth = 0
max_depth_index = None
for index, char in enumerate(nested_str):
if char in opening:
braces.append(char)
depth += 1
elif char == closing[braces[-1]]:
braces.pop()
depth -= 1
else:
raise ValueError("This is not a valid str")
if depth > max_depth:
max_depth = depth
max_depth_index = index
return max_depth, max_depth_index
This function takes a string with only braces, and tells you the deepest level of nesting, and the index of the opening brace of the first instance of that level of nesting. As a bonus, it will raise an error if the string is miss-formed.
>>> is_nested('{[][]}')
(2, 1)
>>> is_nested('{[][<()()>]()}[]()')
(4, 5)
>>> is_nested('{(})')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "nesting.py", line 16, in is_nested
ValueError: This is not a valid str
I've defined any character other than a brace to be an error, but this could easily be changed by modifying the else condition.
def is_nested(in_str):
stack = []
deepest = tuple()
open_b = ('(','[','{','<')
close_b = (')',']','}','>')
for i in in_str:
print stack, i
if i in open_b:
stack.append(i)
if len(stack) > len(deepest):
deepest = tuple(stack)
else:
p = stack.pop()
print p
print open_b.index(p)
print close_b[open_b.index(p)]
if i != close_b[open_b.index(p)]:
raise Exception('Wrongly nested')
if len(stack) > 0:
raise Exception('Wrongly nested')
return deepest

Splitting C string in Python

I would like to split a string similar to
'abc "defg hijk \\"l; mn\\" opqrs"; tuv'
into
(['abc', '"defg hijk \\"l; mn\\" opqrs"'], 33)
i.e. I don't want to break on semicolon inside (nested) quotes. What's the easiest way, tokenize? It doesn't hurt if it's fast, but short is better.
Edit: I forgot one more detail that makes it even more tricky. I need the position of the semicolon that is cutting off the string, or -1 if there is none. (I'm doing changes to legacy code that used to be recursive, but stackoverflowed when the string became very long.)
It's unlikely there is an easy way to solve this without a proper parser. You could probably get away with a hand built parser that doesn't require tokenizing though.
Something like the following should be a good guide:
def parse(s):
cur_s = []
strings = []
def flush_string():
strings.push(''.join(cur_s))
cur_s = []
def handle_special_cases():
# TODO: Fill this in
for c in s:
if c == ';':
break
elif c in ['\\' '"']:
handle_special_cases()
elif c == ' ':
flush_string()
else:
cur_s.push(c)
flush_string()
return strings
It's a stateful search, so simple stateless operations are not available. Here's a simple char-by-char stateful evaluator that might meet your "short" without resorting to full tokenization/parsing:
#!/usr/bin/env python
inp="""abc "defg hijk \\"l; mn\\" opqrs"; tuv'`"""
def words_to_semi(inpstr):
ret = ['']
st8 = 1 # state: 1=reg, 2=in quotes, 3=escaped quote, 4=escaped reg, 0=end
ops = { 1 : {' ': lambda c: (None,1),
'"': lambda c: (c,2),
';': lambda c: ('',0),
'\\': lambda c: (c,4),
},
2 : {'\\': lambda c: (c,3),
'"': lambda c: (c,1),
},
3 : {None: lambda c: (c,2)},
4 : {None: lambda c: (c,1)},
}
pos = 0
for C in inpstr:
oc,st8 = ops[st8].get(C, ops[st8].get(None, lambda c:(c,st8)))(C)
if not st8: break
if oc is None:
ret.append('')
else:
ret[-1] += oc
pos = pos + 1
return ret, pos
print str(words_to_semi(inp))
Just modify the ops dict (and add new states) to handle other cases; everything else is generic code.
Here's the brute-force method I went with. Brrr...
def f(s):
instr = False
inescape = False
a = ''
rs = []
cut_index = -1
for idx,ch in enumerate(s):
if instr:
a += ch
if inescape:
inescape = False
elif ch == '\\':
inescape = True
elif ch == '"':
if a:
rs += [a]
a = ''
instr = False
elif ch == '"':
if a:
rs += [a]
a = ch
instr = True
elif ch == ';':
if a:
rs += [a]
cut_index = idx
break
elif ch == ' ' or ch == '\t' or ch == '\n':
if a:
rs += [a]
a = ''
else:
a += ch
return rs, cut_index
f('abc "defg hijk \\"l; mn\\" opqrs"; tuv')

Categories