I want to convert a single character of a string into an integer, add 2 to it, and then convert it back to a string. Hence, A becomes C, K becomes M, etc.
This is done through the chr and ord functions. Eg; chr(ord(ch)+2) does what you want. These are fully described here.
This sounds a lot like homework, so I'll give you a couple of pieces and let you fill in the rest.
To access a single character of string s, its s[x] where x is an integer index. Indices start at 0.
To get the integer value of a character it is ord(c) where c is the character. To cast an integer back to a character it is chr(x). Be careful of letters close to the end of the alphabet!
Edit: if you have trouble coming up with what to do for Y and Z, leave a comment and I'll give a hint.
Normally, Just ord and add 2 and chr back, (Y, Z will give you unexpected result ("[","\")
>>> chr(ord("A")+2)
'C'
If you want to change Y, Z to A, B, you could do like this.
>>> chr((ord("A")-0x41+2)%26+0x41)
'C'
>>> chr((ord("Y")-0x41+2)%26+0x41)
'A'
>>> chr((ord("Z")-0x41+2)%26+0x41)
'B'
Here is A to Z
>>> [chr((i-0x41+2)%26+0x41) for i in range(0x41,0x41+26)]
['C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'A', 'B']
http://docs.python.org/library/functions.html
ord(c)
Given a string of length one, return an integer representing the Unicode code point of the character when the argument is a unicode object, or the value of the byte when the argument is an 8-bit string. For example, ord('a') returns the integer 97, ord(u'\u2020') returns 8224. This is the inverse of chr() for 8-bit strings and of unichr() for unicode objects. If a unicode argument is given and Python was built with UCS2 Unicode, then the character’s code point must be in the range [0..65535] inclusive; otherwise the string length is two, and a TypeError will be raised.
"ord" is only part of the solution. The puzzle you mentioned there rotates, so that "X"+3 rotates to "A". The most famous of these is rot-13, which rotates 13 characters. Applying rot-13 twice (rotating 26 characters) brings the text back to itself.
The easiest way to handle this is with a translation table.
import string
def rotate(letters, n):
return letters[n:] + letters[:n]
from_letters = string.ascii_lowercase + string.ascii_uppercase
to_letters = rotate(string.ascii_lowercase, 2) + rotate(string.ascii_uppercase, 2)
translation_table = string.maketrans(from_letters, to_letters)
message = "g fmnc wms bgblr"
print message.translate(translation_table)
Not a single ord() or chr() in here. That's because I'm answering a different question than what was asked. ;)
Try ord(), should do the trick :)
For a whole string this would be:
>>> s = "Anne"
>>> ''.join([chr(ord(i)+2) for i in s])
'Cppg'
It's diffucult for 'Y', 'Z' ...
>>> s = "Zappa"
>>> ''.join([chr(ord(i)+2) for i in s])
'\\crrc'
Functions: chr, ord
For those who need to perform the operation on each character of the string, another way of handling this is by converting the str object to/from a bytes object which will take advantage of the fact that a bytes object is just a sequence of integers.
import numpy
old_text_str = "abcde" # Original text
old_num_list = list(old_text_str.encode()) # Integer values of the original text
new_num_list = numpy.add(old_num_list, 2).tolist() # Add +2 to the integer values
new_text_str = bytes(new_num_list).decode() # Updated text
print(f"{old_text_str=}")
print(f"{old_num_list=}")
print(f"{new_num_list=}")
print(f"{new_text_str=}")
Output:
old_text_str='abcde'
old_num_list=[97, 98, 99, 100, 101]
new_num_list=[99, 100, 101, 102, 103]
new_text_str='cdefg'
Related topics:
How do I convert a list of ascii values to a string in python?
How can I convert a character to a integer in Python, and viceversa?
How to add an integer to each element in a list?
Related
I am trying to 'recreate' the str.split() method in python for fun.
def ourveryownstrip(string, character):
newString = [n for n in string if n != character]
return newString
print("The string is", ourveryownstrip(input("Enter a string.`n"), input("enter character to remove`n")))
The way it works is that I create a function that passes in two arguments: 1) the first one is a string supplied, 2) the second is a a string or char that the person wants to remote/whitespace to be moved from the string. Then I use a list comprehension to store the 'modified' string as a new list by using a conditional statement. Then it returns the modified string as a list.
The output however, returns the entire thing as an array with every character in the string separated by a comma.
Expected output:
Boeing 747 Boeing 787
enter character to removeBoeing
The string is ['B', 'o', 'e', 'i', 'n', 'g', ' ', '7', '4', '7', ' ', 'B', 'o', 'e', 'i', 'n', 'g', ' ', '7', '8', '7']
How can I fix this?
What you have set up is checking each individual character in a list and seeing if it matches 'Boeing' which will never be true so it will always return the whole input. It is returning it as a list because using list comprehension makes a list. Like #BrutusForcus said this can be solved using string slicing and the string.index() function like this:
def ourveryownstrip(string,character):
while character in string:
string = string[:string.index(character)] + string[string.index(character)+len(character):]
return string
This will first check if the value you want removed is in your string. If it is then string[:string.index(character)] will get all of the string before the first occurrence of the character variable value and string[string.index(character)+len(character):] will get everything in the string after the first occurrence of the variable value. That will keep happening until the variable value doesn't occur in the string anymore.
I am able to do recognition of car license plate and extract the plate values. Sometimes, the results are inaccurate as i am using OCR to do the recognition. I uses a checksum to ensure only the correct results are being printed and viewed. After the calculation for the checksum, I need to use another formula to get the last letter of the plate. match with these 19 letter, A=0, Z=1, Y=2, X=3, U=4, T=5, S=6, R=7, P=8, M=9, L=10, K=11, J=12, H=13, G=14, E=15, D=16, C=17, B=18. Is there any way i can use a loop to like declare the values of this letters instead of doing it one by one manually? Please help out. Thank you.
You can use a list and perform the lookups according to your needs.
The list looks like this:
plate_letter_list = ['A', 'Z', 'Y', 'X', 'U', 'T', 'S', 'R', 'P', 'M', 'L', 'K', 'J', 'H', 'G', 'E', 'D', 'C', 'B']
Case 1: Lookup value from letter
If you need to find the numeric value associated with a letter, use the index method:
letter = 'T'
print(plate_letter_list.index(letter))
>> 5
Case 2: Lookup letter from value
If you need to find the letter associated with a numeric value, use it as index:
value = 13
print(plate_letter_list[value])
>> H
There are two ways to search for these values. One of it is to use the List datatype like #sal provided. The other way is to use Dictionary datatype
**
Solution using List Datatype
**
pl_vals_list = ['A', 'Z', 'Y', 'X', 'U', 'T', 'S', 'R', 'P', 'M', 'L', 'K', 'J', 'H', 'G', 'E', 'D', 'C', 'B']
You can then do a lookup either by position or by value
To search by position, will provide you the value you assigned to the alphabet.
print(pl_vals_list[0]). This will result in A.
Alternatively, you can search by the alphabet itself. In this case, you have to use the index() function.
print(pl_vals_list.index('A')). This will result in the assigned number you gave to the alphabet. The result will be 0
This provides you a means to look-up based on alphabet or value.
You can also check if the alphabet is inside the list using:
if 'A' in pl_vals_list:
#then do something for value A
elif 'B' in pl_vals_list:
#then do something for value B
else:
#then do something
You can also iterate through the list using a for loop and enumerate. However, I don't know if that will be of value to you.
for i, v in enumerate(pl_vals_list):
#do something with each value in the list
#here i will store the index, and v will have the value - A, B, C, etc
You can get the value of each of these and determine what you want to do.
**
Solution using Dictionary Datatype
**
Similarly, you can do the same using a dictionary.
pl_vals_dict = {'A':0, 'Z':1, 'Y':2, 'X':3, 'U':4, 'T':5, 'S':6, 'R':7, 'P':8, 'M':9, 'L':10, 'K':11, 'J':12, 'H':13, 'G':14, 'E':15, 'D':16, 'C':17, 'B':18}
To look for alphabets within a dictionary, you can use
if 'A' in pl_vals_dict.keys():
#then do something for value A
elif 'A' in pl_vals_dict.keys():
#then do something for value B
else:
#do something else
An alternate way to check for something would be:
x = True if 'F' in pl_vals_dict.keys() else False
In this case x will have a value of False
You can also use the get() function to get the value.
x = pl_vals_dict.get('A') # OR
print (pl_vals_dict.get('A')
The simplest way to look up a dictionary value is:
print (pl_vals_dict['A'])
which will result in 0
However, you have to be careful if you try to print value of 'F', it will throw an error as 'F' is not part of the key value pair within the dictionary.
print (pl_vals_dict['F'])
this will give you the following error:
Traceback (most recent call last):
File "<pyshell#48>", line 1, in <module>
pl_vals_dict['F']
KeyError: 'F'
Similar to list, you can also iterate through the dictionary for keys and values. Not sure if you will need to use this but here's an example for you.
for k, v in pl_vals_dict.items():
#do something with each pair of key and value
#here k will have the keys A Z Y X ....
#and v will have the values 1, 2, 3, 4, ....
I have the following string:
Customer sale 88% in urm 50
Quoted with urllib.parse.quote, it becomes:
Customer%20sale%2088%25%20in%20urm%2050%27
Then I need to limit its length to a maximum of 30 characters and I use value[:30].
The problem is that it becomes "Customer%20sale%2088%25%20in%" which is not valid:
The last % is part of %20 from quoted string and makes it an invalid quoted string.
I don't have control over the original string, and the final result needs to have a maximum 30 length, so I can't truncate it beforehand.
What approach would be feasible?
urllib.quote uses percent-encoding as defined in RFC 3986. This means that encoded character will always be of the form "%" HEXDIG HEXDIG.
So you simply can delete any trailing rest of the encoding by looking for a % sign in the last two characters.
For example:
>>> s=quote("Customer sale 88% in urm 50")[:30]
>>> n=s.find('%', -2)
>>> s if n < 0 else s[:n]
'Customer%20sale%2088%25%20in'
What about looking for dangling percentage marks?
value = value[:30]
if value[-1] == "%":
value = value[:-1]
elif value[-2] == "%":
value = value[:-2]
print(value)
The encoded string will be always in the format of %HH. You want the string length to be maximum of 30characters with a valid encoding. So, probably the best solution I can think of:
from urllib.parse import quote
string= "Customer sale 88% in urm 50"
string=quote(string)
string=string[:string[:30].rfind("%")]
print(string)
Output:
string=string[:string[:30].rfind("%")]
Solution:
After the encoding, you may get a string of any length, the following one line of code will be enough to achieve your requirement in a very optimized way.
string=string[:string[:30].rfind("%")]
Explanation:
It first extracts 30 characters from the quoted string then searches for % from the right end. The position of % from the right end will be used to extract the string. Voilaa!! You got your result.
Alternate approach:
Instead of string=string[:string[:30].rfind("%")] you can do like this too string=string[:string.rfind("%",0,30)]
Note: I extracted the string and stored it back to showcase how it works, if you do not want to store then you can simply use like print(string[:string[:30].rfind("%")]) to display the results
Hope it helps...
How about putting the individual characters in a list and then count and strip?
Rough example:
from urllib import quote
s = 'Customer sale 88% in urm 50'
res = []
for c in s:
res.append(quote(c))
print res # ['C', 'u', 's', 't', 'o', 'm', 'e', 'r', '%20', 's', 'a', 'l', 'e', '%20', '8', '8', '%25', '%20', 'i', 'n', '%20', 'u', 'r', 'm', '%20', '5', '0']
print len(res)
current_length = 0
for item in res:
current_length += len(item)
print current_length # 39
while current_length > 30:
res = res[:-1]
current_length = 0
for item in res:
current_length += len(item)
print "".join(res) # Customer%20sale%2088%25%20in
That way you will not end up cutting in the middle of a quoting character. And in case you need a different length in the future, you just need to modify the while-loop. Well, code can be made more clean as well ;)
I don't understand the built-in functions max and min in python 2.7
max("sehir")
min("sehir")
max gives the letter "s" and min gives the letter "e"
max and min take as parameter (given you only give it one unnamed parameter) an iterable, and returns the maximum / minimum item.
A string is an iterable: if you iterate over a string, you obtain the 1-char strings that are the characters of the string.
Then max and min iterate over that iterable and returns the maximum or minimum item. For a string the lexicographical order is defined. So 'a' < 'b', and 'ab' > 'aa'. So it is compared lexicographically, and the individual characters are compared by ASCII code (Unicode code in python-3.x). Since all characters have are one-caracter strings. We only have to take the ASCII code into account here. You can inspect the ASCII table here [wiki].
So max("sehir") will return 's', since max(['s', 'e', 'h', 'i', 'r']) == 's': the maximum character in the iterable. For min('sehir') == 'e', since min(['s', 'e', 'h', 'i', 'r']) == 'e' because it is the "smallest" character in the string.
I want to be able to isolate the letters in a string from an input and return them as a collection containing 4 separate lower case characters.
This is what I have so far:
def main():
original = input(str("Enter a 4-letter word: "))
letters = isolate_letters(original)
def isolate_letters(original):
letters = list(original.items())
return letters
main()
>>> s = "1234"
>>> list(s)
['1', '2', '3', '4']
You want the first 4 lowercase characters:
letters = [c for c in original.lower() if c.isalpha()][:5]
str.isalpha
str.lower
First you convert the string to lowercase (lower()), then pick out all the alphabet characters from the string (isalpha()) and finally slice off the first 4 ([:5])
I presume you want to filter for the ascii letters. If not, a python string is iterable, so for most practical applications a string behaves just like a list - try just using the string as if it was a list.
If you want all letters:
>>> import string
>>> original = "foo, bar, 2014"
>>> letters = [c for c in original if c in string.ascii_letters]
['f', 'o', 'o', 'b', 'a', 'r']
If you want them without repetitions:
>>> unique_letters = set(letters)
>>> unique_letters
{'a', 'b', 'f', 'o', 'r'}
[update]
Thanks a lot! im new to python is there any chance you could explaiin how this works please?
Well, string.ascii_letters contains:
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
We are using Python list comprehensions, a syntax based on the set-builder notation in math:
[item for item in some_list if condition]
It is almost plain english: return a list of items in some_list if condition is true. In our case, we are testing if the character is an ascii letter using the in operator.
The set object in Python is an unordered list that ensure there is no repeated items.