Changing Characters in sentence Python whithout library - python

In my sentence i want :
replace every # by *
skip every ?
if the ascii value of a char is pair so i am transforming into LowerCase + Shift Value ( input user)
if the ascii value of a char is impair so i am transforming into UpperCase + Shift Value ( input user)
Its tell me
line 19, in replace
new = ord(lower(c)) + (shift % 26)
TypeError: ord() expected string of length 1, but NoneType found
def lower(c):
if 'A' <= c <= 'Z':
c = chr(ord(c) + (ord('a') - ord('A')))
def upper(c):
if 'a' <= 'c' <= 'z':
c = chr(ord(c) - (ord('a') - ord('A')))
def replace(text):
new_text = ''
for c in text:
if c == '#':
new_text += '*'
elif c == '?':
continue
elif ord(c) % 2 == 0:
new = ord(lower(c)) + (shift % 26)
if new > ord('z'):
new = (ord('a') + (new - ord('z')))
new_text += chr(new)
elif ord(c) % 2 != 0:
new = ord(upper(c)) + (shift % 26)
if new_text > 'Z':
new_text = chr('Z' + (new_text - 'Z'))
new_text += chr(new)
return new_text
sentence = (input("Please enter a sentence to encrypt:\n"))
shift = int(input("Please enter the size of the shift:\n"))
sentence = replace(sentence)

Related

reversing this encoding algorithm in Python

I need help reversing this encoding algorithm into a decoding algorithm. I understand the swap function but I'm having trouble with rest of the code.
from string import ascii_letters, digits
def shift(text, shift: int = 0):
SPACE = ' '
letters = ascii_letters + digits + SPACE
letters_length = len(letters)
shifted_chars = []
for char in text:
if char in letters:
shifted_chars.append(letters[(letters.index(char) + shift) % letters_length])
else:
shifted_chars.append(char)
return ''.join(shifted_chars)
def swap(text):
middle = len(text) // 2
return text[middle:] + text[:middle]
def encode(text):
if len(text) < 2:
return shift(text, 7)
for i in range(31):
text = swap(shift(text, i))
return text
Fixed owing to Parisa.H.R's useful comment(s).
The deswap(text) function equalizes asymmetric result of swap(text) in case of odd len(text).
from string import ascii_letters, digits
def shift(text, shift: int = 0):
SPACE = ' '
letters = ascii_letters + digits + SPACE
letters_length = len(letters)
shifted_chars = []
for char in text:
if char in letters:
shifted_chars.append(letters[(letters.index(char) + shift) % letters_length])
else:
shifted_chars.append(char)
return ''.join(shifted_chars)
def swap(text):
middle = len(text) // 2
return text[middle:] + text[:middle]
def deswap(text):
middle = (len(text) + (len(text) % 2)) // 2
return text[middle:] + text[:middle]
def encode(text):
if len(text) < 2:
return shift(text, 7)
for i in range(31):
text = swap(shift(text, i))
return text
def decode(text):
if len(text) < 2:
return shift(text, -7)
for i in range(30, -1, -1):
text = deswap(shift(text, -i))
# text = shift(deswap(text), -i)
return text
Output:
decode(encode('opening'))
# 'opening'
decode(encode('openin'))
# 'openin'
decode(encode('Quora'))
# 'Quora'
decode(encode('Quoran'))
# 'Quoran'
decode(encode(ascii_letters + digits)) == ascii_letters + digits
# True
decode(encode(ascii_letters + digits + ' ')) == ascii_letters + digits + ' '
# True

Trying to wrap caesar cypher (Python)

I've tried using "if" statements to skip characters that aren't alphabetical but It keeps ignoring the code and adding the shifted characters. I'm trying to shift the user input by 2 but the encoded-word should not have any special characters so the shift would wrap round back from z-a.
The code below is before I tried "if" statements.
encoded_word = ("")
decoded_word = ("")
def Encoding(text):
global encoded_word
letter_list = list(text)
length_list = len(text)
for i in range (0,length_list):
letter_ord = ord(letter_list[i])
encoded_letter = chr(letter_ord+2)
encoded_word = (encoded_word + encoded_letter)
print ("The encoded word is now:",encoded_word)
def Decoding(text):
global decoded_word
letter_list = list(text)
length_list = len(text)
for i in range (0,length_list):
letter_ord = ord(letter_list[i])
decoded_letter = chr(letter_ord-2)
decoded_word = (decoded_word + decoded_letter)
print ("The decoded word is:",decoded_word)
decode_encode = str(input("Would you like to encode or decode text? encode/decode: "))
if decode_encode == "encode":
user_word = str(input("Enter in a word to encode: "))
Encoding(user_word)
if decode_encode == "decode":
user_word = str(input("Enter in the encoded word: "))
Decoding(user_word)
to check if a character is a letter you can use isalpha().
For example should print just d and f:
list = ["3","2","-","1","4","5","-","3","d", "f"]
character_list = []
for i in list:
if i.isalpha():
character_list.append(i)
print (character_list)
I think you are on the right track you just to deal with a couple more edge cases such as if the shift amount is greater than 26, or if the shift needs to wrap around, etc. Additionally, string concatenation using + is inefficient since a copy of the existing string needs to be made each concatenation. Therefore, consider appending to a list of characters instead and only creating an output encoded/decoded string at the end:
SHIFT_AMOUNT = 2
def encode(text):
res = []
actual_shift_amount = SHIFT_AMOUNT % 26
for ch in text:
new_letter = ch
if ord('a') <= ord(ch) <= ord('z'):
if (ord(ch) + actual_shift_amount) <= ord('z'):
new_letter = chr(ord(ch) + actual_shift_amount)
else:
new_letter = chr(ord('a') + actual_shift_amount - (ord('z') - ord(ch) + 1))
elif ord('A') <= ord(ch) <= ord('Z'):
if (ord(ch) + actual_shift_amount) <= ord('Z'):
new_letter = chr(ord(ch) + actual_shift_amount)
else:
new_letter = chr(ord('A') + actual_shift_amount - (ord('Z') - ord(ch) + 1))
res.append(new_letter)
return ''.join(res)
def decode(text):
res = []
actual_shift_amount = SHIFT_AMOUNT % 26
for ch in text:
new_letter = ch
if ord('a') <= ord(ch) <= ord('z'):
if (ord(ch) - actual_shift_amount) >= ord('a'):
new_letter = chr(ord(ch) - actual_shift_amount)
else:
new_letter = chr(ord('z') - actual_shift_amount + (ord(ch) - ord('a') + 1))
elif ord('A') <= ord(ch) <= ord('Z'):
if (ord(ch) - actual_shift_amount) >= ord('A'):
new_letter = chr(ord(ch) - actual_shift_amount)
else:
new_letter = chr(ord('Z') - actual_shift_amount + (ord(ch) - ord('A') + 1))
res.append(new_letter)
return ''.join(res)
decode_or_encode = input("Would you like to encode or decode text? encode/decode: ").lower()
if decode_or_encode == "encode":
user_word = input("Enter in a word to encode: ")
print(encode(user_word))
elif decode_or_encode == "decode":
user_word = input("Enter in the encoded word: ")
print(decode(user_word))
Example Usage encode:
Would you like to encode or decode text? encode/decode: encode
Enter in a word to encode: Yoruke-Stack-Overflow
Aqtwmg-Uvcem-Qxgthnqy
Example Usage decode:
Would you like to encode or decode text? encode/decode: decode
Enter in the encoded word: Aqtwmg-Uvcem-Qxgthnqy
Yoruke-Stack-Overflow
Try it here.
The problem is that when adding or subtracting 2 you do not check if you reached the limit of the alphabet ('a' or 'z'). You should do something like
if encoded_letter > "z":
# do something
The approach you are following is not the best one. However, assuming that you are considering lowercase characters only.
Encoding
replacing
encoded_letter = chr(letter_ord + 2)
with
encoded_ord = letter_ord + 2
if encoded_ord > ord('z'): # after encoding if exceeds from 'z'
difference = encoded_ord - ord('z') # finding how much exceeded from 'z'
encoded_ord = ord('a') + difference + 1 # restart from 'a' again.
encoded_letter = chr(encoded_ord)
Decoding
replacing
decoded_letter = chr(letter_ord-2)
with
decoded_ord = letter_ord - 2
if decoded_ord < ord('a'): # after decoding if deceeds from 'a'
difference = ord('a') - decoded_ord # finding how much deceeded from 'a'
decoded_ord = ord('z') - difference + 1 # restart from 'z' again but backward
decoded_letter = chr(decoded_ord)
should work

Python - Iterating over / counting spaces and punctuation

