Home > OS >  Replacing a letter with "#" and reverse
Replacing a letter with "#" and reverse

Time:10-24

I am new to python and doing a test program that replaces all the letters in a given text with signs.

def encrypted(request):
    text = request.GET['text']
    
    text = text.replace("a", "#.")
    text = text.replace("b", "##.")
    text = text.replace("c", "###.")
    text = text.replace("d", "####.")
    text = text.replace("e", "#####.")
    text = text.replace("f", "######.")
    etc...

return render(request, 'encrypted.html', {'text': text})

I have achieved that but I have tried reversing it the same way and it does not work.

def decrypted(request):
    ftext = request.GET['text']

    ftext = ftext.replace("#.", "a")
    ftext = ftext.replace("##.", "b")
    ftext = ftext.replace("###.", "c")
    ftext = ftext.replace("####.", "d")
    ftext = ftext.replace("#####.", "e")
    etc...

    return render(request, 'decrypted.html')

So the text does not appear at all on the page.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>yCrypt</title>
</head>
<body>
TEXT DECRYPTION: {{ftext}}
</body>
</html>

I wonder why it shows no code issues whatsoever. Maybe there is a simplier way to make this possible?

CodePudding user response:

I'm not entirely following what you're trying to do here, but your first replace call in the decrypted function is going to find and replace every occurrence of "#." with the letter "a" in every "encrypted letter", not just the one for "a".

The subsequent calls to replace won't match anything because their trailing "#." has already been erroneously replaced with the letter "a".

For this to work as designed you'd have to reverse the order of your replace calls such that you're finding the longest matches first.

And for it to be rendered you also have to pass it in the context to your template renderer.

def decrypted(request):
    ftext = request.GET['text']

    etc...
    ftext = ftext.replace("#####.", "e")
    ftext = ftext.replace("####.", "d")
    ftext = ftext.replace("###.", "c")
    ftext = ftext.replace("##.", "b")
    ftext = ftext.replace("#.", "a")

    return render(request, 'decrypted.html', { "ftext": ftext }) 

CodePudding user response:

Not an expert but you can try

def decrypted(request):
    ftext = request.GET['text']

    ftext = ftext.replace("#.", "a")
    ftext = ftext.replace("##.", "b")
    ftext = ftext.replace("###.", "c")
    ftext = ftext.replace("####.", "d")
    ftext = ftext.replace("#####.", "e")
    return render(request, 'decrypted.html',{'ftext':ftext})

CodePudding user response:

The reason it is not working is that encoded of a is a sub-string of b, c, d, e, etc.

a = #.
b = ##.
c = ###.

as you can see #. is at the end of every encoded string

So when you first encode, let's say abc it becomes #.##.###. When you run the decode step you use replace("#.", "a") you get the result a#a##a where every #. is replaced by a and as you can see there are no dots left.

The solution is quite simple instead of ###. format, use .###. format

a = .#.
b = .##.
c = .###.

this will ensure only the correct number of # matches and not a substring.

So when you first encode, let's say abc it becomes .#..##..###. When you run the decode step you use replace(".#.", "a") you get the result a.##..###. as you can see codes for b and c are still there.

On a side note, you can use loops to make code much smaller.

CodePudding user response:

Having lots of similar lines of code as you have and as in some other answers, you should consider how you could approach this algorithmically.

Let's say that you're only concerned with encoding lower case ascii letters. If so, you could do this:

import string

encodemap = dict()
decodemap = dict()

for i, c in enumerate(string.ascii_lowercase, 1):
    pattern = '#' * i
    encodemap[c] = pattern   '.'
    decodemap[pattern] = c

def encode(mystring):
    return ''.join([encodemap[c] for c in mystring])

def decode(mystring):
    return ''.join([decodemap[p] for p in mystring.split('.')[:-1]])


ev = encode('helloworld')
print(ev)
dv = decode(ev)
print(dv)

If you want to encode other characters then you just need to change the constant value used in the construction of the encode & decode maps. For example, string.printable could be a good choice

  • Related