Entering more than 1 shift amount in a program - python

Hi I'm having a tough time trying to incorporate more than 1 shift in my program. The goal is to assign a shift amount to each character like:
statement = input("Enter string: ")
shift = input("Enter shift amounts: ")
For example, if
statement = "Hello"
shift = 5 6 7
How do I assign that 5 number to H, 6 to E, 7 to l, then again 5 to l, and 7 to o
I think that I need to make it into a list so this is what I have thus far:
for char in statement:
char[0] = shift[0]

Try this:
#!/usr/bin/python
statement = raw_input("Enter string: ")
shift = raw_input("Enter shift amounts: ").split()
for index, char in enumerate(statement):
if index < len(shift):
print chr(ord(char) + int(shift[index])),
else:
print char,
Written for Python 2, and doesn't do error checking on user input, but should work.
Edit: And a Python3 version, since it looks like that's what you're using:
#!/usr/bin/python
statement = input("Enter string: ")
shift = input("Enter shift amounts: ").split()
for index, char in enumerate(statement):
if index < len(shift):
print(chr(ord(char) + int(shift[index])), end='')
else:
print(char, end='')
print()
In both versions, if the number of integers provided by the user for shift is less than the size of the string, a shift value of 0 is assumed.
If you wanted to, you could do a test to see if the number of shift integers provided by the user is less than the length of the string, and error out, or ask the user for input again.
Edit 2: As requested in comments, this code makes the shift restart instead of assuming it is 0:
#!/usr/bin/python
statement = input("Enter string: ")
shift = input("Enter shift amounts: ").split()
for index, char in enumerate(statement):
index = index % len(shift)
print(chr(ord(char) + int(shift[index])), end='')
print()
Edit 3: As requested in comments, this code makes sure user input is only a-z or A-Z, and is in a function.
#!/usr/bin/python
import sys
from string import ascii_letters as alphabet
def enc_string(statement, shift):
# Make sure user entered valid shift values
try:
shift = [ int(val) for val in shift.split() ]
except ValueError:
print("Error: All shift values must be integers")
sys.exit(1)
# Make sure all chars in statement are valid
for char in statement:
if char not in alphabet:
print("Error: all characters in string must be a-z or A-Z")
sys.exit(1)
# Start putting together result
res = "Result: "
# Convert statement
for index, char in enumerate(statement):
shift_to_use = shift[index % len(shift)]
index_of_char = alphabet.index(char)
index_of_new_char = (index_of_char + shift_to_use) % len(alphabet)
res += alphabet[index_of_new_char]
return res
statement = input("Enter string: ")
shift = input("Enter shift amounts: ")
print(enc_string(statement, shift))

Related

Return values from dictionary?

