Vigenere cipher not working - python

So my teacher created this vigenere cipher and he said it was working.
However, after checking its results with online vigenere ciphers it appears to not be resulting with the correct encryptions.
I have no idea how to fix it and I was wondering if someone could direct me to the errors, and tell me how to fix them.
Here is the code
base = ord("a")
alphabets = 'abcdefghijklmnopqrstuvwxyz'
keyword = input('What is your keyword')
message = input('What is your message to be coded or encoded?').lower()
expandedKeyword = ""
while len(expandedKeyword) < len(message):
for i in keyword:
if len(expandedKeyword) < len(message):
expandedKeyword += i
cipheredMessage = ''
indexofKeyword = 0
for i in message:
if i == ' ':
cipheredMessage = cipheredMessage + " "
else:
shiftedIndex = (ord(i) + ord(expandedKeyword[indexofKeyword])-base) % 26 +base
cipheredMessage = cipheredMessage + chr(shiftedIndex)
indexofKeyword = indexofKeyword + 1
print(cipheredMessage)
I understand the concept of what is happening, but I cant seem to figure out the error.

Your calculation of shiftedIndex is wrong, you need to subtract base twice , but you are currently only subtracting it once. Example -
shiftedIndex = (ord(i) + ord(expandedKeyword[indexofKeyword])-2*base) % 26 +base
This is because you need to subtract base first time from ord(i) to get the index of i (from 'a') , and the second time from ord(expandedKeyword[indexofKeyword]) , to get the index of that character (from 'a' ) . So it should look like (for better understanding) -
shiftedIndex = ((ord(i) - base) + (ord(expandedKeyword[indexofKeyword])-base)) % 26 + base

Related

Openpyxl module: return weird value(not error) + hope to calculate

I wrote some codes trying to let the user be able to check the percentage of the money they spent(compared to the money they earned). Almost every step perform normally, until the final part.
a_c[('L'+row_t)].value return:
=<Cell 'Sheet1'.B5>/<Cell 'Sheet1'.J5>
yet I hope it should be some value.
Code:
st_column = st_column_r.capitalize()
row_s = str(a_c.max_row)
row_t = str(a_c.max_row + 1)
row = int(row_t)
a_c[('J'+row_t)] = ('=SUM(I2,J'+row_s+')') #總收入
errorprevention = a_c[('J'+row_t)].value
a_c[(st_column+row_t)] = ('=SUM('+(st_column+'2')+','+(st_column+row_s)+')')
a_c['L'+row_t].number_format = FORMAT_PERCENTAGE_00
if errorprevention != 0:
a_c[('L'+row_t)] = ('='+str(a_c[(st_column+row_t)])+'/'+str(a_c[('J'+row_t)]))
print('過往支出中,'+inputtype[st_column]+'類別佔總收入的比率為:'+a_c[('L'+row_t)].value)
Try changing the formula creation to;
a_c[('L' + row_t)].value = '=' + a_c[(st_column + row_t)].coordinate + '/' + a_c[('J' + row_t)].coordinate
or use an f string
a_c[('L' + row_t)].value = f"={a_c[(st_column + row_t)].coordinate}/{a_c[('J' + row_t)].coordinate}"

How to test unicode code points for valid LTR use in Python?

