Today I made a .py file that decrypts strings encrypted with a vigenere square. I have gotten this far but I cant seem to add spaces to the ciphr list and encr_txt because it garbles the decrypted message. Instead of "message is, hello my name is slim shady", you get "message is, hellprvmwhwebwrw k d thady", where as if i leave spaces out of encr_txt and the ciphr list I get a fine message. I do not know how to fix this there are no errors either, I just started coding in python a couple days ago so if its obvious i'm sorry. Also I know this could be done way easier but im learning lists so i chose to make it this way instead of something like this:
Another question i found relating my problem but does not describe my situation
Code :
# -*- coding: utf-8 -*-
# ^ encoding
# Encrypted text
# encr_txt = 'tkedobaxoudqrrffhhhalbmmcnedeo'
encr_txt = 'qexpg vy zeen ie wdrm elsmy'
#encr_list = list(encr_txt)
txtpos = 0
# Key to ^
key = 'james'
keypos = 0
limit = len(encr_txt)
limitpos = 0
# Vigenere square
ciphr = ['abcdefghijklmnopqrstuvwxyz ',
'bcdefghijklmnopqrstuvwxyz a',
'cdefghijklmnopqrstuvwxyz ab',
'defghijklmnopqrstuvwxyz abc',
'efghijklmnopqrstuvwxyz abcd',
'fghijklmnopqrstuvwxyz abcde',
'ghijklmnopqrstuvwxyz abcdef',
'hijklmnopqrstuvwxyz abcdefg',
'ijklmnopqrstuvwxyz abcdefgh',
'jklmnopqrstuvwxyz abcdefghi',
'klmnopqrstuvwxyz abcdefghij',
'lmnopqrstuvwxyz abcdefghijk',
'mnopqrstuvwxyz abcdefghijkl',
'nopqrstuvwxyz abcdefghijklm',
'opqrstuvwxyz abcdefghijklmn',
'pqrstuvwxyz abcdefghijklmno',
'qrstuvwxyz abcdefghijklmnop',
'rstuvwxyz abcdefghijklmnopq',
'stuvwxyz abcdefghijklmnopqr',
'tuvwxyz abcdefghijklmnopqrs',
'uvwxyz abcdefghijklmnopqrst',
'vwxyz abcdefghijklmnopqrstu',
'wxyz abcdefghijklmnopqrtsuv',
'xyz abcdefghijklmnopqrtsuvw',
'yz abcdefghijklmnopqrtsuvwx',
'z abcdefghijklmnopqrtsuvwxy',
'abcdefghijklmnopqrtsuvwxyz ']
first = ciphr[0]
string = ''
def start():
global limitpos
limitpos += 1
global keypos
for i in ciphr:
if keypos == len(key):
keypos = 0
else:
pass
if i[0] == key[keypos]:
#print "%s, %s" % (i[0], i)
global currenti
currenti = i
#print currenti
finder()
break
else:
pass
def finder():
global keypos
global txtpos
done = False
position = 0
while done == False:
for i in currenti[position]:
if i == '_':
pass
if i == encr_txt[txtpos]:
global string
string = string + first[position]
#print "message is, %s" % string
keypos += 1
txtpos += 1
done = True
if limitpos == limit:
print "message is, %s" % string
break
else:
start()
else:
position += 1
pass
start()
Adding spaces to the table changes the way the cipher works. You can't expect to make that kind of change and not affect the way messages are encrypted and decrypted!
As an aside, the last row of your table is incorrect. It's identical to the first row, but it should have the space in the first position.
Related
This program essentially encodes and decodes a message and code respectively. I only did the decoding part so far. However I keep getting an EOF error even though I made sure to end parentheses, checked my syntax and kept tampering with it. Unfortunately no luck. Anyone know why this error keeps popping up? I would greatly appreciate it. Also I copied both files that i'm using.
from LetterCodeLogic import LCL
def main():
print("Welcome to the LetterCode program")
choice = getChoice()
while choice !=0:
if choice == 1:
#Encode logic...
print()
elif choice == 2:
#Decode logic...
msg = input("Enter your numbers to decode (separate with commas): ")
#send msg to Decode function in LCL class (LetterCodeLogic.py file)
result = LCL.Decode(msg)
print("Your decoded message is: \n" + result)
else:
print("Unknown process...")
print()
choice = getChoice()
print("Thanks for using the Letter Code program")
def getChoice():
c = int(input("Choice? (1=Encode, 2=Decode, 0=Quit): "))
return c
if __name__ == "__main__":
main()
class LCL:
"""Encode/Decode Functions"""
#staticmethod
def Decode(msg):
#separate numbers from msg string (e.g., "1,2,3")
nums = msg.split(",") #produces list of separate items
result = ""
for x in nums:
try:
n = int(x.strip()) #remove leading/trailing spaces...
if n == 0:
c = " "
elif n < 0 or n > 26:
c = "?"
else:
#ASCII scheme has A=65, B=66, etc.
c = chr(n+64)
except ValueError:
c = "?"
result += c #same as: result = result + c
return result
#staticmethod
def Encode(msg):
the "#staticmethod" and "def Encode()" function was empty and that was the end of line parsing error. When I was coding this and ran it, it ran with no problems. So I removed it for the time being.
Key = int(input('How much would you like to shift your code by?'))
message = input('Write the message that you would like to encrypt.')
def cipherText(message):
for letter in message:
intValue = ord(letter)
convInt = intValue + Key
print(chr(convInt))
print("Here is your ciphertext:")
S2 = str(cipherText(message))
def plainText():
for letter in S2:
intValue = ord(letter)
convInt = intValue - Key
print(chr(convInt))
print('The following is your decrypted message')
plainText()
What is wrong with this code? It prints out klkb. Why is that?
First you do this:
S2 = str(cipherText(message))
Then:
for letter in S2:
But since cipherText doesn't return anything, it returns the default None.
And since you force that result into a string, it is 'None' - that's what then gets mangled in your plainText() function.
This is a good example of why you should avoid type casting if you can. Also, you're using global variables to pass data around, where you could just pass in what you want as parameters to the function.
Finally, you don't follow Python naming conventions, which makes the code harder to read for someone familiar with regular Python. Key looks like a class (it should be key) and cipherText should be cipher_text. Some libraries deviate from this for documentation reasons across multiple platforms and languages, but when writing your own Python, you should try to follow normal naming conventions.
Your code with all those issues fixed:
a_key = int(input('How much would you like to shift your code by?'))
a_message = input('Write the message that you would like to encrypt.')
def cipher_text(message, key):
result = ''
for letter in message:
int_value = ord(letter)
conv_int = int_value + key
result += chr(conv_int)
return result
garbled_message = cipher_text(a_message, a_key)
print("Here is your cipher text: ", garbled_message)
def plain_text(garbled_message, key):
result = ''
for letter in garbled_message:
int_value = ord(letter)
conv_int = int_value - key
result += chr(conv_int )
return result
message2 = plain_text(garbled_message, a_key)
print('The following is your decrypted message: ', message2)
Of course, having two functions that do the same thing, with extra steps, is not ideal either. Here's a shorter version:
a_key = int(input('How much would you like to shift your code by?'))
a_message = input('Write the message that you would like to encrypt.')
def cipher_text(message, key, decrypt=False):
if decrypt:
key = -key
return ''.join([chr(ord(ch) + key) for ch in message])
garbled_message = cipher_text(a_message, a_key)
print(f'Here is your cipher text: {garbled_message}')
decrypted_message = cipher_text(garbled_message, a_key, decrypt=True)
print(f'The following is your decrypted message: ', decrypted_message)
I'm currently writing a test function for class to test provided cases on provided solution code. However I'm running into an issue where a print statement is executing when I don't want it to.
This is the provided solution that I'm testing:
def alphapinDecode(tone):
phone_num = ''
if checkTone(tone): #or checkTone2
while len(tone) > 0:
# retrieve the first tone
next_tone = tone[0:2]
tone = tone[2:]
# find its position
cons = next_tone[0]
vow = next_tone[1]
num1 = consonants.find(cons)
num2 = vowels.find(vow)
# reconstruct this part of the number -
# multiply (was divided) and add back
# the remainder from the encryption division.
phone = (num1 * 5) + num2
# recreate the number
# by treating it as a string
phone = str(phone)
# if single digit, not leading digit, add 0
if len(phone) == 1 and phone_num != '':
phone = '0' + phone
phone_num = phone_num + phone
# but return in original format
phone_num = int(phone_num)
else:
print('Tone is not in correct format.')
phone_num = -1
return phone_num
Here's the (partially done) code for the test function I have written:
def test_decode(f):
testCases = (
('lo', 43),
('hi', 27),
('bomelela', 3464140),
('bomeluco', 3464408),
('', -1),
('abcd', -1),
('diju', 1234),
)
for i in range(len(testCases)):
if f(testCases[i][0]) == testCases[i][1] and testCases[i][1] == -1:
print('Checking '+ f.__name__ + '(' + testCases[i][0] + ')...Tone is not in correct format.')
print('Its value -1 is correct!')
return None
When executing test_decode(alphapinDecode), I get this:
Tone is not in correct format.
Checking alphapinDecode()...Tone is not in correct format.
Its value -1 is correct!
Tone is not in correct format.
Checking alphapinDecode(abcd)...Tone is not in correct format.
Its value -1 is correct!
As you can see, because of the print statement in alphapinDecode(I think), it is printing an extra "Tone is not in correct format." above the print statement I have written.
How would I prevent this print statement from executing, and why is it printing if the print statement I wrote in my test function doesn't ask for the result of alphapinDecode?
We are not allowed to alter the code of the given solution.
I'm fairly new to stackOverflow, so sorry for any formatting issues. Thank you!
Edit: Fixed the idents of the test_decode function
One easy solution would be to pass an extra parameter say, a boolean variable debug to the function. That would go something like this.
def func1(var1, debug):
if debug:
print("Printing from func1")
# Do additional stuff
Now when you call it. You now have the option of setting the debug variable.
func1("hello", debug=True) # will print the statement
func1("hello", debug=False) # will not print statement.
If you cannot modify the called function. Then you can follow this method. explained by #FakeRainBrigand here.
import sys, os
# Disable
def blockPrint():
sys.stdout = open(os.devnull, 'w')
# Restore
def enablePrint():
sys.stdout = sys.__stdout__
print 'This will print'
blockPrint()
print "This won't"
enablePrint()
print "This will too"
So I'm in the middle of making a simple Caesar cipher for practice and I can't get it to decipher entire strings, just individual letters.
symbol_add is the function in question.
Here's the code:
import re
alphabet = "abcdefghijklmnopqrstuvwxyz"
def cleanIt(clean):
global alphabet
s = re.sub('[^a-z]+', '?', str(clean))
return s
def symbol_add(symbol, key):
encryptedMsg = ""
for x in symbol:
position = alphabet.find(x)
newPosition = (position + key) % 26
newLetter = alphabet[nyPosisjon]
encryptedMsg += nyBokstav
return encryptedMsg
def cipher(data,key):
text = ""
if data in alphabet:
text += symbol_add(symbol=data,key=key)
return text
def main():
try:
msg = (input("Write the message you would like to encrypt\n"))
key = int(input("which key would you like to use?\n"))
cleanIt(clean=msg)
print(cipher(data=msg, key=key))
except ValueError:
print("Write a number!")
main()
I'm sure the solution is pretty simple, still learning.
Any help in how to solve this will be greatly appreciated!
import re
alphabet = "abcdefghijklmnopqrstuvwxyz"
def cleanIt(clean):
global alphabet
s = re.sub('[^a-z]+', '?', str(clean))
return s
def symbol_add(symbol, key):
position = alphabet.find(symbol)
newPosition = (position + key) % 26
newLetter = alphabet[newPosition]
return newLetter
def cipher(data,key):
text = ""
for letter in data:
if letter in alphabet:
text += symbol_add(symbol=letter,key=key)
return text
def main():
try:
msg = (input("Write the message you would like to encrypt\n"))
key = int(input("which key would you like to use?\n"))
# Note: you need to assign msg to be equal to cleanIt(clean=msg).
# Just calling cleanIt(clean=msg) won't work, as strings
# are immutable in Python
msg = cleanIt(clean=msg)
print(cipher(data=msg, key=key))
except ValueError:
print("Write a number!")
main()
The main changes are:
The for loop was moved from symbol_add to cipher, so that symbol_add gets called for each character
In main(): cleanIt(clean=msg) -> msg = cleanIt(clean=msg); the reason for this is that strings are immutable in Python, meaning that you need to reassign the variable msg to essentially point to the new string.
Output of this code:
Write the message you would like to encrypt
test
which key would you like to use?
1
uftu
Also, try to stick to a single naming convention; you have a function that follows camelCase (cleanIt) and another that follows snake_case (symbol_add). Try and name all functions in the same way. (The convention in Python is to use snake_case for functions)
You can streamline your cipher method quite a bit if you fill a dictionary as lookup when entering the method. It contains the mapping based on the key provided and maps your input characters to to the cipher-character.
Its much faster to look up in a dict then to .index() into a string.
Using dict.get(key[,default]) allows to provide the '?' for unknowns so you need no import re and no preprocessing.
Read about dict.get(): Why dict.get(key) instead of dict[key]?
Adding uppercase mapping to the chiffre is trivial as well based on the lower case ones:
alphabet = "abcdefghijklmnopqrstuvwxyz"
def cipher(data, key):
# in case you change alphabet
la = len(alphabet)
# get the default lookup
chiffre = { c:alphabet[(i+key)%la] for i,c in enumerate(alphabet) }
# create lookup for upper cases as well
chiffre.update( { c.upper():n.upper() for c,n in chiffre.items() } )
# supply ? for all unknowns, use the knowns where possible and return as string
return ''.join( (chiffre.get(c,"?") for c in data) )
def main():
try:
msg = (input("Write the message you would like to encrypt\n"))
key = int(input("which key would you like to use?\n"))
print(cipher(data=msg, key=key))
except ValueError:
print("Write a number!")
main()
Output:
Write the message you would like to encrypt
Hello World
which key would you like to use?
1
Ifmmp?Xpsme
EDIT: Completely fixed now.
EDIT: Okay so now I got it to change '... --- ...' to 'sos' (yippee!) But for some reason, it gives me a KeyError when I input '... --- ... / ... --- ...'.
This should give me 'sos sos' but I get a KeyError for ' '.
I think this is because after the '/', there's a space which the program sees as a trigger to call the dictionary value of the current key. Problem being, the current key at that time is blank since the previous character was the '/'. How would I be able to fix this?
Thanks.
I'm pretty new to programming with python (well, programming in general, really...) and today I had the bright idea of making a morse code converter.
I have the "plain text to morse code" working flawlessly, but the "morse code to plain text"?
Not so much.
The problem is that when I run the program, it doesn't give me anything, it just breaks its loop (like I told it to) without anything coming back to me.
If you guys could help me out, I'd very much appreciate it.
Oh also, 'decoding_dict' is the dictionary which I made which correlates morse code values to plain text.
For example,
decoding_dict = {'...' : 's' , '---' : 'o'}
And so on and so forth.
def decode(text):
text += ' '
#I have it set up to trigger when there's a space, hence this.
global key
global decoded_text
#I thought maybe this would fix it, it didn't. :(
key = ''
decoded_text = ''
for i in text:
if i == '.':
key += i #This adds a '.' to the key to reference later.
continue
elif i == '-':
key += i #See above comment.
continue
elif i == ' ':
decoded_text += decoding_dict[key]
text = text[(len(key) + 1) :]
key = '' #Calls the value of the key, cuts out the used text, and resets key.
continue
elif i == '/':
decoded_text += decoding_dict['/']
continue #In morse code, a '/' is a ' ' and that's in the dict.
elif text == '':
print "Result: " + decoded_text
break #This is basically the end of the loop
else:
print "Error, please try again."
break
Now when I run it with '... --- ...' , it goes back to the beginning and doesn't print anything.
(By beginning, I mean the menu I made beforehand.)
According to your code try something like this:-
def decode(text):
text += '$'
#I have it set up to trigger when there's a space, hence this.
global key
global decoded_text
#I thought maybe this would fix it, it didn't. :(
key = ''
decoded_text = ''
for i in text:
if i == '.':
key += i #This adds a '.' to the key to reference later.
continue
elif i == '-':
key += i #See above comment.
continue
elif i == ' ':
decoded_text += decoding_dict[key]
text = text[(len(key) + 1) :]
key = '' #Calls the value of the key, cuts out the used text, and resets key.
continue
elif i == '/':
decoded_text += decoding_dict['/']
continue #In morse code, a '/' is a ' ' and that's in the dict.
elif text == '$':
print "Result: " + decoded_text
break #This is basically the end of the loop
else:
print "Error, please try again."
break
According to My Suggestion Try This:-
def decode(text):
error = False
#I have it set up to trigger when there's a space, hence this.
global key
global decoded_text
#I thought maybe this would fix it, it didn't. :(
key = ''
decoded_text = ''
for i in text:
if i == '.':
key += i #This adds a '.' to the key to reference later.
continue
elif i == '-':
key += i #See above comment.
continue
elif i == ' ':
decoded_text += decoding_dict[key]
text = text[(len(key) + 1) :]
key = '' #Calls the value of the key, cuts out the used text, and resets key.
continue
elif i == '/':
decoded_text += decoding_dict['/']
continue #In morse code, a '/' is a ' ' and that's in the dict.
else:
print "Error, please try again."
error = True
break
else:
If not error:
print "Result: " + decoded_text
Last else is used with for instead of if else
Assuming space ' ' is a separator in the input you specify, you may use this:
decoding_dict = {'...' : 's' , '---' : 'o'}
my_text = '... --- ...'
print(''.join(list(map(lambda x: decoding_dict.get(x, None),
Output:
sos
As for the code above, there are couple of issues:
modifying 'text' while iterating over it
checking if text == '', which never happens. Hence, the result is never printed.
Try this:
def decode(text):
text += ' '
#I have it set up to trigger when there's a space, hence this.
global key
global decoded_text
#I thought maybe this would fix it, it didn't. :(
key = ''
decoded_text = ''
for i in text:
if i == '.':
key += i #This adds a '.' to the key to reference later.
continue
elif i == '-':
key += i #See above comment.
continue
elif i == ' ':
decoded_text += decoding_dict[key]
key = '' #Calls the value of the key, cuts out the used text, and resets key.
continue
elif i == '/':
decoded_text += decoding_dict['/']
continue #In morse code, a '/' is a ' ' and that's in the dict.
else:
print("Error, please try again.")
break
print("Result: " + decoded_text)
call: decode(my_text)
Output:
Result: sos
The for loop only considers the initial value of text. Your changes to text in the loop have no effect, because text is a string, and strings are immutable, so your modifications don't modify the original object that you're iterating over. The result is that your loop iterates over all of the original text, completing the loop without ever entering either of your break conditions.
Just get rid of the if text == '' check and move the "print results" line outside the for loop. You don't need to "cut out the used text", because by the time you get to the point where you want to do that, you've already iterated past the entire key. If you just pick up where you left off, you'll begin parsing the next Morse letter on the next loop iteration anyway.