There is a simple decryption algorithm, there was no problem to compose it.

What are we doing? We read the lines and for each letter, after which there is a number we do the conversion word[0] * int(word[1:]) . That is, duplicate the letter a specified number of times.

The code is:

 import re def readfile(filename): result = [] with open (filename, "r") as file: lines = file.readlines() for line in lines: line = re.findall(r'\w\d*', line) result.append(line) return result def decrypt(lines): result = [] for line in lines: for word in line: source_line = word[0] * int(word[1:]) result.append(source_line) return result def encrypt(lines): pass def writefile(filename, lines): with open (filename, "w") as file: for line in lines: file.write(line) lines = readfile("input.txt") decrypted_lines = decrypt(lines) writefile("output.txt", decrypted_lines) 

The code works on the input data

 a2b4c3f5 c2b1m5v6 

It turns out:

 aabbbbcccfffffccbmmmmmvvvvvv 

The question is: how to implement the encryption algorithm, that is, the search for repeated letters in a row. And with this implement it as efficiently as possible?

That is, how to most effectively from, for example, such a line:

 aabbbbccceeeeeff 

Get this:

 a2b4c3e5f2 
  • one
    Do not call this approach "cryptography". - m9_psy
  • one
    Possible duplicate question: How to remove consecutive duplicates from the list? - m9_psy
  • 3
    @Kit Scribe I think m9_psy is right, because it is unlikely to be a symmetric encryption, since no key is required for encryption / decryption. - MihailPw
  • one
    Well now let's call any compression encryption: | - andreymal
  • one
    @KitScribe k will pick up very quickly, in most cases, generally from the first time - andreymal

4 answers 4

It is possible in 1 line like this:

 from itertools import groupby input_str = "aaaaccvvvvvvvbdp" groupped_str = groupby(input_str) result = "".join("".join((elem, str(len(list(grouper))))) for elem, grouper in groupped_str) print(result) >>> a4c2v7b1d1p1 

It can be a little clearer:

 result = [] for elem, grouper in groupped_str: result.append("".join((elem, str(len(list(grouper)))))) print(result) 

groupby returns duplicate elements and their number is an ideal candidate for the solution and no need to write any counters.

  • one
    Another option: rle = ''.join([c+str(len(list(same))) for c, same in groupby(text)]) - jfs

There are no special tricks here. Just follow the line on the line and pack:

 string = 'sssssssssqqqqqqqffff' currCh = string[:1] currCount = 1 result = '' for ch in string[1:]: if ch != currCh: result += (currCh + str(currCount)) currCh = ch currCount = 1 else: currCount += 1 result += (currCh + str(currCount)) print result 

Result:

 s9q7f4 
     def foo(line:str) -> str: decrypt = '' for i in line: if i not in decrypt: decrypt += f'{i}{line.count(i)}' return decrypt 

    Result :

     a2b4c3e5f2 

    Perhaps there is a simpler solution, or this code can be simplified. But the essence is clear.

    You can still like this:

     string = 'aaaaccаааааvvvvрррррvvуууууvbdp' result = "".join("".join((elem, str(string.count(elem)))) for elem in set(string)) 
       s,n = 0,input()+' ' for i in n: if n[0] != i: print(n[0],s,end='',sep='') s,n = 0,i s += 1 

      The easiest way probably so.