Python class variable in recursion function [closed] - python

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
class Solution(object):
def decode(self, s):
sub_s = ""
while self.i < len(s) and s[self.i] != "]":
if not s[self.i].isdigit():
sub_s += s[self.i]
self.i += 1
else:
n = 0
while self.i < len(s) and s[self.i].isdigit():
n = n * 10 + int(s[self.i])
self.i += 1
self.i += 1
seq = self.decode(s)
self.i += 1
sub_s += seq * n
return sub_s
def decodeString(self, s):
self.i = 0
return self.decode(s)
I'm working on leetcode problem 394 decoding string problem the problem is to convert a string.
s = "3[a]2[bc]", return "aaabcbc".
s = "3[a2[c]]", return "accaccacc".
s = "2[abc]3[cd]ef", return "abcabccdcdcdef".
The above solution is a Python version which was translated from author bluedawnstar cpp solution.
self.i is maintaining the global state throughout the recursion, is there a more Pythonic way to maintaining such variable instead using self?

You can use the following function instead with no need for a class variable:
def decode(s):
repeat = output = ''
index = 0
while index < len(s):
char = s[index]
index += 1
if char.isdigit():
repeat += char
elif char == '[':
substring, offset = decode(s[index:])
output += substring * int(repeat)
index += offset
repeat = ''
elif char == ']':
break
else:
output += char
return output, index
def decodeString(s):
return decode(s)[0]
so that:
print(decodeString("3[a]2[bc]"))
print(decodeString("3[a2[c]]"))
print(decodeString("2[abc]3[cd]ef"))
outputs:
aaabcbc
accaccacc
abcabccdcdcdef

That's a perfectly fine way to do it.
But it isn't really "global"; it's restricted to that class instance. If you have two instances of the class, each will have their own separate copy of self.i.

Related

