0

Hey guys I'm trying to get an output of a4b2c1a2d3 with an input of aaaabbcaaddd. I think the problem with my code below is the way I implement the counter for previous. Is there an issue with index > 0:?

string1 = "aaaabbcaaddd" 
previous = ""
finalstr = ""
finalint = 1
for index, val in enumerate(string1):
    if index > 0:
        previous = string1[index - 1]
        if previous == val:
            finalint += 1
        else:
            finalstr += previous + str(finalint)
            finalint = 1
print(finalstr)

#outputs "a4b2c1a2"
3
  • 1
    You forgot to add the last count after the loop: finalstr += previous + str(finalint). Commented Sep 23, 2018 at 4:13
  • 1
    Just an FYI, since you mentioned you had this question in an interview. This question is taken directly out of the book Cracking the Coding Interview (CTCI) by Gayle McDowell, which is recommended basically everywhere for interview prep. It's in the first chapter on arrays/strings, problem 1.6 in my 3rd edition, called "String Compression." Anyways, I suggest if you're having trouble with an algorithm like this for interviews, definitely try to check out the book and work out the problems in it (and there are solutions to double check!) Commented Sep 23, 2018 at 4:33
  • 1
    Ah, I actually did go through that a little bit, but I had trouble understanding the problems and solutions since (if im not wrong) they were in Java? And I've only dealt with JS and Python, sorry, still only 6 months into programming. Thanks btw! Commented Sep 23, 2018 at 4:58

7 Answers 7

2

As I said in the comment, you forgot to add the last count after the loop:

finalstr += previous + str(finalint)

However, unless you are doing this as an assigned homework, there is a much more compact way of solving the problem:

from itertools import groupby
''.join(char + str(len(list(group))) for char,group in groupby(string1))
#'a4b2c1a2d3'

Your own code could be rewritten without indexes (they always cause troubles):

cnt = 1
finalstr = ''
for x,y in zip(string1, string1[1:]):
    if x==y:
        cnt += 1
    else:
        finalstr += x + (str(cnt) if cnt > 1 else '')
        cnt = 1
finalstr += x + (str(cnt) if cnt > 1 else '')
finalstr
#'a4b2ca2d3'
Sign up to request clarification or add additional context in comments.

2 Comments

Ah yes! thanks for that! I got this question in an interview and I had trouble implementing the previous & current variables... currently if i do add that last count, I still have the problem of an output like "a4b2c1a2d3"... how do you propose I remove 1 from "c1" so the output is just "a4b2ca2d3"?
You will need another if statement to check whether to add the count or not. (See the updated answer.)
2

This is called "run-length encoding." In the Python library more-itertools there's a function to do this encoding:

>>> from more_itertools import run_length
... 
... string1 = "aaaabbcaaddd"
... list(run_length.encode(string1))
[('a', 4), ('b', 2), ('c', 1), ('a', 2), ('d', 3)]

We can get your desired output by flattening this and string-ifying it.

>>> list(flatten(run_length.encode(string1)))
['a', 4, 'b', 2, 'c', 1, 'a', 2, 'd', 3]

>>> list(map(str, flatten(run_length.encode(string1))))
['a', '4', 'b', '2', 'c', '1', 'a', '2', 'd', '3']

>>> ''.join(map(str, flatten(run_length.encode(string1))))
'a4b2c1a2d3'

Comments

1

Simply by using groupby from itertools this can be done. And there is no need to put everything in one line.

import itertools

s = "aaaabbcaaddd"

iterator = itertools.groupby(s)
f= ""

for key, group in iterator:
    f += str(key) + str(len(list(group)))

print(f)

#output: a4b2c1a2d3

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
0

If anyone was curious of the solution I got round to (based off DYZ's help)

string1 = "aaaabbcaaddd" 
finalstr = ""
previous = ""
finalint = 0
for c, v in enumerate(string1):
    if c > 0:
        previous = string1[c - 1]
        if previous == v:
            finalint += 1
        else:
            finalstr += previous + str((finalint) if finalint > 1 else '')
            finalint = 1
finalstr += previous + str((finalint) if finalint > 1 else '')
print(finalstr)
#outputs a3b2ca2d3

Comments

0
from itertools import groupby
string1 = "aaaabbcaaddd"
string2 = ''
for c, g in groupby(string1):
    string2 += '%s%d'%(c, len(list(g)))

3 Comments

Please describe in words what was wrong with the original solution, and how your solution works.
In your algorithm you miss one case. When you will reach the end your case previous = string1[index - 1] if previous == val: will not work properly as at the end the value and the previous will be same. So it will not add last item
In order to do this you should add or statement. So, your case should look like if previous != val or index+1 == len(string1) instead of simple else
0

You could do the same using itertools groupby.

from itertools import groupby
string1 = 'aaaabbcaaddd'
result = [[k, len(list(g))] for k, g in groupby(string1)]
final = "".join([i[0]+str(i[1]) for i in result])
final 

output: #'a4b2c1a2d3'

Comments

0

I am new to programming, writing my first comment, i decided this:

string = "qaabbaaccaqwewdssss"
count = 0
temp = str()

for i in range(len(string) - 1):
    count += 1
    if string[i] != string[i + 1]:
        temp += string[i] + str(count)
        count = 0
    elif i + 1 == len(string) - 1:
        count += 1
        temp += string[i] + str(count)
        count = 0

print(temp)
#output: q1a2b2a2c2a1q1w1e1w1d1s4

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.