solution_016.py

#! /usr/bin/python3
# ===================================================================
# Encrypt/Decrypt messages using a shift cipher (a Caesar cipher)
# -------------------------------------------------------------------
# notice how much code is devoted to reading and verifying the
# user's input.
# ===================================================================

import sys 
import random
import user_interface as ui

abc = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
       'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
       'U', 'V', 'W', 'X', 'Y', 'Z', '.', '?', '!', '(',
       '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
       ')']


# -------------------------------------------------------------------
# ---- turn a list into a string
# -------------------------------------------------------------------

def listToString(l):
    return (''.join(l))


# -------------------------------------------------------------------
# ---- create an encrypt/decrypt dictionary
# -------------------------------------------------------------------

def createEncryptDecryptDictionary(shift,ed):

    dct = {}

    for i in range(len(abc)):

        x = i + shift          # list index + shift count

        xx = x % len(abc)      # make sure the shifted index does not
                               # exceed the length of the list 
        if ed == 'E':
            dct[abc[i]] = abc[xx]
        else:
            dct[abc[xx]] = abc[i]

    return dct


# -------------------------------------------------------------------
# ---- check if a key is in a dictionary
# -------------------------------------------------------------------

def checkKey(dict,key):
      
    if key in dict.keys():
       return True
    return False


# ------------------------------------------------------------------
# ---- main
# ------------------------------------------------------------------

while(True):

    # --------------------------------------------------------------
    # ---- get the user's input
    # --------------------------------------------------------------

    ui.clear_screen()

    # ---- ask the user for a shift count

    while(True):

        print()
        s = ui.get_user_input('Enter a shift count: ')

        if not s:               # empty string?
           print()
           sys.exit()

        tf,shift = ui.is_int(s)  # user's input an integer?

        if not tf:
            print()
            print('input was not an integer, try again')
            continue

        shift = shift % len(abc)

        if shift == 0:
            print()
            print('shift count is 0, try again')
            continue

        break
    
    # ---- ask the user decrypt or encrypt?

    while(True):

        print()
        s = ui.get_user_input('Encrypt or Decrypt [e,d]: ')

        if not s:               # empty string?
           print()
           sys.exit()

        if s[0] == 'E' or s[0] == 'e':
            ed = 'E'
            break

        if s[0] == 'D' or s[0] == 'd':
            ed = 'D'
            break

        print()
        print(f'Illegal selection ({s}) entered - try again')

    # ---- ask the user to enter a text string

    while(True):

        print()
        txt = ui.get_user_input('Enter text string: ')


        if not txt:           # empty string?
           print()
           sys.exit()

        break

    # ---- display runtime

    print()
    print(f'shift count {shift}')
    if ed == 'E':
        print(f'encrypt text string')
    else:
        print(f'decrypt text string')


    # ---------------------------------------------------------------
    # encrypt/decrypt the text string
    # ---------------------------------------------------------------


    # ---- create an encrypt/decrypt dictionary

    dct = createEncryptDecryptDictionary(shift,ed)


    # ---- uppercase the text string and convert it to a list
    # ---- so it can be modified

    lst = list(txt.upper())


    # ---- encrypt/decrypt the list's characters
    # ---- test if a character is in the encrypt/decrypt
    # ---- dictionary. if yes change it otherwise leave it alone

    for i in range(len(lst)):
        if checkKey(dct,lst[i]):
            lst[i] = dct[lst[i]]


    # ---- turn the list into a string

    s = ''.join([str(x) for x in lst])


    # ---- tell the world

    if ed == 'E':
        print(f'encrypted text is:\n{s}')
    else:
        print(f'decrypted text is:\n{s}')

    ui.pause()