Playing With Passphrases in Python


The challenge

Everyone knows passphrases. One can choose passphrases from poems, songs, movies names and so on but frequently they can be guessed due to common cultural references. You can get your passphrases stronger by different means. One is the following:

choose a text in capital letters including or not digits and non alphabetic characters,

  1. shift each letter by a given number but the transformed letter must be a letter (circular shift),
  2. replace each digit by its complement to 9,
  3. keep such as non alphabetic and non digit characters,
  4. downcase each letter in odd position, upcase each letter in even position (the first character is in position 0),
  5. reverse the whole result.

Example:

your text: “BORN IN 2015!”, shift 1

1 + 2 + 3 -> “CPSO JO 7984!”

4 “CpSo jO 7984!”

5 “!4897 Oj oSpC”

https://en.wikipedia.org/wiki/Passphrase

The solution in Python code

Option 1:

def play_pass(s, n):

    # Step 1, 2, 3
    shiftText = ""
    for char in s:
        if char.isdigit():
            shiftText += str(9 - int(char))
        elif char.isalpha():
            shifted = ord(char.lower()) + n
            shiftText += chr(shifted) if shifted <= ord('z') else chr(shifted - 26)
        else:
            shiftText += char

    # Step 4
    caseText = ""
    for i in range(len(shiftText)):
        caseText += shiftText[i].upper() if i % 2 == 0 else shiftText[i].lower()

    # Step 5
    return caseText[::-1]

Option 2:

def play_pass(s, n):
    slower = s.lower()
    change = ''
    alphabet = 'abcdefghijklmnopqrstuvwxyz'

    for i,char in list(enumerate(slower)):
        if char in alphabet:
            ind = (alphabet.index(char) + n)
            if ind >= 26:
                ind = ind % 26
            if i % 2 == 0:
                change += alphabet[ind].upper()
            else:
                change += alphabet[ind].lower()
        elif char.isdigit():
            change += str(9 - int(char))
        else:
            change += char

    return change[::-1]

Option 3:

def play_pass(s, n):
    passphrase = list(s)
    for i in range(0, len(s)):
        if passphrase[i].isalpha():
            ascii = ord(passphrase[i].lower())
            passphrase[i] = chr(ascii+n-26) if ascii+n > 122 else chr(ascii+n)
            passphrase[i] = passphrase[i].lower() if i % 2 == 1 else passphrase[i].upper()
        if passphrase[i].isdigit():
            passphrase[i] = str(9 - int(passphrase[i]))
            
    return ''.join(passphrase[::-1])

Test cases to validate our solution

test.assert_equals(play_pass("I LOVE YOU!!!", 1), "!!!vPz fWpM J")

test.assert_equals(play_pass("MY GRANMA CAME FROM NY ON THE 23RD OF APRIL 2015", 2), 
    "4897 NkTrC Hq fT67 GjV Pq aP OqTh gOcE CoPcTi aO")