I am having a lot of trouble understanding this problem. I need to enter a string in the format of 2X+4Y (e.g number + letter, can be two letters such as HE, +number + letter
if the input value is 2X+4Y Then return the value should be x2y4. The values need to be distinct and need to match the dictionary symbol and be positive integers.
#enter a string in form xA + yB +zC
#x, y, z are postive integers
#A,B,C are distinct symbols of elements (2H + 1O + 1C)
symbol = {"H":1,"He":4, "Li":7, "Be":9, "B":11, "C":12, "N":14, "O":16, "F":19, "Ne":20}
def stoi_coefficent(final_input): # this will only work when letter inputs are 'H', 'O' rather than 'HE'
output=[]
for i in final_input:
output+= i[1::2]
output+=i[0: :2]
print(output)
return output
def Convert(output):
output_dct = {output[i]: output[i + 1] for i in range(0, len(output), 2)}
print(output_dct)
return output_dct
def check_if_in_symbol(output):
active = True
while active:
for i in output:
if i not in symbol or i not in numbers:
print('enter another symbol or number')
else:
active=False
continue
a = (stoi_coefficent(final_input))
print(output)
print(Convert(output))
b = (check_if_in_symbol(a))
while True:
user_input = input('\nEnter a string in the format of xA + yB + zC: ') # "4Ne + 1Be + 2Li"
split_str = user_input.replace(" ", "").split("+")
try:
pairs = [str_parser(userstr) for userstr in split_str]
check_elements(pairs)
except ValueError:
continue
final_result = swap(pairs)
print(f"Final Result: {final_result}")
break
I have tried various other ideas but I think I need to make the input into a dictionary. But how do I make a dictionary when the split function makes a list in the format of [2x,4y]
and how would I use a comparative operator when the numbers and letters are one list item?
Based on your recent comments, you should edit your question to be something like this:
Question
I want to take input from the user in the form of xA + yB + zC.
And I want an output like this AxByCz.
They should be able to enter any number of combinations.
If x, y, or z are 1, I want to exclude them.
For example:
4Ne + 1Be + 2Li
Ne4BeLi2
If the first number of every element isn't a positive integer or the element isn't a key in the SYMBOLS dict below, I want to print an error message and have the user try again.
SYMBOLS = {"H":1,"He":4, "Li":7, "Be":9, "B":11, "C":12, "N":14, "O":16, "F":19, "Ne":20}
Here's what I tried:
My code here
Problem I'm having here.
Answer
If you can't use other modules, you'll need to make your own string parser.
There are many different ways to do it, but here's one way, including a loop that starts over whenever the user enters invalid input:
SYMBOLS = {"H":1,"He":4, "Li":7, "Be":9, "B":11, "C":12, "N":14, "O":16, "F":19, "Ne":20}
def str_parser(userstr):
if not userstr:
print("Empty string detected. Please try again.")
raise ValueError()
first_char = userstr[0]
if not first_char.isdigit():
print(f"First digit of element must be a positive integer: {userstr}. Please try again.")
raise ValueError()
index = 1
lastindex = 1
digits = []
char = first_char
while char.isdigit():
digits.append(char)
try:
next_char = userstr[index]
except IndexError:
break
else:
char = next_char
lastindex = index
index += 1
coefficent = "".join(digits)
return coefficent, userstr[lastindex:]
def check_elements(pairs):
for _, element in pairs:
if element.capitalize() not in SYMBOLS:
print(f"Element not recognized: {element}. Please try again.")
raise ValueError()
def swap(pairs):
final_str = ""
for coeff, element in pairs:
if int(coeff) < 2:
final_str += element
else:
final_str += element+coeff
return final_str
while True:
user_input = input('\nEnter a string in the format of xA + yB + zC: ') # "4Ne + 1Be + 2Li"
split_str = user_input.replace(" ", "").split("+")
try:
pairs = [str_parser(userstr) for userstr in split_str]
check_elements(pairs)
except ValueError:
continue
final_result = swap(pairs)
print(f"Final Result: {final_result}")
break
# Ne4BeLi2
You can split the input as you do (user_input.split('+')), then apply this to each element in the list to split numbers from letters.
Product code looks like abcd2343, how to split by letters and numbers?
You then have the symbols and numbers which you can check for validity separately.

How to ask for a string, then ask for a position of string, then remove the letter and print the word without the letter

Python
I want to create a program that asks the user for a string, then asks the user to select a position of the string to be removed, and then print the string without the letter of the position he chose to be removed. I'm struggling to find the correct way to do that.
x = input ('Enter a String: ')
sum = 0
if type(x) != str:
print ('Empty Input')
else:
y = input ('Enter the position of the string to be removed: ')
for i in range x(start, end):
print ('New string is: ', x - i)
The easiest way to achieve this is to use slice notation, and just leave out the character in the specified position:
x = input ('Enter a String: ')
if type(x) != str:
print ('Empty Input')
else:
y = int(input('Enter the position of the string to be removed: ')) or 1
print(x[:y-1] + x[y:])
x = "abcdefgh"
abcefgh
Essentially how you can do this is simply using the .split() method to split it by the index of the string letter and join it with the join() method
x = input ('Enter a String: ')
sum = 0
if type(x) != str:
print ('Empty Input')
else:
y = int(input('Enter the position of the string to be removed: '))
x = ''.join([''.join(x[:y]), ''.join(x[y+1:])])
print(x)
The following part is unnecessary:
if type(x) != str:
print ('Empty Input')
As whatever comes from input builtin is always going to be a string.
The modified version of your code:
text = input('Enter a String: ')
if text == '':
print('Empty string')
else:
pos = int(input('Enter the position of the string to be removed: '))
print(text[:pos] + text[pos+1:]) # TO remove value at given index
print(text[pos+1:]) # TO remove everything bofore the given index
SAMPLE RUN:
Enter a String: >? helloworld
Enter the position of the string to be removed: >? 4
hellworld
world
Does this link help?
Excerpt from said page:
strObj = "This is a sample string"
index = 5
# Slice string to remove character at index 5
if len(strObj) > index:
strObj = strObj[0 : index : ] + strObj[index + 1 : :]

Python how to convert character to string

array = "qwertyuiopasdfghjklzxcvbnm"
m = len(array)
user_input= input("Enter plaintext: ")
a= int(input("choose a: "))
b= int(input("choose b: "))
encryption = ""
for n in array:
if n in user_input :
inin=array.find(n)
result =array.index(user_input) * a+b
enc= result % m
encryption = encryption + array[enc]
print("Encrypted message is :"+encryption)
as you can see from the code above my code worked fine but the only problem that I am facing is
I need to encrypt the message as string like I want to use " hello world" not only a character "s" and its encrypted to " d" i want "hello word"
I tried to correct your code:
array = "qwertyuiopasdfghjklzxcvbnm"
m = len(array)
user_input= input("Enter plaintext: ")
a= int(input("choose a: "))
b= int(input("choose b: "))
encryption = ""
for char in user_input:
if char in array :
index = (array.find(char) * a + b) % m
encryption += array[index]
else:
encryption += char
print("Encrypted message is :", encryption)
From what I understood, you are trying to encrypt your message by shifting the index using an affine function (and applying a modulo so it "loops" if the index is bigger than your alphabet size). Since your input can contain multiple times the same char, you need to iterate through the input and then check for the index of every char in your alphabet (array). Then you can apply your formula to the index and get the new char. I also added a code to add the unciphered char if it doesn't exist in your array. This will prevent you to lose informations when ciphering.
e.g.: hello world will be ciphered in xirrm tmars instead of xirrmtmars which couldn't be unciphered to get the original.

Rc4 decrypt ValueError: Unknown format code 'x' for object of type 'str'

When I get to the following line in my code, I receive the following error:
inputString = "{:02x}".format(inputNumber)
ValueError: Unknown format code 'x' for object of type 'str'
How can I avoid this?
# Global variables
state = [None] * 256
p = q = None
def setKey(key):
##RC4 Key Scheduling Algorithm
global p, q, state
state = [n for n in range(256)]
p = q = j = 0
for i in range(256):
if len(key) > 0:
j = (j + state[i] + key[i % len(key)]) % 256
else:
j = (j + state[i]) % 256
state[i], state[j] = state[j], state[i]
def byteGenerator():
##RC4 Pseudo-Random Generation Algorithm
global p, q, state
p = (p + 1) % 256
q = (q + state[p]) % 256
state[p], state[q] = state[q], state[p]
return state[(state[p] + state[q]) % 256]
def encrypt(key,inputString):
##Encrypt input string returning a byte list
setKey(string_to_list(key))
return [ord(p) ^ byteGenerator() for p in inputString]
def decrypt(inputByteList):
##Decrypt input byte list returning a string
return "".join([chr(c ^ byteGenerator()) for c in inputByteList])
def intToList(inputNumber):
##Convert a number into a byte list
inputString = "{:02x}".format(inputNumber)
return [(inputString[i:i + 2], 16) for i in range(0, len(inputString), 2)]
def string_to_list(inputString):
##Convert a string into a byte list
return [ord(c) for c in inputString]
loop = 1
while loop == 1: #simple loop to always bring the user back to the menu
print("RC4 Encryptor/Decryptor")
print
print("Please choose an option from the below menu")
print
print("1) Encrypt")
print("2) Decrypt")
print
choice = input("Choose your option: ")
choice = int(choice)
if choice == 1:
key = input("Enter Key: ")
inputstring = input("enter plaintext: ")
print(encrypt(key, inputstring))
elif choice == 2:
key = input("Enter Key: ")
ciphertext = input("enter plaintext: ")
print(decrypt(intToList(ciphertext)))
elif choice == 3:
#returns the user to the previous menu by ending the loop and clearing the screen.
loop = 0
else:
print ("please enter a valid option") #if any NUMBER other than 1, 2 or 3 is entered.
The format string code x converts an integer to its hexadecimal representation as a string. For example:
>>> "{:02x}".format(54563)
'd523'
The error you are getting occurs when you pass a string as inputNumber. Arguments passed to your intToList function should be integers. Consider using intToList(int(your_argument_here)).
It looks like you’re trying to convert a string to hex. Unfortunately that’s not the way to do it: "{:02x}".format is for formatting a single integer, so it doesn’t work for a whole string.
Python 3 includes the method bytes.hex() which performs this transformation for you, but you’ll need a byte string rather than a normal string. You can use string encoding to convert from str to bytes.
If you wanted to do the transformation yourself, you could call "{:02x}".format on the character codes of each character in your string, and concatenate the individual hex values together. Be careful with Unicode in this case; you might be better off working with a byte string.

Convert a number into its respective letter in the alphabet - Python 2.7

I am currently working on a python project to take a string of text, encrypt the text by adding a keyword to it and then outputting the result. I currently have all the features of this program operational except converting the numerical value back into text.
For example, the raw text will be converted into a numerical value, for instance [a, b, c] will become [1, 2, 3].
Currently I have no ideas of how to correct this issue and would welcome any help, my current code is as follows:
def encryption():
print("You have chosen Encryption")
outputkeyword = []
output = []
input = raw_input('Enter Text: ')
input = input.lower()
for character in input:
number = ord(character) - 96
output.append(number)
input = raw_input('Enter Keyword: ')
input = input.lower()
for characterkeyword in input:
numberkeyword = ord(characterkeyword) - 96
outputkeyword.append(numberkeyword)
first = output
second = outputkeyword
print("The following is for debugging only")
print output
print outputkeyword
outputfinal = [x + y for x, y in zip(first, second)]
print outputfinal
def decryption():
print("You have chosen Decryption")
outputkeyword = []
output = []
input = raw_input('Enter Text: ')
input = input.lower()
for character in input:
number = ord(character) - 96
output.append(number)
input = raw_input('Enter Keyword: ')
input = input.lower()
for characterkeyword in input:
numberkeyword = ord(characterkeyword) - 96
outputkeyword.append(numberkeyword)
first = output
second = outputkeyword
print("The following is for debuging only")
print output
print outputkeyword
outputfinal = [y - x for x, y in zip(second, first)]
print outputfinal
mode = raw_input("Encrypt 'e' or Decrypt 'd' ")
if mode == "e":
encryption()
elif mode == "d":
decryption()
else:
print("Enter a valid option")
mode = raw_input("Encrypt 'e' or Decrypt 'd' ")
if mode == "e":
encryption()
elif mode == "d":
decryption()
Although Your Question is not quite clear I wrote a script which do encryption using Dictionary
plaintext = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ') #Alphabet String for Input
Etext = list('1A2B3C4D5E6F7G8H90IJKLMNOP') """Here is string combination of numbers and alphabets you can replace it with any kinda format and your dictionary will be build with respect to the alphabet sting"""
def messageEnc(text,plain, encryp):
dictionary = dict(zip(plain, encryp))
newmessage = ''
for char in text:
try:
newmessage = newmessage + dictionary[char.upper()]
except:
newmessage += ''
print(text,'has been encryptd to:',newmessage)
def messageDec(text,encryp, plain):
dictionary = dict(zip(encryp,plain))
newmessage = ''
for char in text:
try:
newmessage = newmessage + dictionary[char.upper()]
except:
newmessage += ''
print(text,'has been Decrypted to:',newmessage)
while True:
print("""
Simple Dictionary Encryption :
Press 1 to Encrypt
Press 2 to Decrypt
""")
try:
choose = int(input())
except:
print("Press Either 1 or 2")
continue
if choose == 1:
text = str(input("enter something: "))
messageEnc(text,plaintext,Etext)
continue
else:
text = str(input("enter something: "))
messageDec(text,Etext,plaintext)
Suppose you've got a list of numbers like a = [1, 2, 3] and an alphabet: alpha = "abcdef". Then you convert this as follows:
def NumToStr(numbers, alpha):
ret = ""
for num in numbers:
try:
ret += alpha[num-1]
except:
# handle error
pass
return ret
Going by your question , you want to convert number back to text.
You can have two list declared for both the number and alphabet, such as:
num=[1,2,3....26]
alpa=['a','b','c'....'z']
and after that find the index/position from the num list and find the alphabet for that index in alpa list.
A couple of things. The first is to convert the coded values back to characters you can use the chr(i) command. Just remember to ad the 96 back on.
for code in outputfinal:
print chr(code + 96),
I tried 'aaa' as my plaintext and 'bbb' as my keyword and this printed 'ccc' which is what I think you are trying to do.
Another thing. The zip command iterates over two lists but (in my playing) only until one of the lists runs out of members. If your plaintext is 10 characters and your keyword is only 5 then only the first 5 characters of your plaintext get encrypted. You will need to expand or inflate your key to the length of your plaintext message. I played with something like this:
plaintext = ['h','e','l','l','o',' ','w','o','r','l','d']
keyword = ['f','r','e','d']
index = len(keyword) # point to the end of the key word
keyLength = len(keyword)
while index < len(plaintext): # while there are still letters in the plain text
keyword.append(keyword[index - keyLength]) # expand the key
index += 1
print keyword
for a,b in zip(plaintext, keyword):
print a, b
I hope this helps. Please let me know if I have misunderstood.

Categories