Why does the python adds letters in dictionary? - python

I have been recently trying to make a program in python that makes text cipher but this is what happens :
text='abab'#the text we want to replace
result=''#we are going to replace it
replace_map={'a':'b', # a dictionary map to replace the text
'b':'a'
}
for ch in text: #loop through every text in the loop
if ch in replace_map: # if the text is in the replace map
result += replace_map[ch] #then we are going to replace every letter in it from replace map
else:
result += ch#else just add the value with no changing
print(text)#for comparison
print(result)#then print the text after replacing it
I want the result text to be 'abab' instead of 'babab'.
please help.

Indentation in Python is critical! The interpreter is misunderstanding the flow of the program because the else keyword is not indented properly. Try using an IDE, which generally does well at indenting the code as needed (if and else statements on the same level, etc).
If you indent the code properly, it looks like the following. I have tested this code on my machine and I can confirm it works.
text = 'abab'#the text we want to replace
result = ''#we are going to replace it
replace_map = {
'a':'b', # a dictionary map to replace the text
'b':'a'
}
for ch in text: # loop through every text in the loop
if ch in replace_map: # if the text is in the replace map
result += replace_map[ch] # then we are going to replace every letter in it from replace map
else:
result += ch # else just add the value with no changing
print(text) # for comparison
print(result) # then print the text after replacing it

The problem is that your else statement is out of the for-loop, just add an indent to it, and it should give you your results.

Related

How to uppercase the first letter of a string that follows a line break?

I have a long text that contains multiple paragraphs. It is stored in one variable.
I need to uppercase the first letter every word that follows a line break (or a period).
What is the most simple way to do that?
Here is a code that capitalize the the letter of every word of a new line.
texts=''' hiii.
hellooooooooo.
my name is stack.
dhdjljdkd.
'''
res=[ i.strip().capitalize() for i in texts.split('\n')]
print('\n'.join(res))
#for i in texts.split('\n'):
# res+=i.strip().capitalize()+'\n'
#print(res) #--- WORKS
Output:
Hiii.
Hellooooooooo.
My name is stack.
Dhdjljdkd.
I suppose you could split your text using as separator character \n. So the code should look like this:
output = []
for x in longString.split("\n"):
try:
x = x[0].upper() + x[1:]
except:
pass
output.append(x)
outputString = "\n".join(output)
With this approach you will be able to upper case the first letter after a line break. You can follow a similar approach for period.
Let me know if this helps! :D
Try like this.
May be it is a little complex.
I seem to have rebuilt the upper() function
import re
content="i have a long text that contains multiple paragraphs.\nit is stored in one variable.\ni need to uppercase the first letter every word that follows a line break (or a period).\nwhat is the most simple way to do that?"
def your_function_name(content):
new_res=[]
res=re.split(r'[.?\n]',content)
while "" in res:
res.remove("")
for con in res:
if 61<=ord(con[0])<=96:
new_con=con
new_res.append(new_con)
elif 97<=ord(con[0])<=123:
new_con=chr(ord(con[0])-32)+con[1:]
new_res.append(new_con)
else:
new_con=con
new_res.append(new_con)
return new_res
print("Transformed\n-----------------")
new_res=your_function_name(content)
for i in new_res:
print(i)
results are as follows
Transformed
-----------------
I have a long text that contains multiple paragraphs
It is stored in one variable
I need to uppercase the first letter every word that follows a line break (or a period)
What is the most simple way to do that

How to change a single letter in input string

