0

I'm trying to decode the encrypted message with the translations / replacements that I have assigned in the code. However, when I run the code, it soleley prints the encrypted text and not the expected outcome. How can I solve this? I am sorry if this an easy solution / problem, I am a beginner.

EDIT: I solved the original issue, however, now its printing the wrong output. Instead of BCDD, it prints AAAAAAAAAAAAA. I would prefer not using imports.

def main():
    encrypted = "**^^^****^^^^" #expected outcome is BCDD
    if "*" or "^" in encrypted:
        encrypted = encrypted.replace("*", "A")
        encrypted = encrypted.replace("^", "A")
    if "**" or "^^" in encrypted:
        encrypted = encrypted.replace("**", "B")
        encrypted = encrypted.replace("^^", "B")
    if "***" or "^^^" in encrypted:
        encrypted = encrypted.replace("***", "C")
        encrypted = encrypted.replace("^^^", "C")
    if "****" or "^^^^" in encrypted:
        encrypted = encrypted.replace("****", "D")
        encrypted = encrypted.replace("^^^^", "D")
    if "*****" or "^^^^^" in encrypted:
        encrypted = encrypted.replace("*****", "E")
        encrypted = encrypted.replace("^^^^^", "E")     
    print(encrypted)
main()
  • You need to save the modified string returned by `replace`, e.g. `encrypted = encrypted.replace(...)`. – sj95126 Jan 11 '22 at 02:53
  • In Python, strings are immutable - they can't be changed. So `replace` returns a new string. – 001 Jan 11 '22 at 02:53
  • 1
    Would I need to do that for every line? –  Jan 11 '22 at 02:54
  • You also have to start with the longest string to replace... – thebjorn Jan 11 '22 at 02:54
  • Like in pretty much every recent language Replace does not work in Python - same as C#, Java, JavaScript,... – Alexei Levenkov Jan 11 '22 at 02:54
  • See also: [How to test multiple variables for equality against a single value?](https://stackoverflow.com/q/15112125) Applies to `in` as well. So `if "*" or "^" in encrypted:` is always `True` but `if "*" in encrypted or "^" in encrypted:` may not be. Then again, the `if`s aren't needed at all since `replace` won't throw an error if the string isn't there. – 001 Jan 11 '22 at 02:56
  • 1
    Please don't update the question modifying the original code. It invalidates existing comments/answers. – 001 Jan 11 '22 at 03:02
  • Independently of the incorrect use of booleans, note that it is useless to check if the characters are present before replacing. This will be **less** efficient as you have to read the string twice. Also given the many replacements, you should probably use regexes. – mozway Jan 11 '22 at 03:21

5 Answers5

4

This way works:

encrypted = "**^^^****^^^^"
#expected outcome is BCDD
if "*****" in encrypted or "^^^^^" in encrypted:
    encrypted = encrypted.replace("*****", "E")
    encrypted = encrypted.replace("^^^^^", "E")
if "****" in encrypted or "^^^^" in encrypted:
    encrypted = encrypted.replace("****", "D")
    encrypted = encrypted.replace("^^^^", "D")
if "***" in encrypted or "^^^" in encrypted:
    encrypted = encrypted.replace("***", "C")
    encrypted = encrypted.replace("^^^", "C")
if "**" in encrypted or "^^" in encrypted:
    encrypted = encrypted.replace("**", "B")
    encrypted = encrypted.replace("^^", "B")
if "*" in encrypted or "^" in encrypted:
    encrypted = encrypted.replace("*", "A")
    encrypted = encrypted.replace("^", "A")
print(encrypted)

What I've changed:

  • encrypted.replace(...) -> encrypted = encrypted.replace(...). See replace.
  • Rearranged replaces in reversed order. Firstly you have to replace longer strings, if some of them are substring of next ones.
  • Replaced conditions with correct (but still useless) ones.

This version works correctly, the versions below are basically the same but in a different form.

The same solution, but without redundant ifs:

encrypted = "**^^^****^^^^"

encrypted = encrypted.replace("*****", "E")
encrypted = encrypted.replace("^^^^^", "E")
encrypted = encrypted.replace("****", "D")
encrypted = encrypted.replace("^^^^", "D")
encrypted = encrypted.replace("***", "C")
encrypted = encrypted.replace("^^^", "C")
encrypted = encrypted.replace("**", "B")
encrypted = encrypted.replace("^^", "B")
encrypted = encrypted.replace("*", "A")
encrypted = encrypted.replace("^", "A")

print(encrypted)

The same, but without lots of encrypted = encrypted.replace(...):

encrypted = "**^^^****^^^^"

replacements = {
    "*****": "E",
    "^^^^^": "E",
    "****": "D",
    "^^^^": "D",
    "***": "C",
    "^^^": "C",
    "**": "B",
    "^^": "B",
    "*": "A",
    "^": "A",
}

for r_from, r_to in replacements.items():
    encrypted = encrypted.replace(r_from, r_to)

print(encrypted)

The same, but with more convenient replacements:

encrypted = "**^^^****^^^^"

replacements = {
    **{'*' * n: chr(n + 64) for n in reversed(range(1, 6))},
    **{'^' * n: chr(n + 64) for n in reversed(range(1, 6))}
}

for r_from, r_to in replacements.items():
    encrypted = encrypted.replace(r_from, r_to)

print(encrypted)

But the best solution, as for me, uses regex :)

