Skip to content

Instantly share code, notes, and snippets.

@Goorzhel
Last active November 11, 2021 18:37
Show Gist options
  • Save Goorzhel/af5154de418d7943adb798a434b760e5 to your computer and use it in GitHub Desktop.
Save Goorzhel/af5154de418d7943adb798a434b760e5 to your computer and use it in GitHub Desktop.
Demilich cipher codec.
#!/usr/bin/env python3
"""
The Finnish death metal band Demilich released an album in 1993 called
"Nespithe". The liner notes, as well as the album title and one song title,
are written in code: start at the end of the phrase, group the letters in
three, and reverse the groups' order.
"""
from sys import argv, stdin
def encode(string):
string = string.replace(" ","")
newstr = ""
for i in range(0,len(string),3):
newstr = string[i:i+3] + newstr
return newstr.upper()
def decode(string):
string = string.replace(" ","")
newstr = ""
for i in range(len(string),2,-3):
newstr += string[i-3:i]
newstr += string[0:i%3]
return newstr.upper()
def test():
plain = "THESPINE"
cipher = "NESPITHE"
assert encode(plain) == cipher
assert decode(cipher) == plain
OPS = {"-d": decode, "-e": encode}
def main():
if len(argv) < 2 or argv[1] not in OPS:
raise RuntimeError(f"Argument must be one of: {', '.join(OPS.keys())}")
oper = OPS[argv[1]]
for line in stdin:
line = line.rstrip().replace(" ", "")
print(oper(line), end="")
if __name__ == "__main__":
main()
@AnttiBoman
Copy link

Nice! Could you specify the interpreter on the first line, at least for us Linux geeks?
#!/usr/bin/env python3

@Goorzhel
Copy link
Author

Goorzhel commented Oct 4, 2016

Damn, how'd I forget that, especially having written this on a Linux machine?

Kiitos, it's fixed now.

@Goorzhel
Copy link
Author

Goorzhel commented Sep 2, 2021

Came back to make this behave more like a Unix text filter, and also attempt some genexpr nonsense—

def encode_stupid(string):
    length = len(string)
    start = length - length % 3
    return "".join(string[i : min(i + 3, length)] for i in range(start, -1, -3)).upper()

def decode_stupid(string):
    length = len(string)
    return "".join(string[max(0, i - 3) : i] for i in range(length, -1, -3)).upper()

—that is, until I saw no difference with hyperfine and a worse result with timeit.

>>> timeit.timeit(lambda: decode_stupid("nespithe"))
2.2625253699952736
>>> timeit.timeit(lambda: decode("nespithe"))
1.0990409349906258

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment