Python Message Cipher Indexation Error + WhiteSpace issue - python

I am working on an exercise to encode a message in Python. The following function is supposed to take in a message and a number to shift the letters in each word by that amount in the alphabet i.e. the letter a if moved 3 spaced would become d.
I have two issues:
The length of the alphabet is only 26 characters long. If you shift a letter too far right i.e. past the 26th position of Z you get the following error:
IndexError: string index out of range
I'd be happy with a fix that shifts the index back to the start again and moves the letter index based on the remainder of whatever goes past 26 characters i.e. if there is a shift of 9 with the char y then the remaining 9 after 26 could be positioned start from a again, making y the letter i.
If I were to input a message with spaces i.e. "I need help", the returned characters do not retain the original white space between each word.
Can anyone help with questions 1 or 2?
def message_to_code():
normal_message = input(str("Please enter a message you would like coded: "))
Cipher_shift = int(input("Please enter the whole number you would like to act as the key to hide your message "))
Alphabet = "abcdefghijklmnopqrstuvwxyz"
Cipher_message = ' '
for letter in normal_message:
Encrypted_letter = Alphabet.find(letter) + Cipher_shift
Cipher_message = Cipher_message + Alphabet[Encrypted_letter]
return print(Cipher_message)
message_to_code()

Your first problem can be easily fixed by checking if Alphabet.find(letter) + Cipher_shift >= len(Alphabet). If it is, than Encrypted_letter = Encrypted_letter - len(Alphabet).
Your second problem was tricky to completely understand, but I think the fix you are looking for is checking if letter is a space. If it is, loop to the next character, if it's not, do the logic with that character.
The bug fixes look like this:
def message_to_code():
normal_message = input(str("Please enter a message you would like coded: "))
Cipher_shift = int(input("Please enter the whole number you would like to act as the key to hide your message "))
Alphabet = "abcdefghijklmnopqrstuvwxyz"
Cipher_message = ' '
for letter in normal_message:
if letter != ' ':
Encrypted_letter = Alphabet.find(letter) + Cipher_shift
if Encrypted_letter >= len(Alphabet):
Encrypted_letter -= len(Alphabet)
Cipher_message = Cipher_message + Alphabet[Encrypted_letter]
else:
Cipher_message += ' '
I also fixed some other problems. For example, if you have a capital letter, your original code wouldn't catch that, since Alphabet is only filled with lower-case letters. To fix this, I added a second array dedicated to capital-letters, and check to see if letter is capital or not.
The second fix is checking if letter is a part of the alphabet or not. If it isn't, that would mean letter is: '/', '.', ',', ':', ';', etc. If it does happen to be one of these characters, it just adds its original self to the encrypted string.
The modified code looks like this:
def message_to_code():
normal_message = input(str("Please enter a message you would like coded: "))
Cipher_shift = int(input("Please enter the whole number you would like to act as the key to hide your message "))
Alphabet = "abcdefghijklmnopqrstuvwxyz"
AlphabetCaps = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Cipher_message = ""
is_letter = True
for letter in normal_message:
if letter != ' ':
if Alphabet.find(letter) != -1:
Encrypted_letter = Alphabet.find(letter) + Cipher_shift
is_letter = True
elif AlphabetCaps.find(letter) != -1:
Encrypted_letter = AlphabetCaps.find(letter) + Cipher_shift
is_letter = True
else:
is_letter = False
if is_letter:
if Encrypted_letter >= len(Alphabet):
Encrypted_letter -= len(Alphabet)
if Alphabet.find(letter) != -1:
Cipher_message += Alphabet[Encrypted_letter]
else:
Cipher_message += AlphabetCaps[Encrypted_letter]
else:
Cipher_message += letter
else:
Cipher_message += ' '
return print(Cipher_message)

Related

