0

Using Python 2.7, imagine I have two variables:

encoded_username = 'bender_in_soup_1234'
code = '000204071012'

The string in code actually specifies the position of upper case characters in encoded_username. I.e. 00 implies the first character is upper case. 02 implies the third character is upper case. 04 implies the fifth character is upper case. And so on. It can possibly go to 99 (usernames are not longer than 100 characters).

The fully decoded username is:

decoded_username = 'BeNdEr_In_SoUp_1234'

What's the most efficient way (in Python 2.7) to decode the encoded_username using the code provided?


I'm trying:

upper_case_positions = [code[i:i+2] for i in range(0,len(code),2)]
for position in upper_case_positions:
    encoded_username[position] = encoded_username[int(position)].upper()
return encoded_uname

But this simply gives me 'str' object does not support item assignment.

Moreover, I'm to parse through multiple usernames while decoding them, i.e. the code above is going to be nested inside a for loop. Having for loops within for loops makes me feel there could have been a more efficient solution. What do you folks suggest? I'm highly intrigued.

Hassan Baig
  • 15,055
  • 27
  • 102
  • 205

3 Answers3

2

How about the following:

encoded_username = 'bender_in_soup_1234'
code = '000204071012'

upper_case_positions = [int(code[i:i+2]) for i in range(0, len(code), 2)]

decoded_username = ''.join(let.upper() if pos in upper_case_positions else let 
                           for pos, let in enumerate(encoded_username))
print decoded_username

Firstly, you need to wrap your upper_case_positions as integers to ensure they are usable as positions. We enumerate the word to return each character and its relevant position, and change the case where required. Joining using an empty string gives us our output username. This prints, as expected, 'BeNdEr_In_SoUp_1234'

asongtoruin
  • 9,794
  • 3
  • 36
  • 47
1

Here you have an aproach using ord and chr:

encoded_username = 'bender_in_soup_1234'
code = '000204071012'


def upperText(s, pos):
    gap = ord("a") - ord("A")
    upper_case_positions = [int(pos[i:i + 2]) for i in xrange(0, len(pos), 2)]
    txt = map(ord, s)
    for i in upper_case_positions:
        txt[i] -= gap
    return "".join(map(chr, txt))

print upperText(encoded_username, code)
BeNdEr_In_SoUp_1234
Netwave
  • 40,134
  • 6
  • 50
  • 93
1

String are immutable Why are Python strings immutable? Best practices for using them

You can use regexp to split in chunk https://stackoverflow.com/a/25430739/123808

You can transform in list ( which is mutable) and rebuild your string once you mutation is done

import re

encoded_username = 'bender_in_soup_1234'
code = '000204071012'

encoded_username_list = list ( encoded_username )

upper_case_positions = [int(pos) for pos in re.findall('.{2}', code)]

for position in upper_case_positions:
    encoded_username_list[position] = encoded_username[position].upper()

print "".join(encoded_username_list)

BeNdEr_In_SoUp_1234

Community
  • 1
  • 1
rapdum
  • 323
  • 1
  • 2
  • 7
  • Interested in knowing how using regexp to split is better than `[int(pos[i:i + 2]) for i in xrange(0, len(pos), 2)]` – Hassan Baig Mar 16 '17 at 11:56
  • granted it's more readable, but it might actually perform slower than `[int(pos[i:i + 2]) for i in xrange(0, len(pos), 2)]` (since we need to use `re` in the former case). – Hassan Baig Mar 16 '17 at 13:29
  • @HassanBaig it was just pointing out a way to split in chunk of size two using regex. I find it a little bit more readable but less efficient. didn't read your question thoroughly,Read it till str error not the request of efficiency – rapdum Mar 16 '17 at 13:33
  • Well nevertheless, it's an interesting answer. – Hassan Baig Mar 16 '17 at 15:35