Yevgeniy Kosmak
  • 3,561
  • 2
  • 10
  • 26
  • 1
    Please see my [comment](https://stackoverflow.com/questions/70661089/why-are-the-characters-not-being-replaced#comment124914579_70661089). The `if`s are useless and can be removed. – 001 Jan 11 '22 at 03:09
  • @JohnnyMopp I can solve this task in dozens of different ways. But why does it matter if my answer wouldn't be understandable and helpful for OP? – Yevgeniy Kosmak Jan 11 '22 at 03:11
  • 1
    So let the OP go on thinking the `if` statements are correct and required? They are neither. – 001 Jan 11 '22 at 03:13
  • @JohnnyMopp okay, right you are, it could be better to explain that in more details. I'll add some. – Yevgeniy Kosmak Jan 11 '22 at 03:15
  • OK. You could argue that they are required in that (when they are correct) they will avoid unnecessary calls to `replace()` but the code will work correctly without them. – 001 Jan 11 '22 at 03:17
  • 1
    @JohnnyMopp updated, looks good enough? :) – Yevgeniy Kosmak Jan 11 '22 at 03:22
  • 1
    While you have some nice content, you fail to address the only important issue (the incorrect `a or b in c`). Please read the linked duplicate. – mozway Jan 11 '22 at 03:24
  • @mozway didn't even look at it. Thanks a lot! I'll fix it now. – Yevgeniy Kosmak Jan 11 '22 at 03:28
  • All of your answers helped me; as a beginner, I didn't know if the IF statements were useful, but I appreciate you walking me through it! –  Jan 11 '22 at 03:29
  • @JonolOakwood they were useless, see how [replace](https://docs.python.org/3/library/stdtypes.html#str.replace) works. Welcome to Stack Overflow :) – Yevgeniy Kosmak Jan 11 '22 at 03:35
  • @Yevgeniv please make it clear that this is the only problem with the code, All the rest is "only" optimization – mozway Jan 11 '22 at 03:35
  • @mozway in fact, @JonolOakwood changed their initial post, in first version they also had an issue with `encrypted.replace(...)` -> `encrypted = encrypted.replace(...)`. Anyway, I'll add it. – Yevgeniy Kosmak Jan 11 '22 at 03:39
  • I understand most of it now; however, I don't understand how the "but with more convenient replacements" method works. Could you explain this final thing for me? I know I'm asking for a lot so if you don't want to dont worry! Thanks again! –  Jan 11 '22 at 03:51
  • @JonolOakwood look at these links: [dictionary comprehension](https://stackoverflow.com/questions/14507591/python-dictionary-comprehension), [multiply strings](https://www.pythoncentral.io/use-python-multiply-strings/), [chr](https://docs.python.org/3/library/functions.html#chr), [dictionary unpacking](https://python-reference.readthedocs.io/en/latest/docs/operators/dict_unpack.html). Hope that would be enough :) – Yevgeniy Kosmak Jan 11 '22 at 03:57
  • That's perfect, I can't thank you enough! –  Jan 11 '22 at 04:07
1

encrypted.replace does not do an in-line replace.. it returns a replaced string..

strings are immutable in python.

so do this in every line:

encrypted = encrypted.replace(..blah..)

Bhakta Raghavan
  • 664
  • 6
  • 16
1

If the pattern is as given, then in this specific case you can do:

import re

encrypted = "**^^^****^^^^"
output = re.sub(r"\*+|\^+", lambda m: chr(len(m.group(0)) + 64), encrypted)
print(output) # BCDD

This basically finds a pattern (r"\*+|\^+"), reads the length of the substring (len(m.group(0))), and then substitutes the pattern with a character that corresponds to the length (chr(... + 64)).

j1-lee
  • 13,764
  • 3
  • 14
  • 26
1

Everyone so far seems to have missed a repeated error. Example:

if "*" or "^" in encrypted:

is parsed as:

if ("*") or ("^" in encrypted):

and so is always True (because bool("*") is True, and the in test is never even tried).

What you wanted to write instead:

if "*" in encrypted or "^" in encrypted:
Tim Peters
  • 67,464
  • 13
  • 126
  • 132
0

You must set encrypted equal to the replace function like so:

encrypted = encrypted.replace("*", "A")
  • I've done this. Please check my edit, the problem now is that I only get AAAAAAAAA as the output –  Jan 11 '22 at 02:58