Reputation: 593
I've been having problems with this simple hackerrank question. My code works in the compiler but hackerrank test is failing 6 test cases. One of which my output is correct for (I didn't pay premium). Is there something wrong here?
Prompt: Steve has a string of lowercase characters in range ascii[‘a’..’z’]. He wants to reduce the string to its shortest length by doing a series of operations in which he selects a pair of adjacent lowercase letters that match, and then he deletes them. For instance, the string aab could be shortened to b in one operation.
Steve’s task is to delete as many characters as possible using this method and print the resulting string. If the final string is empty, print Empty String
Ex.
aaabccddd → abccddd → abddd → abd
baab → bb → Empty String
Here is my code:
def super_reduced_string(s):
count_dict = {}
for i in s:
if (i in count_dict.keys()):
count_dict[i] += 1
else:
count_dict[i] = 1
new_string = ''
for char in count_dict.keys():
if (count_dict[char] % 2 == 1):
new_string += char
if (new_string is ''):
return 'Empty String'
else:
return new_string
Here is an example of output for which it does not work.
print(super_reduced_string('abab'))
It outputs 'Empty String'
but should output 'abab'
.
Upvotes: 3
Views: 9155
Reputation: 416
def superReducedString(s):
retString = s
i=0
while i < len(retString)-1:
if retString[i] == retString[i+1]:
if i == 0:
retString= retString[2:]
else:
retString= retString[:i] + retString[i+2:]
i = 0
else:
i += 1
return retString if retString else "Empty String"
It passes all the test cases :)
Upvotes: 0
Reputation: 11
I used a while loop to keep cutting down the string until there's no change:
def superReducedString(s):
repeat = set()
dups = set()
for char in s:
if char in repeat:
dups.add(char + char)
else:
repeat.add(char)
s_old = ''
while s_old != s:
s_old = s
for char in dups:
if char in s:
s = s.replace(char, '')
if len(s) == 0:
return 'Empty String'
else:
return s
Upvotes: 1
Reputation: 11
I solved it by creating a list and then add only unique letters and remove the last letter that found on the main string. Finally all the tests passed!
def superReducedString(self, s):
stack = []
for i in range(len(s)):
if len(stack) == 0 or s[i] != stack[-1]:
stack.append(s[i])
else:
stack.pop()
return 'Empty String' if len(stack) == 0 else ''.join(stack)
Upvotes: 1
Reputation: 2661
I solved it with recursion:
def superReducedString(s):
if not s:
return "Empty String"
for i in range(0,len(s)):
if i < len(s)-1:
if s[i] == s[i+1]:
return superReducedString(s[:i]+s[i+2:])
return s
This code loops over the string and checks if the current and next letter/position in the string are the same. If so, these two letters/positions I get sliced from the string and the newly created reduced string gets passed to the function. This occurs until there are no pairs in the string.
TESTS:
print(super_reduced_string('aaabccddd')) # 'abd'
print(super_reduced_string('aa')) # 'Empty String'
print(super_reduced_string('baab')) # 'Empty String'
Upvotes: 3
Reputation: 22314
By using a counter, your program loses track of the order in which it saw characters. By example with input 'abab'
, you program sees two a's and two b's and deletes them even though they are not adjacent. It then outputs 'Empty String'
but should output 'abab'
.
This problem is equivalent to finding unmatched parentheses, but where an opening character is its own closing character.
What this means is that it can be solved in a single traversal using a stack.
Since Python can return an actual empty string, we are going to output that instead of 'Empty String'
which could be ambiguous if given an input such as 'EEEmpty String'
.
def super_reduced_string(s):
stack = []
for c in s:
if stack and c == stack[-1]:
stack.pop()
else:
stack.append(c)
return ''.join(stack)
print(super_reduced_string('aaabab')) # 'abab'
print(super_reduced_string('aabab')) # 'bab'
print(super_reduced_string('abab')) # 'abab'
print(super_reduced_string('aaabccddd ')) # 'abd'
print(super_reduced_string('baab ')) # ''
Upvotes: 5