For some reason I get an error in python 2.7 when running this and entering in my 26 letter key. It says that the list index is out of range. Any help would be greatly appreciated. Thanks! (And I know I could've used a loop for the encrypter)
#-------------------------#
# Code Translator #
#-------------------------#
message = ''
messagearray = []
user = ''
encrypted = []
decrypted = []
keystring = ''
alphabet = ['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']
dataset = []
keyarray = []
def encrypter():
keystring = raw_input("Please paste key: ")
message = raw_input("Message to Encrypt: ")
for char in message:
if char == alphabet[0]:
messagearray.append(keyarray[0])
elif char == alphabet[1]:
messagearray.append(keyarray[1])
elif char == alphabet[2]:
messagearray.append(keyarray[2])
elif char == alphabet[3]:
messagearray.append(keyarray[3])
elif char == alphabet[4]:
messagearray.append(keyarray[4])
elif char == alphabet[5]:
messagearray.append(keyarray[5])
elif char == alphabet[6]:
messagearray.append(keyarray[6])
elif char == alphabet[7]:
messagearray.append(keyarray[7])
elif char == alphabet[8]:
messagearray.append(keyarray[8])
elif char == alphabet[9]:
messagearray.append(keyarray[9])
elif char == alphabet[10]:
messagearray.append(keyarray[10])
elif char == alphabet[11]:
messagearray.append(keyarray[11])
elif char == alphabet[12]:
messagearray.append(keyarray[12])
elif char == alphabet[13]:
messagearray.append(keyarray[13])
elif char == alphabet[14]:
messagearray.append(keyarray[14])
elif char == alphabet[15]:
messagearray.append(keyarray[15])
elif char == alphabet[16]:
messagearray.append(keyarray[16])
elif char == alphabet[17]:
messagearray.append(keyarray[17])
elif char == alphabet[18]:
messagearray.append(keyarray[18])
elif char == alphabet[19]:
messagearray.append(keyarray[19])
elif char == alphabet[20]:
messagearray.append(keyarray[20])
elif char == alphabet[21]:
messagearray.append(keyarray[21])
elif char == alphabet[22]:
messagearray.append(keyarray[22])
elif char == alphabet[23]:
messagearray.append(keyarray[23])
elif char == alphabet[24]:
messagearray.append(keyarray[24])
elif char == alphabet[25]:
messagearray.append(keyarray[25])
print ''.join(messagearray)
def decrypter():
keystring = raw_input("Please paste key: ")
message = raw_input("Message to Decrypt: ")
def outputM():
print decrypted
def userChoice():
user = raw_input("Encrypt or Decrypt?")
if user.upper() == "ENCRYPT":
encrypter()
elif user.upper() == "DECRYPT":
decrypter()
else:
print "Please enter a valid command."
userChoice()
for char in keystring:
keyarray.append(char)
userChoice()
Here's the full traceback I get:
Traceback (most recent call last):
File "translate.py", line 102, in <module>
userChoice()
File "translate.py", line 92, in userChoice
encrypter()
File "translate.py", line 43, in encrypter
messagearray.append(keyarray[11])
IndexError: list index out of range
The problem is here:
for char in keystring:
keyarray.append(char)
keystring is empty so also keyarray will remain empty. In order not to have IndexError you would need a keystring as much longer as the alphabet (since basically you are just substituting chars)
The problem is that in:
def decrypter():
keystring = raw_input("Please paste key: ")
message = raw_input("Message to Decrypt: ")
you are assigning the values to local variables, so the global ones remain empty. If you want to modify the global variables you have to state so:
def decrypter():
global keystring, message
keystring = raw_input("Please paste key: ")
message = raw_input("Message to Decrypt: ")
the same is true for encrypter.
Also, you cannot create keyarray before having taken some input!
There are also many other issues with the code. You cannot possibly think that doing all the manual indexing is the best way to proceed. What if you want to support a 128 character alphabet?
Use loops:
for char in message:
for i, c in enumerate(alphabet):
if char == c:
messagearray.append(keyarray[i])
(Instead of all those repeating lines).
Moreover strings already provide a method to do exactly what you are trying to do. It's called translate.
You could simply do:
import string
table = str.maketrans(string.ascii_lowercase, keystring)
And then use:
decrypted_text = some_encrypted_text.translate(table)
example run:
In [1]: import string
...: alphabet = string.ascii_lowercase
...: table = str.maketrans(alphabet, alphabet[3:]+alphabet[:3])
...:
In [2]: 'hello'.translate(table)
Out[2]: 'khoor'
The above is for python3+. In python2.7 you have to use string.maketrans instead of str.maketrans. So you'd have to do:
In [1]: import string
...: alphabet = string.ascii_lowercase
...: table = string.maketrans(alphabet, alphabet[3:]+alphabet[:3])
...:
In [2]: 'hello'.translate(table)
Out[2]: 'khoor'
Related
I am making a language in python called PythonScript, which is a JavaScript and Python (not Python 3) mix.
I am adding variables, but when I do the following code I don't get the expected result.
var scuffles = hi!
I have tried to debug it, and as you will see in my code I made a debugging array, which I found to be empty. I looked up some tutorials, but none were covering what I am trying to do.
This is a portion of the file:
import os
import sys
programDebugingArray1 = []
functions = ["Console"]
functionCodes = [["out \"TEST\""]]
programVariables = {}
def lex(cm,stri,nums,toWake):
i = 0
if cm == "":
console()
elif cm == "var" or cm == "=":
pass
elif cm == "--vars":
print(programVariables)
elif cm == "--debugManual1":
print(programDebugingArray1)
else:
print("\""+cm+"\" was not recognized as a PythonScript command.")
console()
def console():
commandToRun = ""
tok = ""
string = ""
varValue = ""
newVarName = ""
Strings = []
Numbers = []
functionToCall = ""
state = 0
command = input()
for char in command:
tok += char
if state == 1:
string += char
elif state == 2:
if char == " ":
char = ""
newVarName += char
elif state == 3:
varValue += char
if (tok == "\"" or tok == "'") or (char == "\"" or char == "'"):
if state == 0:
state = 1
elif state == 1:
state = 0
string = string[0:len(string) - 1]
Strings.append(string)
string = ""
tok = ""
char = ""
elif tok == " ":
tok = ""
elif tok == "var" and state == 0:
state = 2
tok = ""
elif tok == "=" and state == 2:
state = 3
tok = ""
elif tok == "!" and state == 3:
programDebugingArray1.append(newVarName)
programDebugingArray1.append(varValue)
state == 0
programVariables[newVarName] = varValue
tok = ""
elif tok == "--vars" and state == 0:
commandToRun == "--vars"
tok = ""
elif tok == "--debugManual1" and state == 0:
commandToRun == "--debugManual1"
tok = ""
if commandToRun == "":
commandToRun = command
lex(commandToRun,Strings,Numbers,functionToCall)
console()
I expected the debug array to at least have something in it, but for some reason it and the variables dictionary is empty. There are no error messages or boots out of the console.
I don't know what to add. At the time that's why I only posted the code.
But the intended result is that a string should be parsed (and successfully printed).
I don't remember what the issue was, but by the sounds of it, it probably just didn't print.
(I'm doing this to get back on S.O.'s "good side".)
class Lex:
def run(args, string):
if args == "print":
print(str(string))
class Calin:
string = ""
running = ""
def parse(args):
lexic = Lex
string = ""
tok = ""
state = 0
for char in args:
tok += char
if tok == " ":
if state == 0:
tok = ""
elif state == 1:
tok = " "
elif tok == "\"":
if state == 0:
state = 1
elif state == 1:
state = 0
elif state == 1:
string += char
elif tok == "print":
running = "print"
lexic.run(running, string)
trans = Calin
trans.parse("print \"WOW A STRING\"")
Because you are making state == 1 only when tok == "\"", which never happens (You are keep adding strs to it.). Changing it to char works:
class Lex:
def run(args, string):
if args == "print":
print(str(string))
class Calin:
string = ""
running = ""
def parse(args):
lexic = Lex
string = ""
tok = ""
state = 0
for char in args:
tok += char
if tok == " ":
if state == 0:
tok = ""
elif state == 1:
tok = " "
elif char == "\"": # <<< Change this
if state == 0:
state = 1
elif state == 1:
state = 0
elif state == 1:
string += char
elif tok == "print":
running = "print"
lexic.run(running, string)
trans = Calin
trans.parse("print \"WOW A STRING\"")
# WOW A STRING
I am trying to make my own basic programming language. I have the following code in my smrlang.py file
from sys import *
tokens = []
def open_file(filename):
data = open(filename, "r").read()
return data
def smr(filecontents):
tok = ""
state = 0
string = ""
filecontents = list(filecontents)
for char in filecontents:
tok += char
if tok == " ":
if state == 0:
tok = ""
else:
tok = " "
elif tok == "PRINT":
tokens.append("PRINT")
tok = ""
elif tok == "\"":
if state == 0:
state = 1
elif state == 1:
print("STRING")
string = ""
state = 0
elif state == 1:
string += tok
print(tokens)
def run():
data = open_file(argv[1])
smr(data)
run()
And I have this in my one.smr file:
PRINT "HELLO WORLD"
The output should be something like PRINT STRING, but when I use the command python3 smrlang.py one.smr, the output is just PRINT. I am using Python 3
Debugging it in the head, I found the problem:
elif state == 1:
string += tok
You don't reset the token here. It will be aababcabcd instead of abcd and recognizing \ won't work (as it will be aababcabcd\).
This also causes the token to just be everything and it will never print.
Try changing it to:
elif state == 1:
string += tok
tok = ""
Output after fix:
> py -3 temp.py temp.txt
STRING
['PRINT']
I am trying to import a text file and encrypt/decrypt by two key words. I set a key variable but can't find the correct place to locate it.
Here is where it currently is:
def importFile():
importText = []
file = input('What is the text file name: ')
fileName = open(file,'r')
text = fileName.read()
fileName.close()
fileName = text
message = text
#print (text)
delete = open(file,'w')
delete.write('')
key = input ('What key do you wnat to use: ')
Here is where the key is called:
def translatedMessage(mode):
translated = []
keyIndex = 0
key = key.upper()
for symbol in message:
num =LETTERS .find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS .find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS .find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
If you need it here is it all together:
LETTERS = 'ZABCDEFGHIJKLMNOPQRSTUVWXY'
def main():
myMode = input("Encrypt 'e' or Decrypt 'd': ")
if myMode == 'encrypt' or myMode == 'e':
translated = encryptFile()
elif myMode == 'decrypt' or myMode == 'd':
translated = decryptFile()
def importFile():
importText = []
file = input('What is the text file name: ')
fileName = open(file,'r')
text = fileName.read()
fileName.close()
fileName = text
message = text
#print (text)
delete = open(file,'w')
delete.write('')
key = input ('What key do you wnat to use: ')
def encryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
importFile()
return translatedMessage('encrypt')
def decryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
importFile()
return translatedMessage('decrypt')
def translatedMessage(mode):
translated = []
keyIndex = 0
key = key.upper()
for symbol in message:
num =LETTERS .find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS .find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS .find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
I'm pretty new to coding and know this is pretty simple so any advice is greatly appreciated:)
The problem in your code is that you are treating key like a global variable, but it is a local one, so you need to pass it between your functions:
LETTERS = 'ZABCDEFGHIJKLMNOPQRSTUVWXY'
def main():
myMode = input("Encrypt 'e' or Decrypt 'd': ")
if myMode == 'encrypt' or myMode == 'e':
translated = encryptFile()
elif myMode == 'decrypt' or myMode == 'd':
translated = decryptFile()
def importFile():
importText = []
file = input('What is the text file name: ')
fileName = open(file,'r')
text = fileName.read()
fileName.close()
fileName = text
message = text
#print (text)
delete = open(file,'w')
delete.write('')
return input ('What key do you wnat to use: ') # Return the key
def encryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
key = importFile() # Get the key returned by the function
return translatedMessage('encrypt', key) # Pass the key to the function
def decryptFile():
textFile = input("Would you like to import a text file 'Y' or 'N': ")
if textFile.lower() == 'y' :
key = importFile() # Get the key returned by the function
return translatedMessage('decrypt', key) # Pass the key to the function
def translatedMessage(mode, key): # `key` is an argument
translated = []
keyIndex = 0
key = key.upper()
for symbol in message:
num =LETTERS .find(symbol.upper())
if num != -1:
if mode == 'encrypt':
num += LETTERS .find(key[keyIndex])
elif mode == 'decrypt':
num -= LETTERS .find(key[keyIndex])
num %= len(LETTERS)
if symbol.isupper():
translated.append(LETTERS[num])
elif symbol.islower():
translated.append(LETTERS[num].lower())
keyIndex += 1
if keyIndex == len(key):
keyIndex = 0
else:
translated.append(symbol)
return ''.join(translated)
if __name__ == '__main__':
main()
A simpler solution would be to define key as a global variable by adding the line global key to the importFile() function. In general however, I think using the global keyword in Python is discouraged.
This explanation of global vs. local variables in Python might be helpful: http://www.python-course.eu/global_vs_local_variables.php
I'm very new to python so bear with me. I'm putting together a little crypto puzzle and part of it requires a substitution cipher. In this case each letter is replaced with three random letters. Every time I run this code it throws an error when I try to encrypt something:
Traceback (most recent call last):
File "/home/pi/Desktop/expansion cipher.py", line 159, in <module>
crypt()
File "/home/pi/Desktop/expansion cipher.py", line 142, in crypt
print encrypt(txt)
File "/home/pi/Desktop/expansion cipher.py", line 127, in encrypt
ctxt = ctxt + exp_ciph(ptxt[counter])
File "/home/pi/Desktop/expansion cipher.py", line 121, in exp_ciph
return cur_exp
UnboundLocalError: local variable 'cur_exp' referenced before assignment
Here is my code:
def rev_ciph(char):
if char == "gps":
cur_rev = "_"
if char == "evl":
cur_rev = "."
if char == "jkb":
cur_rev = "e"
if char == "bhj":
cur_rev = "t"
if char == "szk":
cur_rev = "a"
if char == "nwu":
cur_rev = "o"
if char == "dpl":
cur_rev = "i"
if char == "sbg":
cur_rev = "n"
if char == "dsl":
cur_rev = "s"
if char == "yhq":
cur_rev = "p"
if char == "sav":
cur_rev = "h"
if char == "gfs":
cur_rev = ","
if char == "rtg":
cur_rev = "d"
if char == "fqu":
cur_rev = "l"
if char == "rjt":
cur_rev = "u"
if char == "sbv":
cur_rev = "c"
if char == "yqm":
cur_rev = "m"
if char == "ywh":
cur_rev = "f"
if char == "drt":
cur_rev = "y"
if char == "zfd":
cur_rev = "w"
if char == "asn":
cur_rev = "g"
if char == "fzj":
cur_rev = "p"
if char == "rka":
cur_rev = "b"
if char == "kzv":
cur_rev = "v"
if char == "lah":
cur_rev = "k"
if char == "rma":
cur_rev = "x"
if char == "fqn":
cur_rev = "q"
if char == "vrq":
cur_rev = "j"
if char == "tfv":
cur_rev = "z"
return cur_rev
def exp_ciph(char):
if char == "_":
cur_exp = "gps"
if char == ".":
cur_exp = "evl"
if char == "e":
cur_exp = "jkb"
if char == "t":
cur_exp = "bhj"
if char == "a":
cur_exp = "szk"
if char == "o":
cur_exp = "nwu"
if char == "i":
cur_exp = "dpl"
if char == "n":
cur_exp = "sbg"
if char == "s":
cur_exp = "dsl"
if char == "p":
cur_exp = "yhq"
if char == "h":
cur_exp = "sav"
if char == ",":
cur_exp = "gfs"
if char == "d":
cur_exp = "rtg"
if char == "l":
cur_exp = "fqu"
if char == "u":
cur_exp = "rjt"
if char == "c":
cur_exp = "sbv"
if char == "m":
cur_exp = "yqm"
if char == "f":
cur_exp = "ywh"
if char == "y":
cur_exp = "drt"
if char == "w":
cur_exp = "zfd"
if char == "g":
cur_exp = "asn"
if char == "p":
cur_exp = "fzj"
if char == "b":
cur_exp = "rka"
if char == "v":
cur_exp = "kzv"
if char == "k":
cur_exp = "lah"
if char == "x":
cur_exp = "rma"
if char == "q":
cur_exp = "fqn"
if char == "j":
cur_exp = "vrq"
if char == "z":
cur_exp = "tfv"
return cur_exp
def encrypt(ptxt):
ctxt = "Ciphertext: "
counter = 0
while counter <= len(ptxt):
ctxt = ctxt + exp_ciph(ptxt[counter])
counter += 1
return ctxt
def decrypt(ctxt):
ptxt = "Plaintext: "
counter = 0
while counter <= len(ctxt):
ptxt = ptxt + rev_ciph(ctxt[counter])
counter += 1
return ptxt
def crypt():
print
txt = raw_input("Plaintext: ")
print encrypt(txt)
print
def ucrypt():
print
txt = raw_input("Ciphertext: ")
print decrypt(txt)
print
ex_code = False
while ex_code == False:
print "(1) Encrypt"
print "(2) Decript"
print "(3) Exit"
print
mchoc = raw_input("What would you like to do(1,2,3?): ")
if mchoc == "1":
crypt()
if mchoc == "2":
ucrypt()
if mchoc == "3":
ex_code = True
print
You have two problems. The first is that you aren't handling all possible inputs. Having just copied and tested you code, I see that you get UnboundLocalError: local variable 'cur_exp' referenced before assignment if and only if you try to encrypt something that includes a character that isn't handled by exp_ciph(char) (or rev_ciph(char) for that matter). Neither of these functions handles capital letters, for instance. Python is ALWAYS case sensitive, and regards capital and lower case letters as entirely different characters. Your functions also don't handle other characters, such as "," and ";". If you give the program a string to encrypt that includes a character not handled by your first two functions, then, when that character comes up, all of the conditions for the if statements in these functions are false, and thus cur_exp is never created and assigned a value. When one of these functions then tries to return cur_exp, it finds that cur_exp doesn't exist. That is the source of the error you describe above.
If you input a string consisting ONLY of lower case letters and possibly "_", the you get an entirely different error, namely:
IndexError: string index out of range
This is because the function encrypt(ptxt) always goes looking for one more character than a string has. In Python (and, I think, every programming language) the elements in an iterable such as a string or a list are indexed by their OFFSET from the first item; that is, how many items are in front of it. So, if you have a string foo with 4 charachters:
foo = "abcd"
then:
foo[0] == "a"
foo[1] == "b"
foo[2] == "c"
foo[3] == "d"
There is no foo[4]. Calling foo[4] will raise exactly the above error. The len(object) function returns the number of items in an iterable. So, keeping with the above example,
len(foo) == 4
and thus calling
foo[len(foo)]
will raise IndexError:. This is EXACTLY what always happens in your encrypt(ptxt) function here
counter = 0
while counter <= len(ptxt):
ctxt = ctxt + exp_ciph(ptxt[counter])
counter += 1
You will want to do this instead:
counter = 0
while counter <= len(ptxt) - 1:
ctxt = ctxt + exp_ciph(ptxt[counter])
counter += 1
Those are the first two problem I encounter running this. I won't guarantee there are no more. Hopefully this gets you farther down the path though.