python list index is out of range [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 months ago.
Improve this question
I am trying to make a program that shifts the characters of a message to the right of its position in the alphabet. For example: the input is "abc" and the output would be "bcd".
Currently this is the code:
import string
alphabet = list(string.ascii_lowercase)
codelist = []
code = input("input text message: ")
for char in code:
codelist.append(char)
for x in codelist:
for y in alphabet:
if y == x and x != " ":
x = alphabet[alphabet.index(y) + 1]
Traceback:
Traceback (most recent call last):
File "C:\Users\User\PycharmProjects\pythonProject1\file.py", line 12, in <module>
x = alphabet[alphabet.index(y) + 1]
IndexError: list index out of range
This is a Caesar shift. Here is a Caesar shift implementation handling spaces, digits, and alphabetical characters. Just give it a string and the "shift" that you want the characters to change by.
# a function that takes prompts the user for a string and a shift value
# and returns the encoded string
def shift():
# prompt the user for a string
string = input("Enter a string: ")
# prompt the user for a shift value
shift = int(input("Enter a shift value: "))
# create an empty string
new_string = ""
# shift string based on shift value
for i in string:
# if the character is a space, add it to the new string
if i == " ":
new_string += i
# if the character is a lowercase letter, shift it
elif i.islower():
# if the character is shifted past z, wrap around to a
if ord(i) + shift > ord("z"):
new_string += chr(ord(i) + shift - 26)
# otherwise, shift the character
else:
new_string += chr(ord(i) + shift)
# if the character is an uppercase letter, shift it
elif i.isupper():
# if the character is shifted past Z, wrap around to A
if ord(i) + shift > ord("Z"):
new_string += chr(ord(i) + shift - 26)
# otherwise, shift the character
else:
new_string += chr(ord(i) + shift)
# if the character is a number, shift it
elif i.isdigit():
# if the character is shifted past 9, wrap around to 0
if ord(i) + shift > ord("9"):
new_string += chr(ord(i) + shift - 10)
# otherwise, shift the character
else:
new_string += chr(ord(i) + shift)
# if the character is a special character, shift it
else:
new_string += chr(ord(i) + shift)
# return the new string
print("DEBUG: " + new_string)
# call the function
shift()
Actually, your code will break if someone enters 'z' in their input your code will break. Also, if someone enters an uppercase letter then your code will just skip that uppercase letter. You can solve these small errors by changing the input to lowercase form like this:
code = input('input text message: ')
code = code.lower()
For the second error you can add an if statement. So, whenever it faces 'z' in the input it will just specify the value of char to 'a'
You can achieve this like this
if y == x and x != " " and x !="z":
char = alphabet[alphabet.index(y) + 1]
moved += char
elif y == x and x == "z":
char = 'a'
moved +=char
If you are wondering about that moved variable then this is just a variable storing the shifted letters for example if the input is 'The' then for every iteration the shifted chracter will be added to the moved variable. And the value of moved variable will update like this
1. u
2. ui
3. uif
After the program ends you should also print this value to the console using the print statement.
print(moved)
Your code will now look like this:
import string
alphabet = list(string.ascii_lowercase)
codelist = []
moved = ""
code = input("input text message: ")
code = code.lower()
for char in code:
codelist.append(char)
for x in codelist:
for y in alphabet:
if y == x and x != " " and x !="z":
char = alphabet[alphabet.index(y) + 1]
moved += char
elif y == x and x == "z":
char = 'a'
moved +=char
print(moved)
You could do this simply with ord and slicing
alphabet = string.ascii_lowercase
codelist = []
code = input("input text message: ")
code = code.lower() # make sure user inputs values between a-z
alphabet[ord(code[0])-ord('a')+1 : ord(code[0])-ord('a')+len(code)+1]
# for abc -> bcd and xyz -> yz

I want all characters in a string to increase, except for certain ones

I am working on a small script to encrypt a string that the user provides. The user can also choose how much each character in the string should increment by (on a scale from 1 to 25).
But, I want certain characters to not increment at all (commas, periods, question marks, and spaces) and I have these in a list. How exactly is the possible?
Below is the Python Script.
user_str = str(input("Enter String: "))
user_inc = int(input("How much do you want to increase by: "))
if user_inc > 25:
print("You cannot increase by a number larger than 25.")
elif user_inc <= 0:
print("You cannot increase by a number lower than 1.")
else:
final_str = ""
for letter in user_str:
new_str = ord(letter)
enc_str = new_str + user_inc
if enc_str > 122:
enc_str -= 26
# Here is where I need help.
if letter in [',', '.', ' ', '?']:
letter + enc_str
final_str += chr(enc_str)
print(final_str)
I've tried a few different things like trying to add or subtract nothing from the letter, trying to add letter to the final_str, and so far nothing has worked. How exactly can this be done?
You use an if statement to determine whether to add the original value, or the new value to the ciphertext.
[...]
else:
final_str = ""
for letter in user_str:
new_str = ord(letter)
enc_str = new_str + user_inc
if enc_str > 122:
enc_str -= 26
# Here is one idea
if letter in [',', '.', ' ', '?']:
final_str += letter
else:
final_str += chr(enc_str)
print(final_str)

How do I choose 2 or more letters in a word?

Basically my plan was to return text with random-sized letters in words i.e. "upper" or "lower". The script is working, though it seems raw (I am a Beginner and I'd appreciate some corrections from You).
The problem is:
It is not consistent. With that said, it can print word 'about' even if it should be 'About' or something similar.
I want to be sure that the maximum of UPPER or lower letters in a row do not exceed 3 letters. and I don't know how to do it.
Thank you in advance.
#!/usr/bin/env python3
import random
message = input()
stop = ''
def mocking(message):
result = ''
for word in message:
for letter in word:
word = random.choice(random.choice(letter.upper()) + random.choice(letter.lower()))
result += word
return result
while stop != 'n':
print(mocking(message))
stop = input("Wanna more? y/n ").lower()
if stop == 'n':
break
else:
message = input()
You need to split the input into words, decide how many positions inside the word you want to change (minimum 3 or less if the word is shorter).
Then generate 3 unique positions inside the word (via random.sample) to change, check if upper then make lower else make upper. Add to resultlist and join words back together.
import random
message = "Some text to randomize"
def mocking(message):
result = []
for word in message.split():
len_word = len(word)
# get max 3 random positions
p = random.sample(range(len_word),k = min(len_word,3))
for position in p:
l = word[position]
if l.isupper():
word = word[:position] + l.lower() + word[position+1:]
else:
word = word[:position] + l.upper() + word[position+1:]
result.append(word)
return ' '.join(result)
while True:
print(mocking(message))
stop = input("Wanna more? y/n ").lower()
if stop == 'n':
break
else:
message = input()
See Understanding slice notation for slicing
At most 3 modifications? I would go with something like this.
def mocking(message):
result = ''
randomCount = 0
for word in message:
for letter in word:
newLetter = random.choice( letter.upper() + letter.lower() )
if randomCount < 3 and newLetter != letter:
randomCount += 1
result += newLetter
else:
result += letter
randomCount = 0
return result
If the random choice has modified the letter then count it.

Python hangman without lists

I need a simple Python Hangman program without using Lists - It is just one word
HAPPY - this program works - BUT...
This is what I did, with Lists - but teacher said Lists are not allowed
We do not have to draw hangman - we just prompt for the letters - print the "-" for each letter to show length of word.
def main():
secretword = "HAPPY"
displayword=[]
displayword.extend(secretword)
for I in range (len(displayword)):
displayword[I]="_"
print ('current word
')
print (' '.join(displayword))
count = 0
while count < len(secretword):
guess = input('Please guess a etter: ')
for I in range(len(secretword)):
if secretword[I] == guess:
displayword[I] = guess
countr - count + 1
print (' '.join(displayword))
print (congratulations you guess the word')
main()
If you don't like the code - that's fine. This is how our teacher is requiring us to do this. I can see it is not like others do it. I only left out the comments - that are also required on every line of code
One solution to your problem would be to use two strings, secretword, which is the word you're looking for and displayword which is what the user sees so far, the combination of letters and -. Every time you enter a letter, the program checks if the secretword contains that letter and if it does, it updates the character of the specific index in displayword:
def main():
secretword = "HAPPY"
length = len(secretword)
displayword = '-' * length
count = 0
while count < length:
guess = input("Please guess a letter: ")
for i in range(length):
if secretword[i] == guess:
displayword[i] = guess
count += 1
print(displayword)
print("Congratulations, you guessed the word.")
main()

Python Replace Blanks With Letter

I want the letters the user types (granted that they're in the 'letters') to replace the blanks in their correct sequential position (I don't want 'agbdf__'), and stop when all the letters are typed in. As the code is now, it requires letters to be typed multiple times, and it stops if the letter 'g' is typed seven times. This is a part of a hangman code I'm trying to implement. If anyone could post the right way to program this (not just a tip, because I most likely won't be able to figure out how to implement it), it would be much appreciated.
letters='abcdefg'
blanks='_'*len(letters)
print('type letters from a to g')
print(blanks)
for i in range(len(letters)):
if letters[i] in input():
blanks = blanks[:i] + letters[i] + blanks[i+1:]
print(blanks)
Change your loop to:
for i in range(len(letters)):
letter = raw_input()
index = letters.index(letter)
blanks = blanks[:index] + letter + blanks[index + 1:]
print blanks
You are not replacing the correct blank/underscore, you are just sequentially replacing them. Instead you need to find the correct blank to replace, and then replace that. Also don't expect this code to be running infinitely until the blanks is completely filled. If you want that, you can figure that out I guess (as your question is specific to replacing correct letters). Also you might want this program should handle inputs other than 'abcdef' too :).
You could use a list comprehension for this. Here's an example:
letters = 'abcdefg'
typed = raw_input('Type the characters a through g: ')
print ''.join(s if s in typed else '_' for s in letters)
Sample Output:
Type the characters a through g: abdef
ab_def_
Here's a more complete/advanced hangman example: https://gist.github.com/dbowring/6419866
letters = 'abcdefg'
print('type letters from a to g')
all_letters = list(letters)
blanks = ['_'] * len(letters)
while True:
guessed_letter = input("guess > ")
while guessed_letter in all_letters:
index = all_letters.index(guessed_letter)
all_letters[index] = None
blanks[index] = guessed_letter
output = ''.join(blanks)
print(output)
if letters == output:
print("gg")
break
Or if you prefere a more stringy version
letters = 'abcdefg'
print('type letters from a to g')
all_letters = list(letters)
blanks = '_' * len(letters)
while True:
guessed_letter = input("guess > ")
while guessed_letter in all_letters:
index = all_letters.index(guessed_letter)
all_letters[index] = None
blanks = blanks[:index] + guessed_letter + blanks[index+1:]
print(blanks)
if letters == blanks:
print("gg")
break

Categories

Resources