I cannot understand why the below code is not updating/incrementing the "spaces" or "sentences" variable - but it is recognising "letters"
Any suggestions would be immense! Thank you so much!!
from cs50 import get_string
text = get_string("text: ")
i = 0
letters = 0
spaces = 0
sentences = 0;
for element in text:
if text[i] != '.' and text[i] != '?' and text[i] != '!' and text[i] != '"' and text[i] != ',' and text[i] != '-' and text[i] != ':' and text[i] != ';' and text[i] != ' ':
letters += 1
for element in text:
if text[i] == " ":
spaces += 1
for element in text:
if text[i] == '.' or text[i] == '?' or text[i] == '!':
sentences += 1
words = spaces +1
L = float(letters/words *100)
S = float(sentences/words *100)
A = float(0.0588*L)
B = float(A - 0.296*S)
C = float(B - 15.8)
index = int(C)
if index < 1:
print("Before Grade 1")
elif index >= 16:
print("Grade 16+")
else:
print("Grade %i\n", index)
print(L,S,A,B,C,index, i, letters, spaces, sentences)

How can I make this code shorter (less lines etc)

I am writing a code and want to make it as short as possible, is there any way i can?
text = raw_input("Give me some text > ")
list1 = []
for char in text:
num = ord(char)
if num in range(48,57):
print "ERROR 319: Number entered"
quit()
elif num in range(65,90) or num in range (97,122):
upper = char.upper()
list1.append(upper)
num1 = 0
vowelCount = 0
conCount = 0
for x in range(len(list1)):
if list1[num1] == "A" or list1[num1] == "E" or list1[num1] == "I" or list1[num1] == "O" or list1[num1] == "U":
vowelCount = vowelCount + 1
else:
conCount = conCount + 1
num1 = num1 + 1
print "Vowels: " +str(vowelCount) + " Consonants: " + str(conCount)
Instead of taking ord() of the character, you can use the string methods:
char.isdigit() # check if a char is a digit
char.isalpha() # check if char is letter
For checking the vowel counts, try:
vowel_count = len(filter(lambda c: c in "aeiou", list1))
cons_count = len(list1) - vowel_count
Building off of AmourK's answer, you could do something like this:
text = raw_input("Give me some text > ")
vowel_count = len(filter(lambda c: c in "aeiou", text))
cons_count = len(filter(lambda c: c not in "aeiou" and c.isalpha(), text))
print "Vowels: %d Consonants: %d" % (vowel_count, cons_count)

python caesar chr and ord without newline and just iterate in the alphabet

I have some problem with my caesar code.
1) I don't know how to check if a character is a punctuation and print without sum.
2) print the char on the same line but when it's finished return a newline.
3) Iterate through the alphabet with big number return me a punctuation, how can I do to return just a character?
import sys
import string
def main():
if len(sys.argv) != 2:
print("Usage: caesar.py k")
else:
k = int(sys.argv[1])
if k == 1 or k <= 26:
text = input("plaintext: ");
j = len(text)
for i in range(j):
#check if is a character
if text[i].isalpha:
if text[i].islower():
print(chr(ord(text[i]) + k),end = "")
if text[i].isupper():
print(chr(ord(text[i]) + k),end = "")
elif text[i].punctuation():
print(text[i])
else:
print("You have to introduce a number between 1 and 26")
main()
Try this code:
import string
def encrypt_ceasar(s, shift):
assert abs(shift) < 26, 'shift is between -25 and 25 (inclusive)'
encrypted_s = ''
for char in s:
if char.isalpha():
is_upper = char.isupper()
char = char.lower()
pos_alphabet = ord(char) - ord('a')
new_pos = (pos_alphabet + shift) % 26
encryted_char = chr(ord('a') + new_pos)
if is_upper:
encryted_char = encryted_char.upper()
encrypted_s += encryted_char
else:
encrypted_s += char
return encrypted_s
def decrypt_ceasar(s, shift):
return encrypt_ceasar(s, -shift)
if __name__ == "__main__":
s = 'AbC1$de#zy'
encrypted_s = encrypt_ceasar(s, 3)
print('s:', s)
print('encrypted_s:', encrypted_s)
print('again s:', decrypt_ceasar(encrypted_s, 3))
Output:
s: AbC1$de#zy
encrypted_s: DeF1$gh#cb
again s: AbC1$de#zy

Categories