Solving Google Code Jam 2022 "Chain Reaction" [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 days ago.
Improve this question
I´m trying to solve this problem from the Qualification Round of the contest. It successfully solves the sample, but I receive a WA (Wrong Answer) for the cases. Can anyone figure out what is wrong with my code?
I tried my best looked solutions on google, but I could not find any difference between my code and the code of other contestants.
offline = True
if(offline):
f = open("Input")
f = f.read()
f = f.split("\n")
numCases = int(f[0])
readingLine = 1
else:
numCases = int(input())
myFun = []
IPointTo = []
pointsToMe = [[] for _ in range(1)]
def greater(a,b):
if(a>b): return a
return b
def fun(i):
#Returns a pair [fun, max]
#fun = a + b
# a = fun is the sum of the fun() of all children, except the one with the lowest max
# b = greater(fun of myself, max of the child with the lowest max)
# "max" is the value greater(myfun, max of the child with lowest max)
global myFun,IPointTo,pointsToMe
if (pointsToMe[i].__len__() == 0): return [myFun[i],myFun[i]]
a = 0
for j in range(pointsToMe[i].__len__()):
child = pointsToMe[i][j]
aux = fun(child)
a += aux[0]
if(j==0 or aux[1] < lowestMax):
funOfTheChildWithLowestMax = aux[0]
lowestMax = aux[1]
a -= funOfTheChildWithLowestMax
b = greater(myFun[i],lowestMax)
return [a+b,greater(myFun[i],lowestMax)]
for case in range(numCases):
myFun = []
IPointTo = []
for i in range(3):
if(offline):
line = f[readingLine]
readingLine += 1
else:
line = input()
if(i==0):
N = int(line)
if(i==1):
line = line.split(" ")
for x in line: myFun.append(int(x))
if(i==2):
line = line.split(" ")
for x in line: IPointTo.append(int(x)-1)
pointsToMe = [[] for _ in range(N)]
for i in range(N):
if(IPointTo[i] != -1): pointsToMe[IPointTo[i]].append(i)
sum = 0
for i in range(N):
if(IPointTo[i] == -1):
aux = fun(i)
sum += aux[0]
print("Case #{}: {}".format(case + 1, sum))

finding the longest common prefix of elements inside a list

I have a sequence print(lcp(["flower","flow","flight", "dog"])) which should return fl. Currently I can get it to return flowfl.
I can locate the instances where o or w should be removed, and tried different approaches to remove them. However they seem to hit syntax issue, which I cannot seem to resolve by myself.
I would very much appreciate a little guidance to either have the tools to remedy this issue my self, or learn from a working proposed solution.
def lcp(strs):
if not isinstance(strs, list) or len(strs) == 0:
return ""
if len(strs) == 1:
return strs[0]
original = strs[0]
original_max = len(original)
result = ""
for _, word in enumerate(strs[1:],1):
current_max = len(word)
i = 0
while i < current_max and i < original_max:
copy = "".join(result)
if len(copy) and copy[i-1] not in word:
# result = result.replace(copy[i-1], "")
# result = copy[:i-1]
print(copy[i-1], copy, result.index(copy[i-1]), i, word)
if word[i] == original[i]:
result += word[i]
i += 1
return result
print(lcp(["flower","flow","flight", "dog"])) # returns flowfl should be fl
print(lcp(["dog","car"])) # works
print(lcp(["dog","racecar","car"])) # works
print(lcp([])) # works
print(lcp(["one"])) # works
I worked on an alternative which does not be solve removing inside the same loop, adding a counter at the end. However my instincts suggest it can be solved within the for and while loops without increasing code bloat.
if len(result) > 1:
counter = {char: result.count(char) for char in result}
print(counter)
I have solved this using the below approach.
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
N = len(strs)
if N == 1:
return strs[0]
len_of_small_str, small_str = self.get_min_str(strs)
ans = ""
for i in range(len_of_small_str):
ch = small_str[i]
is_qualified = True
for j in range(N):
if strs[j][i] != ch:
is_qualified = False
break
if is_qualified:
ans += ch
else:
break
return ans
def get_min_str(self, A):
min_len = len(A[0])
s = A[0]
for i in range(1, len(A)):
if len(A[i]) < min_len:
min_len = len(A[i])
s = A[i]
return min_len, s
Returns the longest prefix that the set of words have in common.
def lcp(strs):
if len(strs) == 0:
return ""
result = strs[0]
for word in strs[1:]:
for i, (l1, l2) in enumerate(zip(result, word)):
if l1 != l2:
result = result[:i]
break
else:
result = result[:i+1]
return result
Results:
>>> print(lcp(["flower","flow","flight"]))
fl
>>> print(lcp(["flower","flow","flight", "dog"]))
>>> print(lcp(["dog","car"]))
>>> print(lcp(["dog","racecar","car"]))
>>> print(lcp([]))
>>> print(lcp(["one"]))
one
>>> print(lcp(["one", "one"]))
one
You might need to rephrase your goal.
By your description you don't want the longest common prefix, but the prefix that the most words have in common with the first one.
One of your issues is that your tests only test one real case and four edgecases. Make some more real examples.
Here's my proposition: I mostly added the elif to check if we already have a difference on the first letter to then discard the entry.
It also overwrites the original to rebuild the string based on the common prefix with the next word (if there are any)
def lcp(strs):
if not isinstance(strs, list) or len(strs) == 0:
return ""
if len(strs) == 1:
return strs[0]
original = strs[0]
result = ""
for word in strs[1:]:
i = 0
while i < len(word) and i < len(original) :
if word[i] == original[i]:
result += word[i]
elif i == 0:
result = original
break
i += 1
original = result
result = ""
return original
print(lcp(["flower","flow","flight", "dog"])) # fl
print(lcp(["shift", "shill", "hunter", "shame"])) # sh
print(lcp(["dog","car"])) # dog
print(lcp(["dog","racecar","car"])) # dog
print(lcp(["dog","racecar","dodge"])) # do
print(lcp([])) # [nothing]
print(lcp(["one"])) # one

Understanding "TypeError: 'bool' object is not subscriptable" in Python [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am trying to use the code below to find the shortest path between 2 points and by doing so I am attempting to apply the Dijkstra's algorithm. For some reason the code is erroring out I was wondering if someone could have a look.
Any help is appreciated
Error:
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pip/calcdistance.py", line 86, in minDist
if distArray[v] < min and vistSet[v] == False:
TypeError: 'bool' object is not subscriptable
Python Code:
import sys
import csv
size = 100
class CalcCreate:
locationList = []
def __init__(self, size):
self.V = size
self.locationList = [] #Square brackets are an indexing operator
self.distArray = [0 for i in range(size)]
self.vistSet = [0 for i in range(size)]
self.matrix = [[0 for x in range(size)] for y in range (size)]
self.points = []
self.readData()
self.storeDist()
self.INF = 1000000
def readData(self):
with open('/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pip/Locations.csv') as f:
csv_reader = csv.reader(f)
index = 0
next(csv_reader)
for line in csv_reader:
pointName = line[0]
x = line[1]
y = line[2]
number = line[3]
edge = line[4]
water=False
if line[5] == "W":
water=True
self.locationList.append( [pointName, x, y, number, edge, water] ) # etc
if not pointName in self.points:
self.points.append(pointName)
index += 1
f.close()
def storeDist(self):
for index in range(0, len(self.locationList)-1):
if self.locationList[index][4] !="":
start = self.locationList[index][0]
end = self.locationList[index][4]
for indexA in range(0, len(self.points)-1):
if self.points[indexA] == start:
indexPointA = indexA
for indexB in range(0, len(self.points)-1):
if self.points[indexB] == end:
indexPointB =indexB
distance = self.computeDist(start, end)
break
break
def computeDist (self, a, b):
# provide the distance between two points a and b on a path. Assume adjacent
distance=0
return distance
def dijkstra(self, srcsize):
for i in range(self.V):
self.distArray[i] = self.INF
self.vistSet = False
self.distArray[srcsize] = 0
for i in range(self.V):
u = self.minDist(self.distArray, self.vistSet)
self.vistSet[u] = True
for v in range(self.V):
if self.matrix[u][v] > 0 and self.vistSet[v] == False and self.distArray[v] > self.distArray[u] + self.matrix[u][v]:
self.distArray[v] = self.distArray[u] + self.matrix[u][v]
self.printSolution(self.distArray)
def minDist(self, distArray, vistSet):
min = self.INF
for v in range(self.V):
if distArray[v] < min and vistSet[v] == False:
min = distArray[v]
min_index = v
return min_index
def printSolution(self, distArray):
print("Node \tDistance from 0")
for i in range(self.V):
print (i, "\t", distArray[i])
if __name__ == '__main__':
cc = CalcCreate(100)
print(cc.locationList)
cc.graph = cc.locationList
cc.dijkstra(0)
In your dijkstra function, the line self.vistSet = False appears to be missing any indexing, so it replaces the entire vistSet with the boolean False instead of setting the elements of the list to False as you probably meant to do.

How to generate alternating substrings using recursion

I have a practice question that requires me to generate x number of alternating substrings, namely "#-" & "#--" using both recursion as well as iteration. Eg.string_iteration(3) generates "#-#--#-".
I have successfully implemented the solution for the iterative method,
but I'm having trouble getting started on the recursive method. How can I proceed?
Iterative method
def string_iteration(x):
odd_block = '#-'
even_block = '#--'
current_block = ''
if x == 0:
return ''
else:
for i in range(1,x+1):
if i % 2 != 0:
current_block += odd_block
elif i % 2 == 0:
current_block += even_block
i += 1
return current_block
For recursion, you almost always just need a base case and everything else. Here, your base case it pretty simple — when x < 1, you can return an empty string:
if x < 1:
return ''
After than you just need to return the block + the result of string_iteration(x-1). After than it's just a matter of deciding which block to choose. For example:
def string_iteration(x):
# base case
if x < 1:
return ''
blocks = ('#--', '#-')
# recursion
return string_iteration(x-1) + blocks[x % 2]
string_iteration(5)
# '#-#--#-#--#-'
This boils down to
string_iteration(1) + string_iteration(2) ... string_iteration(x)
The other answer doesn't give the same result as your iterative method. If you always want it to start with the odd block, you should add the block on the right of the recursive call instead of the left:
def string_recursion(x):
odd_block = '#-'
even_block = '#--'
if x == 0:
return ''
if x % 2 != 0:
return string_recursion(x - 1) + odd_block
elif x % 2 == 0:
return string_recursion(x - 1) + even_block
For recursive solution, you need a base case and calling the function again with some other value so that at the end you will have the desired output. Here, we can break this problem recursively like - string_recursive(x) = string_recursive(x-1) + string_recursive(x-2) + ... + string_recursive(1).
def string_recursion(x, parity):
final_str = ''
if x == 0:
return ''
if parity == -1: # when parity -1 we will add odd block
final_str += odd_block
elif parity == 1:
final_str += even_block
parity *= -1 # flip the parity every time
final_str += string_recursion(x-1, parity)
return final_str
odd_block = '#-'
even_block = '#--'
print(string_recursion(3, -1)) # for x=1 case we have odd parity, hence -1
# Output: #-#--#-

Pythonic way to construct data structures [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I have implemented the following code which works perfectly without any problem. But I am not satisfied with it because it doesn't look pretty? More than anything I feel like it doesn't look like pythonic way to do it.
So I thought I ll take suggestions from the stackoverflow community. This metod is getting its data from sql query which is in another method that method return a dictionary and based the data in that dictionary I am doing pattern match and counting process. I would like to do this in a pythonic way and return a better data structure.
Here is the code:
def getLaguageUserCount(self):
bots = self.getBotUsers()
user_template_dic = self.getEnglishTemplateUsers()
print user_template_dic
user_by_language = {}
en1Users = []
en2Users = []
en3Users=[]
en3Users=[]
en4Users=[]
en5Users=[]
en_N_Users=[]
en1 = 0
en2 = 0
en3 = 0
en4 = 0
en5 = 0
enN = 0
lang_regx = re.compile(r'User_en-([1-5n])', re.M|re.I)
for userId, langCode in user_template_dic.iteritems():
if userId not in bots:
print 'printing key value'
for item in langCode:
item = item.replace('--','-')
match_lang_obj = lang_regx.match(item)
if match_lang_obj is not None:
if match_lang_obj.group(1) == '1':
en1 += 1
en1Users.append(userId)
if match_lang_obj.group(1) == '2':
en2 += 1
en2Users.append(userId)
if match_lang_obj.group(1) == '3':
en3 += 1
en3Users.append(userId)
if match_lang_obj.group(1) == '4':
en4 += 1
en4Users.append(userId)
if match_lang_obj.group(1) == '5':
en5 += 1
en5Users.append(userId)
if match_lang_obj.group(1) == 'N':
enN += 1
en_N_Users.append(userId)
else:
print "Group didn't match our regex: " + item
else:
print userId + ' is a bot'
language_count = {}
user_by_language['en-1-users'] = en1Users
user_by_language['en-2-users'] = en2Users
user_by_language['en-3-users'] = en3Users
user_by_language['en-4-users'] = en4Users
user_by_language['en-5-users'] = en5Users
user_by_language['en-N-users'] = en_N_Users
user_by_language['en-1'] = en1
user_by_language['en-2'] = en2
user_by_language['en-3'] = en3
user_by_language['en-4'] = en4
user_by_language['en-5'] = en5
user_by_language['en-n'] = enN
return user_by_language
You can avoid all these lists and add the data directly to the user_by_language dict.
I would define it as:
user_by_language = collections.defaultdict(list)
After matching the regex, just do this:
user_by_language['en-%s-users' % match_lang_obj.group(1)].append(userId)
In the end, you grab all the lengths of these elements and save them as en-1, en-2...

Categories

Resources