This question already has answers here:
Convert letters to numbers
(5 answers)
Closed 1 year ago.
message = str(input())
for i in message:
if i == "a": i = 1
if i == "b": i = 2
print(i)
ect.
I am trying to create a code generator where the user inputs a string eg. "hello" and it is converted to a number code by assigning each letter a number, based on their position in the alphabet. 1 = a, 2 = b and so on. The method I am currently using is very long - are there other ways to do this to avoid this issues?
How can I print the answer together, without the numbers being on multiple lines eg. 1 2 3 21 19
Use string lib:
import string
[string.ascii_lowercase.index(s)+1 for s in 'hello'.lower()]
Output:
[8, 5, 12, 12, 15]
You could convert the letter to its ASCII code value, calculate its position, then add the position of the letter to the string and print the string.
To get the numeric value of a char, use the ord() method, to get a character from a numeric value, use the char() method.
Link to ASCII table
import string
low_letter = list(string.ascii_lowercase)
now you have a list of all letters in order
so...
message = str(input())
for i in message:
print(low_letter.index(i))
now you have the index
and in case you need the upper case :
upper_case = list(string.ascii_uppercase)
```
msg = str(input())
for char in msg:
print(ord(char) - ord('a') + 1)
The idea is to convert each character into ASCII using ord() in python and subtract it with the ASCII of 'a' and + 1
So consider "hello" string :
The output will be :
hello
8
5
12
12
15
Note : Here we subtract the ASCII of the character with the ASCII of character 'a' in order to get the correct Position as in Alphabetical order.
Eg : h
Ascii of h = 104
Ascii of a = 97
So our required answer = Ascii of h - Ascii of a + 1
= 104 - 97 + 1 = 8
And if we look the alphabetical order - a,b,c,d,e,f,g,h -> h is the 8th character
Hope this helps you. Thank you
Just create a dictionary that maps 'a' to 1, 'b' to 2, etc
from string import ascii_lowercase
mapping = dict(zip(ascii_lowercase, range(1, 27)))
And use it like this
numbers = [mapping[char] for char in message if char in mapping]
You need to check if each character is in the alphabet, otherwise you'll get an error. If you also want to cover the uppercase letters, change message to message.lower() in the loop line.
Using index() every iteration is inefficient, even though in this case it won't matter much because you're searching through at most 26 letters. But in general it's not a good strategy. Dictionary lookup is O(1).
Related
I mean like it is gonna ask me to type some string and ask me to type one letter and gives me position of it.
like "Hello"
i wanna letter e
it gives me position 2.
Thank you for answer
There are two ways I know of that you could use, one makes the string into a list, making it easier to iterate through, and the other just iterates through the string.
Option #1 (String):
string = 'Hello'
for char in string:
if char == 'e':
break <or whatever code you want here>
Option #2 (List):
def split(string):
return [char for char in string]
string = 'Hello'
for char in split(string):
if char == 'e':
break <or your code>
You can use the .find method.
string = input() # Gets the input from the user
character = input() # Gets another input from the user (the character)
index = string.find(character) # This function is going to return the index of character in string
print(index + 1)
It prints index + 1 because the index in python (actually most languages) starts at 0
Input:
Hello
e
Output:
2
I've been trying to tackle this problem but I haven't got any luck so far :( so any guidance would be awesome, especially since I'm just learning Python, so the problem is this:
Given a certain string, first you'll have to encode it using the following algorithm:
For every letter, strip the consecutive repetitions, if any, and add a number with the number of times it appears consecutively, including the first time.
After you've completed the encoding you'll have to create a function to decode it using the same criteria/assumptions.
Some examples of how it should work:
“Goooooooooddddd” => “G1o9d5”
“Oooo” => “O1o3”
“anagram” => “a1n1a1g1r1a1m1”
So far I have the following code for the encoding:
def encode(s) :
i = 0
while( i < len(s) - 1) :
count = 1
while s[i] == s[i + 1] :
i += 1
count += 1
if i + 1 == len(s):
break
print(str(s[i]) + str(count),
end = "")
i += 1
print()
# Code for the driver
if __name__ == "__main__" :
encode("Goooooooooddddd")
encode("Oooo")
With this I'm getting the needed output for the encoding part at least.
But I'm unable to actually do the "decoding" part by using this encoding as a starting point.
I know this question is quite silly/basic but I really can't get my head over it
Thanks in advance for the guidance/tips for this challenge problem
Decoding would be very simple in python since it allows character multiplication:
It might be like:
def decode(s):
a = list(s) # separate each character and number
i = 0
z = len(a)
while i < z-1: #This for block checks for any 2 digit numbers
print(i, a[i])
if a[i].isdigit() and a[i+1].isdigit():
a[i] = a[i]+a[i+1]
a.pop(i+1)
print(a)
z-=1
try:
if a[i+2].isdigit():
i-=1
except IndexError:
i-=1
i+=1
final_str = '' # the string that will have the value
for i in range(0, len(a), 2):
final_str += a[i]*int(a[i+1]) #a[i] is the character and int(a[i+1]) is the number of times.
# They are multiplied and then added to the final string
print(final_str) # The final string is printed
Thanks to #Tobi208 for pointing out the bug.
Decoding in pseudo code would involve:
Scan encoded string character by character
If character is alphabetic then add it to the decoded result
Sub scan encoded string for numeric sequence of 1 or more characters till next alphabetic character or end of string.
Repeat the last decoded string character this many times minus one.
Resume from step 1 till encoded string is entirely consumed.
Let's say I have a string a = 31 4 5 + + and a string b = 31 4 5 ++. I need to check that all numbers and operators in the string are delimited by at least one white space. Therefore, string a is correct, string b incorrect. c = 31 4 5+ + is also incorrect. Is there a way how to check for this? I could not come up with anything reasonable.
You can check it through following steps -
Break string into list using .split()
Check whether items in list whose length is more than 1 is numeric or not.
Code snippet:
def is_valid_string(st, delimiter = ' '):
lst = st.split(delimiter) # create list of chars separated by space
for item in lst:
if len(item) > 1 and not item.isdigit():
return False
return True
In case if you are considering float numbers you can use item.replace('.','',1).isdigit()
First thing to do would be splitting the strings by the whitespaces into "words", so something like words = a.split() (split's delimitor is a whitespace by default so no need for arguments)
I'm guessing you're only gonna use integers or floats and a set of operators like adding, substraction, multiplication and division, so one thing that you could do is check if you can cast the words into numbers with int or float and if you can't, check if the word is in your operators set, so something like:
a = "31 4 5 + +"
operators = ["+", "-", "*", "/"]
# Every string is valid by default
valid = True
words = a.split() # ["31", "4", "5", "+", "+"]
for word in words:
# try to cast word into a number
try:
float(word)
except:
# if you can't, check if it's an operator
if word not in operators:
valid = False #if it's not, the string isn't valid
if valid:
print("String is valid")
else:
print("String is not valid")
More complex stuff like equations and variables is obviously more difficult to code.
EDIT: python's isdigit() checks if a string is a number and it is more simple than a try block for casting the string, but it doesn't check for floats, which won't be valid. (you could still replace decimal points by numbers)
Try use regex ^((\d+|[+*/-])(\s+|$))+$. It matches more or more items, each of which is either a number (\d+) or an operator ([+*/-]), followed by either one or more spaces (\s+) or the end of string ($). The ^ at the beginning and ($) at the end force the regex match the whole string. Example:
>>> import re
>>> a = '31 4 5 + +'
>>> b = '31 4 5 ++'
>>> c = '31 4 5+ +'
>>> print(re.match(r'^((\d+|[+*/-])(\s+|$))+$', a))
<re.Match object; span=(0, 10), match='31 4 5 + +'>
>>> print(re.match(r'^((\d+|[+*/-])(\s+|$))+$', b))
None
>>> print(re.match(r'^((\d+|[+*/-])(\s+|$))+$', c))
None
I wanted to make a really small program that would convert the alphabet characters into ascii_values and vice versa but when it comes to incrementing the ascii value of the current character being processed an error is raised.
TypeError: ord() expected string of length 1, but int found
Here is the code (Just the part that gets the error)
def character_to_ascii_value(char):
print("The ASCII value of", char, "is:", ord(char))
character = "A"
for i in range(25):
character_to_ascii_value(character)
character = ord(character) + 1
PS: Searched it already but couldn't find out... (didn't get the other answers)
PS no2: I've found a solution but it's non pythonic... Converts this and that and back to adding it blah blah.. I think there must be something more simplistic
character = "A"
char_ascii = ord(character)
for i in range(25):
character_to_ascii_value(character)
char_ascii += 1
character = chr(char_ascii)
Shorter version
import string
for char in string.ascii_uppercase:
print("The ASCII value of", char, "is:", ord(char))
Original problem
Use chr() to convert the number into a string:
def character_to_ascii_value(char):
print("The ASCII value of", char, "is:", ord(char))
character = "A"
for i in range(25):
character_to_ascii_value(character)
character = chr(ord(character) + 1)
Output:
The ASCII value of A is: 65
The ASCII value of B is: 66
The ASCII value of C is: 67
The ASCII value of D is: 68
The ASCII value of E is: 69
The ASCII value of F is: 70
You have to convert back from the ASCII number to a char. Replace the last line with
character = chr(ord(character) + 1)
After much frustration, I have made my first Caesar Decoder :)
But the problem now is to make the program circular...
For example if we want to shift doge by 1, no problem, it's ephf...
But what about xyz, and the shift was 4???
So programming pros help a first time novice aka newb out :P
Thanks...
import string
def main():
inString = raw_input("Please enter the word to be "
"translated: ")
key = int(raw_input("What is the key value? "))
toConv = [ord(i) for i in inString] #now want to shift it by key
toConv = [x+key for x in toConv]
#^can use map(lambda x:x+key, toConv)
result = ''.join(chr(i) for i in toConv)
print "This is the final result due to the shift", result
Here is Python code that I wrote to be easy to understand. Also, I think the classic Caesar cipher didn't define what to do with punctuation; I think the classic secret messages were unpunctuated and only contained letters. I wrote this to only handle the classic Roman alphabet and pass any other characters unchanged.
As a bonus, you can use this code with a shift of 13 to decode ROT13-encoded jokes.
def caesar_ch(ch, shift):
"""
Caesar cipher for one character. Only shifts 'a' through 'z'
and 'A' through 'Z'; leaves other chars unchanged.
"""
n = ord(ch)
if ord('a') <= n <= ord('z'):
n = n - ord('a')
n = (n + shift) % 26
n = n + ord('a')
return chr(n)
elif ord('A') <= n <= ord('Z'):
n = n - ord('A')
n = (n + shift) % 26
n = n + ord('A')
return chr(n)
else:
return ch
def caesar(s, shift):
"""
Caesar cipher for a string. Only shifts 'a' through 'z'
and 'A' through 'Z'; leaves other chars unchanged.
"""
return ''.join(caesar_ch(ch, shift) for ch in s)
if __name__ == "__main__":
assert caesar("doge", 1) == "ephf"
assert caesar("xyz", 4) == "bcd"
assert caesar("Veni, vidi, vici.", 13) == "Irav, ivqv, ivpv."
The part at the end is a "self-test" for the code. If you run this as a stand-alone program, it will test itself, and "assert" if a test fails.
If you have any questions about this code, just ask and I'll explain.
Just add the key to all the actual character codes, then if the added value is greater than z, modulo with character code of z and add it with the character code of a.
inString, key = "xyz", 4
toConv = [(ord(i) + key) for i in inString] #now want to shift it by key
toConv = [(x % ord("z")) + ord("a") if x > ord("z") else x for x in toConv]
result = ''.join(chr(i) for i in toConv)
print result # cde
I'd recommend using string.translate().
So, we can do the following:
key = 1
table = string.maketrans(string.ascii_lowercase + string.ascii_uppercase, string.ascii_lowercase[key:] + string.ascii_lowercase[:key] + string.ascii_uppercase[key:] + string.ascii_uppercase[:key])
And then we can use it as follows:
'doge'.translate(table) # Outputs 'ephf'
'Doge'.translate(table) # Outputs 'Ephf'
'xyz'.translate(table) # Outputs 'yza'
In particular, this doesn't change characters that are not ascii lowercase or uppercase characters, like numbers or spaces.
'3 2 1 a'.translate(table) # Outputs '3 2 1 b'
in general, to make something "wrap" you use the modulo function (% in Python) with the number you want to wrap, and the range you want it to wrap in. For example, if I wanted to print the numbers 1 through 10 a bajillion times, I would do:
i = 0
while 1:
print(i%10+1)
# I want to see 1-10, and i=10 will give me 0 (10%10==0), so i%10+1!
i += 1
In this case it's a little more difficult because you're using ord, which doesn't have a nice happy "range" of values. If you had done something like string.ascii_lowercase you could do...
import string
codex = string.ascii_lowercase
inString = "abcdxyz"
key = 3
outString = [codex[(codex.index(char)+key)%len(codex)] for char in inString]
However since you're using ord, we're kind of going from ord('A') == 65 to ord('z')==122, so a range of 0 -> 57 (e.g. range(58), with a constant of 65. In other words:
codex = "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz"
# every char for chr(65) -> chr(122)
codex = ''.join([chr(i+65) for i in range(58)]) # this is the same thing!
we can do this instead, but it WILL include the characters [\]^_`
inString, key = 'abcxyzABCXYZ', 4
toConv = [(ord(i)+key-65)%58 for i in inString]
result = ''.join(chr(i+65) for i in toConv)
print(result)
# "efgBCDEFG\\]^"
I know this is kind of an old topic, but I just happened to be working on it today. I found the answers in this thread useful, but they all seemed to use a decision to loop. I figured a way to accomplish the same goal just using the modulus(remainder) operator (%). This allows the number to stay within the range of a table and loop around. It also allows for easy decoding.
# advCeaser.py
# This program uses a ceaser cypher to encode and decode messages
import string
def main():
# Create a table to reference all upper, lower case, numbers and common punctuation.
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz1234567890,.!?-#'
print 'This program accepts a message and a key to encode the message.'
print 'If the encoded message is entered with the negative value of the key'
print 'The message will be decoded!'
# Create accumulator to collect coded message
code =''
# Get input from user: Message and encode key
message = raw_input('Enter the message you would like to have encoded:')
key = input('Enter the encode or decode key: ')
# Loop through each character in the message
for ch in message:
# Find the index of the char in the table add the key value
# Then use the remainder function to stay within range of the table.
index = ((table.find(ch)+key)%len(table))
# Add a new character to the code using the index
code = code + table[index]
# Print out the final code
print code
main()
The encode and decode output look like this.
encode:
This program accepts a message and a key to encode the message.
If the encoded message is entered with the negative value of the key
The message will be decoded!
Enter the message you would like to have encoded:The zephyr blows from the east to the west!
Enter the encode or decode key: 10
croj0ozr92jlvy73jp2ywj4rojok34j4yj4roj7o34G
decode:
This program accepts a message and a key to encode the message.
If the encoded message is entered with the negative value of the key
The message will be decoded!
Enter the message you would like to have encoded:croj0ozr92jlvy73jp2ywj4rojok34j4yj4roj7o34G
Enter the encode or decode key: -10
The zephyr blows from the east to the west!
Sorry if my formatting looks catywompus I literally found stackoverflow yesterday! Yes, I literally mean literally :)