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.
Related
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 : :]
I have a list here where I only need to input 10 letters or strings. I am having a problem separating the list.
print ("Please input letter: \n")
num_string = []
num = 10
for i in range (0,num):
element = str(input(str(i + 1) + ". "))
num_string.append(element)
string = ' '.join([str(item) for item in num_string])
print (string)
In my code, for example, I inputted a b c d e f g h i j since it is only 10 inputs. Instead of having an output like a b c d e f g h i j because I used the join method, I want to have a NewLine for every list. So I want it to be like
a
b
c
d
e
f
g
h
i
j
You are almost there just instead of joining a whitespace, join a newline, also you don't need to convert each element to string because each element is a string already because input always returns a string (in Python3) (so this is redundant: str(input()), it is the exact same as: input()):
string = '\n'.join(num_string)
Complete example (removed the redundant str):
print("Please input letter: \n")
num_string = []
num = 10
# the 0 isn't necessary either but
# I guess for clarification it can stay
for i in range(0, num):
element = input(str(i + 1) + ". ")
num_string.append(element)
string = '\n'.join(num_string)
print(string)
Alternatively you can use this (instead of the last two lines in the above code example):
print(*num_string, sep='\n')
And if you really want to shorten the code (it can be as short as 3 lines):
print("Please input letter: \n")
num = 10
print('\n'.join(input(f'{i + 1}. ') for i in range(num)))
print ("Please input letter: \n")
num_string = []
num = 10
for i in range (0,num):
element = str(input(str(i + 1) + ". "))
num_string.append(element)
string = '\n' .join([str(item) for item in num_string])
print (string)
Use '\n' , it is like a breakline in your output
I'm trying to code a chatbot that will print a string containing n times the first letter of my name, followed by "n" and then followed by n-1 times the second letter in my name.
Example:
name: chris
n = 5 (since there are 5 letters in the name)
n-1 = 4
first letter of the name: c
second letter of the name: h
The string I want to generate: ccccc5hhhh
My problem: The string generated is in brackets which I don't want. I want the string to be exactly as "ccccc5hhhh", no spaces; all in one line, but I keep getting ['c','c','c','c','c']5['h','h','h','h'] as the output.
st1 = input("First name? ==> ")
print("Please enter the first letter of your name")
letter = input ("First letter? ==>? ")
if (letter == st1[0]):
# initializing list of lists
test_list = st1[0]
test_list1 = st1[1]
# repeat letters n times
res = [ele for ele in test_list for i in range(len(st1))]
res2 = [ele for ele in test_list1 for i in range(len(st1)-1)]
# printing result
print(str(res), len(st1), str(res2))
You are looking for the join function. Using , with your arguments will insert a space though.
To get the result you are looking for you will want:
print(''.join(res) + str(len(st1)) + ''.join(res2))
Instead of converting your lists into string you can use the .join() function, like so ''.join(res)
So you final line should be:
print(''.join(res) + str(len(st1)) + ''.join(res2))
You're overcomplicating this. Just use string multiplication.
s = 'chris'
n = len(s)
res1 = s[0] * n
res2 = s[1] * (n - 1)
print(res1 + str(n) + res2) # -> ccccc5hhhh
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))
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.