This question is relative to this one. But as my tried solution does not work, I open a new question to deal with my specific problems.
Context:
In the application I develop, I need to build python regex that includes unicodes, possibly in the whole range(0, 0x110000). When I build my regex, for example with the following:
regex += mycodepoint_as_char + ".{0," + str(max_repeat) + "}"
I observes that for some code points, the order is reversed as if I had written:
regex += "{0," + str(max_repeat) + "}." + mycodepoint_as_char
regex = ή.{0,2}{0,3}.䝆⚭.{0,3}俩.{0,4}ⷭ
In other cases, I have an exception.
So I studied the norm for biderectional unicode and some Q/A that explain surrogate pairs, Left-To-Right and Right-To-Left special code points, and some prohibited ones reserved for UTF-16.
My problem:
Then I have decided to test all of them, and to build a list of RTL ones and prohibited ones, assuming the first would change the order in the string, and that the last would raise an exception.
Here is my test code:
#!/usr/bin/python3
import sys
import os
import unicodedata #https://docs.python.org/fr/3/library/unicodedata.html, https://fr.wikipedia.org/wiki/Normalisation_Unicode
def group_consecutive(l):
res = []
i1 = 0
i2 = 0
while i1 < len(l):
while i2 + 1 < len(l) and l[i2+1] == l[i2] + 1:
i2 += 1
res.append((i1, i2+1)) # range(i1, i2+1) has consecutive values
i1 = i2+1
i2 = i1
return res
def id_rtl_code_points():
oldstdout = sys.stdout # https://stackoverflow.com/questions/8777152/unable-to-restore-stdout-to-original-only-to-terminal
nullstdout = open(os.devnull, 'w') # https://stackoverflow.com/questions/26837247/how-to-disable-print-statements-conveniently-so-that-pythonw-can-run?noredirect=1&lq=1
forbiddenCP = []
sep = 'a' # choose a letter that can receive modifiers
s = ""
for i in range(0, 0x110000):
if i%0x10000 == 0:
print(hex(i) + "-------------") # show progress
try:
if len(s) % 2 == 1: #keep synchronised, sep on modulo = 0, chr(i) on modulo = 1
s += sep
#sys.stdout = nullstdout
print(hex(i), " : " + sep + chr(i)) # without print, no error
except:
forbiddenCP.append(i)
else:
s += sep + chr(i)
finally:
pass
#sys.stdout = oldstdout
s += sep
rtlCP = []
for i in range(0, 0x110000,2):
if s[i] != sep: #not sure at all this algorythm is right
rtlCP.append(ord(s[i]))
sys.stdout = oldstdout
#print("id_rtl_code_points - s = ", s)
print("rtlCP = ", group_consecutive(rtlCP))
print("rtlCP% = ", round(float(len(rtlCP))/0x110000*100, 2), "%")
print("forbiddenCP = ", group_consecutive(forbiddenCP))
print("forbiddenCP% = ", round(float(len(forbiddenCP))/0x110000*100, 2), "%")
def main():
id_rtl_code_points()
if __name__ == '__main__':
main()
Run as it is, I get (I skip parts with dots):
$ ./test.py
0x0-------------
0x0 : a
0x1 : a
0x2 : a
....................
0x21 : a!
0x22 : a"
0x23 : a#
0x24 : a$
....................
0x60 : a`
0x61 : aa
0x62 : ab
0x63 : ac
0x64 : ad
....................
0x98 : a
0x9a : a
0x9b : a
9c : a
0x9d : a$ 1;1;120;120;1;0x
Not so good, I don't understand why it stops displaying.
If I forward stdout to /dev/null for the exception test (uncomment lines 33 and 41), I get:
$ ./test.py
0x0-------------
0x10000-------------
0x20000-------------
0x30000-------------
0x40000-------------
0x50000-------------
0x60000-------------
0x70000-------------
0x80000-------------
0x90000-------------
0xa0000-------------
0xb0000-------------
0xc0000-------------
0xd0000-------------
0xe0000-------------
0xf0000-------------
0x100000-------------
rtlCP = []
rtlCP% = 0.0 %
forbiddenCP = [(0, 2048)]
forbiddenCP% = 0.18 %
The first 2048 code points would raise exception ? This is a silly result, of course not. I would have expected problems in the range U+D800 and U+DFFF.
Is my approach correct, then what do I miss, or is it non sense, then why?

how to find out how many lines are in a variable

I'm doing a Telegram bot and I want to print string in Inline keyboard. I have a variable text which can change and I want to chack how much lines(string) in variable as it can do with it 0<name<2 and do restrictions. How can do it?
I could make it with len(), but it show me list index out range
text="head,hand,..."
selectKeyboard = telebot.types.InlineKeyboardMarkup( row_width=1)
if 0<name<2:
for i in range(len(text)):
one=types.InlineKeyboardButton(text=str(text[0]['name']),callback_data="first")
selectKeyboard.add(one)
if 0<name<3:
for i in range(len(text)):
one=types.InlineKeyboardButton(text=str(text[0]['name'])+" ",callback_data="first")
two=types.InlineKeyboardButton(text=str(text[1]['name'])+" ",callback_data="second")
selectKeyboard.add(one,two)
if 0<name<4:
for i in range(len(text)):
one=types.InlineKeyboardButton(text=str(text[0]['name'])+" ",callback_data="first")
two=types.InlineKeyboardButton(text=str(text[1]['name'])+" ",callback_data="second")
three = types.InlineKeyboardButton(text=str(text[2]['name']) + " " ,callback_data="three")
selectKeyboard.add(one,two,three)
if 0<name<5:
for i in range(len(text)):
one=types.InlineKeyboardButton(text=str(text[0]['name'])+" ",callback_data="first")
two=types.InlineKeyboardButton(text=str(text[1]['name'])+" "+,callback_data="second")
three = types.InlineKeyboardButton(text=str(text[2]['name']) + " " ,callback_data="three")
four = types.InlineKeyboardButton(text=str(text[3]['name']) + " " , callback_data="four")
selectKeyboard.add(one,two,three,four)
if 0<name<6:
for i in range(len(text)):
one=types.InlineKeyboardButton(text=str(text[0]['name'])+" ",callback_data="first")
two=types.InlineKeyboardButton(text=str(text[1]['name'])+" ",callback_data="second")
three = types.InlineKeyboardButton(
text=str(text[2]['name']) + " " ,
callback_data="three")
four = types.InlineKeyboardButton(
text=str(text[3]['name']) + " " ,
callback_data="four")
five=types.InlineKeyboardButton(
text=str(text[4]['name']) + " " ,
callback_data="five")
selectKeyboard.add(one, two, three, four,five)
The following piece of code is not doing what you imagine, in fact it'll just return False, because name is a string and you're comparing it against integers:
0 < name < 2
Instead, you should test for the number of variables, like this:
text = "head,hand,..."
num_vars = len(text.split(','))
if 0 < num_vars < 2:
# same for all the other comparisons

How would I find the nearest space per every 2000 characters and add everything before it to a variable? (Python)

I'm currently writing a program that posts messages with a 2,000 character limit. The string I'm using is usually around 10,000 characters. However, the method I'm using to divide it up can divide the string up in the middle of a word - how would I only have it divide at the nearest space (BEFORE) 2k characters?
Here's the current code:
text = str(post.selftext)
title = await client.send_message(message.author, str(post.title))
if len(text) > 1990:
amountsplit = math.ceil(len(text) / 1990)
atatime = math.floor(len(text) / amountsplit)
donetimes = 0
lastone = 0
for i in range(amountsplit):
todonow = int(donetimes + 1) * atatime
tmp = await client.send_message(message.author, str(text[lastone:todonow]))
lastone = todonow
donetimes += 1
U can use rfind() method of str:
from __future__ import print_function
def split_message(message, character_limit=2000):
messages = []
while len(message) > character_limit:
split_index = message[:character_limit].rfind(" ")
if split_index == -1:
# No space found, just split at the character limit
split_index = character_limit
else:
# Else space is found, split after the space
split_index += 1
messages.append(message[:split_index])
message = message[split_index:]
messages.append(message)
return messages
# Test code
test_string = "this is a test string to see if this works right"
test_string = "thisisateststringwithnospaces"
for character_limit in range(1, 10):
print ("limit", character_limit, ": ", split_message(test_string, character_limit))
you can take the characters and read it from the end (with a decremental loop for until find space) It should look like :
for i in range(len(text)-1, 0, -1):
if text[i]==' ':
break
print "found the last space !"
EDIT
VeryLongText="the very long text..[..]....here"
text = VeryLongText[0:1999]
for i in range(len(text)-1, 0, -1):
if text[i]==' ':
Var=text[0:i]
break
print Var
Var will be your text (the first 2000 characters of the long text) until the last space
Use a generator.
def messages_from_post(post, limit=2000):
while len(post) > limit:
try:
i = post.rindex(' ', 0, limit + 1)
except ValueError:
i = limit
message, post = map(str.lstrip, [post[:i], post[i:]])
yield message
yield post

Python Encryption using Keyphrase

I am trying to make a python program that will take in plain text and encrypt it using a key. It is written with python 2.7.4
This is my code so far
def encrypter(intext, shift, modder):
plain = list(intext)
out = ''
j = 0
key = list(shift)
for i in plain:
if mod > 0:
x = chr((ord(i) + ord(key[(j % (len(plain) - 1)) % len(key)]) - 48) % 58 + 48)
if mod < 0:
x = chr(((ord(i) - ord(key[(j % (len(plain) - 1)) % len(key)]) - 48) % 58 + 48))
out += x
j += 1
return out
sel = raw_input("Encrypt (e)/ Decrypt (d)")
if sel == 'e':
mod = 1
elif sel == 'd':
mod = -1
else:
mod = 0
print('Enter a proper value!')
if mod != 0:
print(encrypter(raw_input('Enter the text:'), raw_input('Enter the key-phrase:'), mod)
When I encrypt something I get this:
C:\Users\aesha_000\py\Scripts\python.exe "D:/Programming/Computing GCSE/Resources/functiontest3.py"
Encrypt (e)/ Decrypt (d)e
Enter the text:alex
Enter the key-phrase:pass
]Yd:
Process finished with exit code 0
But the problem is when I then Decrypt it again I get the wrong output:
C:\Users\aesha_000\py\Scripts\python.exe "D:/Programming/Computing GCSE/Resources/functiontest3.py"
Encrypt (e)/ Decrypt (d)d
Enter the text:]Yd:
Enter the key-phrase:pass
a2e>
Process finished with exit code 0
Does anyone know the answer to this or am I just being stupid?
You should remove % 58 + 48.
I'm assuming you're using it for having printable ascii chars, but you should not. You're loosing information.
If you want to display "not printable ascii chard", use base64.

Categories

Resources