Hello guys I'm trying to creat a function that works similarly to split() function but I'm unable to make it count " " as an item and seperate it
here is my code:
def mysplit(argstr, delimitor):
A = ""
B = []
for i in argstr, delimitor:
if i != " ":
A += i
elif A != "":
B.append(A)
A = ""
if A != "":
B.append(A)
return B
print(mysplit('abc def',' '))
You problem is that your for loop is ill defined.
What are you looping on? You are trying to look at argstr character by character. The delimitor is a constant.
Result:
def mysplit(argstr, delimitor):
A = ""
B = []
for i in argstr:
if i != " ":
A += i
elif A != "":
B.append(A)
A = ""
if A != "":
B.append(A)
return B
print(mysplit('abc def',' '))
Another problem you have is that you aren't actually using the delimitor at all, instead redefining it to be " " in your code. An improvement would be:
def mysplit(argstr, delimitor):
A = ""
B = []
for i in argstr:
if i != delimitor:
A += i
elif A != "":
B.append(A)
A = ""
if A != "":
B.append(A)
return B
print(mysplit('abc def',' '))
It's possible to make your code even cleaner, but this way it should already work properly.
I see that you are insistent on wanting a ' ' in your result array. First I must warn you that this isn't consistent with what str.split does, so if you want to imitate str.split, you shouldn't do that.
But if you want it, here is a simple solution to it:
def mysplit(argstr, delimitor):
A = ""
B = []
for i in argstr:
if i != delimitor:
A += i
elif i == delimitor:
if A != "":
B.append(A)
A = ""
B.append(delimitor)
if A != "":
B.append(A)
return B
print(mysplit('abc def',' '))
because of this line:
for i in argstr, delimitor:
You're telling the for loop to iterate over those two variables, so it takes the entire string in argstr as the first iteration.
replacing it with:
for i in argstr:
does what you want.
Related
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
A friend of mine told me that she needs help with some homework, I owe her a favor so I said fine, why not. she needed help with a program that checks a sequence, if the sequence is made of the same 2 chars one after the other it will print "yes" (for example "ABABABAB" or "3$3$3$3:)
The program works fine with even length strings (for example "abab") but not with odd length one ("ububu")
I made the code messy and "bad" in purpose, computers is her worst subject so I don't want it to look obvious that someone else wrote the code
the code -
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = StringInput[0]
L2 = StringInput[1]
i = 0
while i <= len(StringInput):
if i % 2 == 0:
if StringInput[i] == L1:
i = i + 1
else:
GoodOrBad = False
break
if i % 2 != 0:
if StringInput[i] == L2:
i = i + 1
else:
GoodOrBad = False
break
if GoodOrBad == True:
print("yes")
elif GoodOrBad != True:
print("no")
main()
I hope someone will spot the problem, thanks you if you read everything :)
How about (assuming s is your string):
len(set(s[::2]))==1 & len(set(s[1::2]))==1
It checks that there is 1 char in the even locations, and 1 char in the odd locations.
a) Showing your friend bad and messy code makes her hardly a better programmer. I suggest that you explain to her in a way that she can improve her programming skills.
b) If you check for the character at the even position and find that it is good, you increment i. After that, you check if i is odd (which it is, since you found a valid character at the even position), you check if the character is valid. Instead of checking for odd position, an else should do the trick.
You can do this using two methods->
O(n)-
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = StringInput[0]
L2 = StringInput[1]
i = 2
while i < len(StringInput):
l=StringInput[i]
if(l==StringInput[i-2]):
GoodOrBad=True
else:
GoodOrBad=False
i+=1
if GoodOrBad == True:
print("yes")
elif GoodOrBad == False:
print("no")
main()
Another method->
O(1)-
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = set(StringInput[0::2])
L2 = set(StringInput[1::2])
if len(L1)==len(L2):
print("yes")
else:
print("no")
main()
There is a lot in this that I would change, but I am just showing the minimal changes to get it to work. There are 2 issues.
You have an off by one error in the code:
i = 0
while i <= len(StringInput):
# in the loop you index into StringInput
StringInput[i]
Say you have 5 characters in StringInput. Because your while loop is going from i = 0 to i < = len(StringInput), it is going to go through the values [0, 1, 2, 3, 4, 5]. That last index is a problem since it is off the end off StringInput.
It will throw a 'string index out of range' exception.
You need to use:
while i < len(StringInput)
You also need to change the second if to an elif (actually it could just be an else, but...) so you do not try to test both in the same pass of the loop. If you go into the second if after the last char has been tested in the first if it will go out of range again.
elif i % 2 != 0:
So the corrected code would be:
def main():
StringInput = input('your string here - ')
GoodOrBad = True
L1 = StringInput[0]
L2 = StringInput[1]
i = 0
while i < len(StringInput):
if i % 2 == 0:
if StringInput[i] == L1:
i = i + 1
else:
GoodOrBad = False
break
elif i % 2 != 0:
if StringInput[i] == L2:
i = i + 1
else:
GoodOrBad = False
break
if GoodOrBad == True:
print("yes")
elif GoodOrBad != True:
print("no")
main()
def main():
StringInput = input('your string here - ')
MaxLength = len(StringInput) // 2 + (len(StringInput) % 2 > 0)
start = StringInput[:2]
chained = start * MaxLength
GoodOrBad = chained[:len(StringInput)] == StringInput
if GoodOrBad == True:
print("yes")
elif GoodOrBad != True:
print("no")
I believe this does what you want. You can make it messier if this isn't bad enough.
I am writing a program to reverse the substrings enclosed in parenthesis in python. The resultant string should not contain any parenthesis. I am printing b1 and b2 and ch for testing purposes. It seems that in the second iteration of the for loop inside the while loop, the b1 variable is not updated with the correct index.
I tried to write a solution like below:
def reverseParentheses(s):
r = s
sstring = ''
astring = ''
b1 = b2 = 0
count = 0
for ch in s:
if ch == '(':
count+=1
elif ch ==')':
count+=1
else:
pass
while True:
b1 = b2 = 0
for ch in r:
if ch == '(':
b1 = r.index(ch)
print("b1= ",b1, ch)
if ch == ')':
b2 = r.index(ch)
print("b2= ",b2, ch)
sstring = r[b2-1:b1:-1]
print(r)
print(sstring)
astring = r[0:b1]+sstring+r[b2+1:]
print(astring)
r = astring
break
if len(astring)+count == len(s):
break
return r
s = "a(bcdefghijkl(mno)p)q"
print(reverseParentheses(s))
This is the output that I get:
aonmpbcdefghijklq
This is the output I expect:
apmnolkjihgfedcbq
A nice way to deal with nested delimiters is to use a stack. When you encounter an opening delimiter push a new collection to the stack. pop() when you find a closing. This will keep the order of nesting correct.
Here's one way to do this (it doesn't check for balanced parenthesis, but it's not hard to add):
s = "a(bcdefghijkl(mno)p)q"
stack = [[]] # accumulate letters in stack[0]
for l in s:
if l == '(':
stack.append([]) # start a new level
elif l == ')':
sub = stack.pop()[::-1] # pop the last level and reverse
stack[-1].extend(sub) # add to current
else:
stack[-1].append(l) # add to current
''.join(stack[0]) #'apmnolkjihgfedcbq'
A method by finding the position of the parenthesis and reversing from inside out (so the ones that are contained in-between an even number of parenthesis stay the same) and finally gets rid of the parenthesis:
s = "a(bcdefghijkl(mno)p)q"
leftp = reversed([pos for pos, char in enumerate(s) if char == "("])
rightp = [pos for pos, char in enumerate(s) if char == ")"]
for i in zip(leftp,rightp):
subs = s[i[0]+1:i[1]][::-1]
s = s[:i[0]+1]+subs+s[i[1]:]
for c in ["(", ")"]:
s = s.replace(c, "")
print(s) # Outputs "apmnolkjihgfedcbq"
EDIT
For parenthesis that are not nested, as pointed out by .#Mark Meyer, you can find them as described here and same rule applies
def find_parens(s):
toret = {}
pstack = []
for i, c in enumerate(s):
if c == '(':
pstack.append(i)
elif c == ')':
if len(pstack) == 0:
raise IndexError("No matching closing parens at: " + str(i))
toret[pstack.pop()] = i
if len(pstack) > 0:
raise IndexError("No matching opening parens at: " + str(pstack.pop()))
return toret
s = "a(bcd)efghijkl(mno)pq"
parens = find_parens(s)
for leftp, rightp in parens.items():
subs = s[leftp+1:rightp][::-1]
s = s[:leftp+1]+subs+s[rightp:]
for c in ["(", ")"]:
s = s.replace(c, "")
print(s) # Outputs "adcbefghijklonmpq"
Hi guys i got my code to work by putting everything in one function which is this
spam = ''
def enterList (names):
newList = []
while True:
names = raw_input('list a series of items and press blank when finished: ')
if names == '':
break
newList = newList + [names]
a = ''
finalText = ''
listOfStuff = []
item = 0
for i in newList:
if item < len(newList)-2:
a = (i + ', ')
listOfStuff.append(a)
item +=1
elif item == len(newList)-2:
a = (i + ' and ')
listOfStuff.append(a)
item +=1
else:
a = i
listOfStuff.append(a)
break
finalText = finalText.join(listOfStuff)
return finalText
print enterList(spam)
So the above code works as i want it to. However i was trying to do the same thing by having two separate functions, the issue that i was having was that i couldn't take the return value of one function and use it in the next function.
This is the old code
spam = ''
def enterList (names):
newList = []
while True:
names = raw_input('list a series of items and press blank when finished: ')
if names == '':
break
newList = newList + [names]
return newList
print enterList(spam)
def newFunc(Addand):
a = ''
finalText = ''
listOfStuff = []
item = 0
for i in spam:
if item < len(spam)-2:
a = (i + ', ')
listOfStuff.append(a)
item +=1
elif item == len(spam)-2:
a = (i + ' and ')
listOfStuff.append(a)
item +=1
else:
a = i
listOfStuff.append(a)
break
finalText = finalText.join(listOfStuff)
return finalText
newFunc(spam)
print newFunc (spam)
I'm not sure what I was doing wrong doing it this way.
Thanks for any help to get my head around the error with this approach.
In your first function make the return statement
return newFunc(newlist)
It's not working because the second function is never actually called.
I have a string like '....(((...((...' for which I have to generate another string 'ss(4)h5(3)ss(3)h2(2)ss(3)'.
'.' corresponds to 'ss' and the number of continous '.' is in the bracket.
'(' corresponds to 'h5' and the number of continuos '(' is in the bracket.
Currently I'm able to get the output 'ss(4)h5(3)ss(3)' and my code ignores the last two character sequences.
This is what I have done so far
def main():
stringInput = raw_input("Enter the string:")
ssCount = 0
h5Count = 0
finalString = ""
ssString = ""
h5String = ""
ssCont = True
h5Cont = True
for i in range(0, len(stringInput), 1):
if stringInput[i] == ".":
h5Cont = False
if ssCont:
ssCount = ssCount + 1
ssString = "ss(" + str(ssCount) + ")"
ssCont = True
else:
finalString = finalString + ssString
ssCont = True
ssCount = 1
elif stringInput[i] == "(":
ssCont = False
if h5Cont:
h5Count = h5Count + 1
h5String = "h5(" + str(h5Count) + ")"
h5Cont = True
else:
finalString = finalString + h5String
h5Cont = True
h5Count = 1
print finalString
main()
How to modify the code to get the desired output?
I don’t know about modifying your existing code, but to me this can be done very succinctly and pythonically using itertools.groupby. Note that I’m not sure if the 'h2' in your expected output is a typo or if it should be 'h5', which I’m assuming.
from itertools import chain, groupby
string = '....(((...((...'
def character_count(S, labels): # this allows you to customize the labels you want to use
for K, G in groupby(S):
yield labels[K], '(', str(sum(1 for c in G)), ')' # sum() counts the number of items in the iterator G
output = ''.join(chain.from_iterable(character_count(string, {'.': 'ss', '(': 'h5'}))) # joins the components into a single string
print(output)
# >>> ss(4)h5(3)ss(3)h5(2)ss(3)
#Kelvin 's answer is great, however if you want to define a function yourself, you could do it like this:
def h5ss(x):
names = {".": "ss", "(": "h5"}
count = 0
current = None
out = ""
for i in x:
if i == current:
count += 1
else:
if current is not None:
out += "{}({})".format(names[current], count)
count = 1
current = i
if current is not None:
out += "{}({})".format(names[current], count)
return out