I'm newbie in Python so that I have a question. I want to change letter in word if the first letter appears more than once. Moreover I want to use input to get the word from user. I'll present the problem using an example:
word = 'restart'
After changes the word should be like this:
word = 'resta$t'
I was trying couple of ideas but always I got stuck. Is there any simple sollutions for this?
Thanks in advance.
EDIT: In response to Simas Joneliunas
It's not my homework. I'm just finished reading some basic Python tutorials and I found some questions that I couldn't solve on my own. My first thought was to separate word into a single letters and then to find out the place of the letter I want to replace by "$". I have wrote that code but I couldn't came up with sollution how to get to specific place and replace it.
word = 'restart'
how_many = {}
for x in word:
how_many=+1
else:
how_many=1
for y in how_many:
if how_many[y] > 0:
print(y,how_many[y])
Using str.replace:
s = "restart"
new_s = s[0] + s[1:].replace(s[0], "$")
Output:
'resta$t'
Try:
"".join([["$" if ch in word[:i] else ch for i, ch in enumerate(word)])
enumerate iterates through the string (i.e. a list of characters) and keeps a running index of the iteration
word[:i] checks the list of chars until the current index, i.e. previously appeared characters
"$" if ch in word[:i] else ch means replace the character at existing position with $ if it appears before others keep the character
"".join() joins the list of characters into a single string.
This is where the python console is handy and lets you experiment. Since you have to keep track of number of letters, for a good visual I would list the alphabet in a list. Then in the loop remove from the list the current letter. If letter does not exist in the list replace the letter with $.
So check if it exists first thing in the loop, if it exists, remove it, if it doesn’t exist replace it from example above.

Can I remove multiple indexes from a string with a for loop? [duplicate]

This question already has answers here:
Remove char at specific index - python
(8 answers)
Closed 3 years ago.
I am new to Python and I‘m currently just messing around a little bit... but I am stuck with this one problem. I am trying to remove certain indexes from a string with a for loop. My Idea was something like this:
Text="Gvusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas"
for i in range(0,7):
Text=Text.replace(Text[i], "")
print(Text)
But it removes only one index and is restoring the already replaced ones, for example:
1.loop: vusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
2.loop: Gusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
Surely, there is many ways to get the desired result. Below, there is a good one based on your logic (using a for loop). As you are replacing a character by an empty character, It is better to directly remove the desired character.
In the code, I have transformed the text into a list for easy handling. After that, I have removed all characters based on the indexes. Finally, a join operation yields the desired text.
text = "Gvusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas"
text_list = list(text)
for index in range(0, 7):
text_list.remove(text[index])
text = ''.join(text_list)
print(text) # dsz8audvbsauzdgsavuczisagbcsuzaicbhas
If I understand what you are trying to do, you are trying to omit letters of the string Text that are in indexes 0,1,2,3,4,5 and 6. but your code doesn't do that currently, but indeed it will take the first letter which is G and it will remove it from all the string(there is one occurrence), the next loop Text is equal to u because Text is equal vusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas after omitting G in the first iteration, as there are five occurrences of u, Text will be equal to vsaibdsz8advbsazdgsavczisagbcszaicbhas and so on..
you can put print(Text) inside the for loop and watch the results:
>>> Text="Gvusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas"
>>> for i in range(0,7):
... Text=Text.replace(Text[i], "")
... print(Text)
...
vusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
vsaibdsz8advbsazdgsavczisagbcszaicbhas
vsibdsz8dvbszdgsvczisgbcszicbhs
vsidsz8dvszdgsvczisgcszichs
vidz8dvzdgvczigczich
viz8vzgvczigczich
viz8vzvcziczich
In Python you can do that without a loop and the best way for that by using slicing as follows:
Text = Text[7:]
This will give you Text equal to dsz8audvbsauzdgsavuczisagbcsuzaicbhas.
If your goal is to reach this through a loop(supposing you are in need of Text in every iteration), you can try this:
>>> Text="Gvusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas"
>>> for i in range(0,7):
... Text = Text[1:]
... print(Text)
...
vusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
usaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
saibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
aibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
ibdsz8audvbsauzdgsavuczisagbcsuzaicbhas
bdsz8audvbsauzdgsavuczisagbcsuzaicbhas
dsz8audvbsauzdgsavuczisagbcsuzaicbhas
I hope this will help!
Take a look at string slicing:
text = "Gvusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas"
newtext = text[1:]
print(newtext)
--> "Gvusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas"
--> "vusaibdsz8audvbsauzdgsavuczisagbcsuzaicbhas"
You can replace
Text=Text.replace(Text[i], "")
with
Text = Text[:i] + Text[i+1:]
which uses slicing to rebuild a string without the specific index.
Side note: variable names should be lower case.

How do I turn my code into a working Caesar Cipher translator?

I've been trying to work on this code of mine that takes a string of words, converts every letter into an ASCII code, adds a certain number (rotate_number), and then prints out the translated version of those numbers, all converted back into a string of random letters (but with the spaces and symbols remaining the same). For example, I want the string of "How are you today?" to rotate by a number of say +4, so that the final product says, "Lsa evi csy xshec?"
Here's the code I have so far, however when I run it, only one letter is rotated and printed out:
def encrypt_words(words, rotate_number):
blank = ""
for i in words:
translate1 = ord(i) + rotate_number
translated = chr(translate1)
blank += translated
print translated
encrypt_words("How are you today?", 3)
Also, I am sorry if my question has already been answered. I've been searching all across the web and this specific site, but nothing seems to work for me...
I would recommend first creating a rotate method
def rotate(alphabet,rotation):
return alphabet[rotation:]+alphabet[:rotation]
#test it
print(rotate(string.ascii_lowercase,5))
now create a lookup table of the rotation
def create_lookup_table(rotation,*alphabets):
if not alphabets:
alphabets = [string.ascii_lowercase,string.ascii_uppercase]
alphabet = "".join(alphabets)
rotated = "".join(rotate(a,rotation) for a in alphabets)
return dict(zip(alphabet,rotated))
# test it
create_lookup_table(5)
create_lookup_table(2,"abcdef","GHIJKLM")
now implementing ceasar cipher is trival because we have given ourselves the toolset to help us
def ceasar(msg_plain,rotation):
lookup_table = create_lookup_table(rotation)
return ''.join(lookup_table.get(char,char) for char in msg_plain)
# test it
ceasar("Hello World!",13) # 'Uryyb Jbeyq!'
It looks like you want to be printing the string "blank", not translated as in your code. Try the following:
def encrypt_words(words, rotate_number):
blank = ""
for i in words:
translate1 = ord(i) + rotate_number
translated = chr(translate1)
blank += translated
print blank
Blank is the concatenation of each of the translated values. You should probably rename 'blank' as the name is misleading.
You would want to do something like :
def encrypt_words(words, rotate_number):
blank = ""
for i in words:
if i.isalpha(): # if part of alphabet shift with cipher
translate1 = ord(i) + rotate_number
translated = chr(translate1)
blank += translated
else: # else leave as is
blank += i
print blank # print entire word, not just last character
# change blank variable to something that better describes function?

Python Challenge #3: Loop stops way too early

I'm working on PythonChallenge #3. I've got a huge block of text that I have to sort through. I am trying to find a sequence in which the first and last three letters are caps, and the middle one is lowercase.
My function loops through the text. The variable block stores the seven letters that are currently being looped through. There's a variable, toPrint, which gets turned on and off based on whether the letters in block correspond to my pattern (AAAaAAA). Based on the last block printed according to my function, my loop stops early in my text. I have no idea why this is happening and if you could help me figure this out, that would be great.
text = """kAewtloYgcFQaJNhHVGxXDiQmzjfcpYbzxlWrVcqsmUbCunkfxZWDZjUZMiGqhRRiUvGmYmvnJ"""
words = []
for i in text:
toPrint = True
block = text[text.index(i):text.index(i)+7]
for b in block[:3]:
if b.isupper() == False:
toPrint = False
for b in block[3]:
if b.islower() == False:
toPrint = False
for b in block[4:]:
if b.isupper() == False:
toPrint = False
if toPrint == True and block not in words:
words.append(block)
print (block)
print (words)
With Regex:
This is a really good time to use regex, it's super fast, more clear, and doesn't require a bunch of nested if statements.
import re
text = """kAewtloYgcFQaJNhHVGxXDiQmzjfcpYbzxlWrVcqsmUbCunkfxZWDZjUZMiGqhRRiUvGmYmvnJ"""
print(re.search(r"[A-Z]{3}[a-z][A-Z]{3}", text).group(0))
Explanation of regex:
[A-Z]{3] ---> matches any 3 uppercase letters
[a-z] -------> matches a single lowercase letter
[A-Z]{3] ---> matches 3 more uppercase letters
Without Regex:
If you really don't want to use regex this is how you could do it:
text = """kAewtloYgcFQaJNhHVGxXDiQmzjfcpYbzxlWrVcqsmUbCunkfxZWDZjUZMiGqhRRiUvGmYmvnJ"""
for i, _ in enumerate(text[:-6]): #loop through index of each char (not including last 6)
sevenCharacters = text[i:i+7] #create chunk of seven characters
shouldBeCapital = sevenCharacters[0:3] + sevenCharacters[4:7] #combine all the chars that should be cap into list
if (all(char.isupper() for char in shouldBeCapital)): #make sure all those characters are indeeed capital
if(sevenCharacters[3].islower()): #make sure middle character is lowercase
print(sevenCharacters)
I think your first problem is that you are using str.index(). Like find(), the .index() method of a string returns the index of the first match that is found.
Thus, in your example, whenever you search for 'x' you will get the index of the first 'x' found, etc. You cannot successfully work with any character that is not unique in the string, or that is not the first occurrence of a repeated character.
In order to keep the same structure (which isn't necessary- there is an answer posted using enumerate that I prefer myself) I implemented a queuing approach with your block variable. Each iteration, a character is dropped from the front of block, while the new character is appended to the end.
I also cleaned up some of your needless comparisons with False. You will find that this is not only inefficient, it is frequently wrong, because many of the "boolean" activities you perform will not be on actual boolean values. Get out of the habit of spelling out True/False. Just use if c or if not c.
Here's the result:
text = """kAewtloYgcFQaJNhHVGxXDiQmzjfcpYbzxlWrVcqsmUbCunkfxZWDZjUZMiGqhRRiUvGmYmvnJ"""
words = []
block = '.' + text[0:6]
for i in text[6:]:
block = block[1:] + i # Drop 1st char, append 'i'
toPrint = True
for b in block[:3]:
if not b.isupper():
toPrint = False
if not block[3].islower():
toPrint = False
for b in block[4:]:
if not b.isupper():
toPrint = False
if toPrint and block not in words:
words.append(block)
print (words)
If I understood your question, then according to my opinion there is no need of loop. My this simple code can find required sequence.
# Use this code
text = """kAewtloYgcFQaJNhHVGxXDiQmzjfcpYbzxlWrVcqsmUbCunkfxZWDZjUZMiGqhRRiUvGmYmvnJ"""
import re
print(re.findall("[A-Z]{3}[a-z][A-Z]{3}", text))

Categories

Resources