0

I have st = 'aaaabbсaa'. My task is if in the string characters repeat then I must write the character plus a number counting the repeats.

My code (but it doesn't work):

st = "aaaabbcaa"
cnt = 0
cnt2 = 0
cnt3 = 0
j = len(st)
i = 0
while i < j:
 if st[i] == st[i - 1]:
 cnt += 1
 print("a" + str(cnt), end="")
 elif st[i] == st[i - 1]:
 cnt2 += 1
 print("b" + str(cnt2), end="")
 elif st[i] == st[i - 1]:
 cnt3 += 1
 print("c" + str(cnt3), end="")
 i += 1 

Sample Input 1: aaaabbcaa
Sample Output 1: a4b2c1a2
Sample Input 2: abc
Sample Output 2: a1b1c1

fredtantini
16.6k8 gold badges51 silver badges58 bronze badges
asked Nov 19, 2014 at 21:06
2
  • This is called 'run-length encoding'. Commented Nov 19, 2014 at 21:09
  • 1
    All your if/elif conditions are the same. Hint: You shouldn't need one for each different letter anyway. Commented Nov 19, 2014 at 21:11

3 Answers 3

4

This looks like a task for itertools.groupby.

from itertools import groupby
data = 'aaaabbсaa'
compressed = ''.join('{}{}'.format(key, len(list(group))) for key, group in groupby(data))
print(compressed)

Result

a4b2с1a2

This might help to understand what's happening here.

data = 'aaaabbсaa'
for key, group in groupby(data):
 print(key, len(list(group)))

Result

a 4
b 2
с 1
a 2
answered Nov 19, 2014 at 21:15
Sign up to request clarification or add additional context in comments.

2 Comments

exactly how I'd do it, but I included an answer that's closer to OP's attempted code for completeness.
Yes this help too, but I needed solutions without any import :) Thnaks for help.
2

You've got three problems with your code.

First, as gnibbler points out, all of your if/elif conditions are the same. And you don't need a separate condition for each letter, you just need to print the variable (like st[i]) instead of a literal (like "a").

Second, you're trying to print out the current run length for each character in the run, instead of after the entire run. So, if you get this working, instead of a4b2c1a2 you're going to get a1a2a3a4b1b2c1a1a2. You need to keep track of the current run length for each character in the run, but then only print it out when you get to a different character.

Finally, you've got two off-by-one errors. First, when i starts at 0, st[i - 1] is st[-1], which is the last character; you don't want to compare with that. Second, when i finally gets to j-1 at the end, you've got a leftover run that you need to deal with.

So, the smallest change to your code is:

st = "aaaabbcaa"
cnt = 0
j = len(st)
i = 0
while i < j:
 if i == 0 or st[i] == st[i - 1]:
 cnt += 1
 else:
 print(st[i - 1] + str(cnt), end="")
 cnt = 1
 i += 1
print(st[i - 1] + str(cnt))

As a side note, one really easy way to improve this: range(len(st)) gives you all the numbers from 0 up to but not including len(st), so you can get rid of j and the manual i loop and just use for i in range(len(st)):.

But you can improve this even further by looping over an iterable of st[i], st[i-1] pairs; then you don't need the indexes at all. This is pretty easy with zip and slicing. And then you don't need the special handling for the edges either either:

st = "aaaabbcaa"
cnt = 1
for current, previous in zip(st[1:]+" ", st):
 if current == previous:
 cnt += 1
 else:
 print(previous + str(cnt), end="")
 cnt = 1

I think Matthias's groupby solution is more pythonic, and simpler (there's still a lot of things you could get wrong with this, like starting with cnt = 0), but this should be mostly understandable to a novice out of the box. (If you don't understand the zip(st[1:]+" ", st), try printing out st[1:], list(zip(st[1:], st)), and list(zip(st[1:]+" ", st) and it should be clearer.)

answered Nov 19, 2014 at 21:24

5 Comments

@abarnert Please recommend to me book or materials of programming in c# or python. I want to solve my logical to do best and brain work good. Thank's.
@EldarNecefov: Honestly, I learned Python through the official tutorial and reference guide and inline help. It was a great resource in the late 90s for someone who already knew other languages like C, Perl, ML, and Smalltalk, but I doubt that's going to be much good for you. The official website has a Getting Started page with links to all kinds of books and other resources, and there's a python-tutor mailing list which I think has a FAQ.
@EldarNecefov: I'm probably even less useful for C#. I mainly learned it from a "differences between C# and Java" webpage and Microsoft's "C# for C++/.NET programmers" docs, and never used it that much anyway.
@EldarNecefov: The only programming books I can definitely recommend aren't for either language you want: Why's Poignant Guide to Ruby is a great first book for anyone, then Learn You a Haskell for Great Good and The C Programming Language will expand your horizons in opposite directions, and after that you should be able to pick up any particular language pretty easily.
Thank you for recommendation
0

This is kind of a silly way to go about it, but:

def encode(s):
 _lastch = s[0]
 out = []
 count = 0
 for ch in s:
 if ch == _lastch:
 count +=1
 else:
 out.append(_lastch + str(count))
 _lastch = ch
 count = 1
 out.append(_lastch + str(count))
 return ''.join(out)

Example

>>> st = "aaaabbcaa"
>>> encode(st)
'a4b2c1a2'
answered Nov 19, 2014 at 21:13

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.