As of now it takes the punctuation out, but I cannot figure out how to make it add a space instead of just taking out the punctuation.
Currently I have:
punctuation = "!\"#$%&()*+,-./:;<=>?#[\\]^_`{|}~"
def remove_punct(theStr):
theStr_sans_punct = ""
for letter in theStr:
if letter not in punctuation:
theStr_sans_punct = theStr_sans_punct + letter
return theStr_sans_punct
It's in a interactive textbook so it will automatically do the tests on their site.
By adding an else to your code:
punctuation = "!\"#$%&()*+,-./:;<=>?#[\\]^_`{|}~"
def remove_punct(theStr):
theStr_sans_punct = ""
for letter in theStr:
if letter not in punctuation:
theStr_sans_punct = theStr_sans_punct + letter
else:
theStr_sans_punct = theStr_sans_punct + " "
return theStr_sans_punct
Related
I came across below mentioned scenario:
Input:-
parselTongue
Expected Output:-
parsel_tongue
My code:-
empty_string = ""
word = input()
if word.islower() == 1:
empty_string = empty_string + word
print(empty_string)
else:
for char in word:
char = str(char)
if char.isupper() == 1:
x = char
y = word.find(x)
print(char.replace(char, word[0:y] + "_" + char.lower() + word[y:]))
My output:-
parsel_tTongue
Please advice where i am going wrong as my output is coming as "parsel_tTongue" and not "parsel_tongue"
The more elegant solution would be just to implement the logic using comprehension.
word = input()
output= ''.join(c if not c.isupper() else f'_{c.lower()}' for c in word)
#output: 'parsel_tongue'
I believe that this approach could be better.
It prevents from situations where word contains not only letters but also special characters or numbers.
word = "camelCaseWord"
res = "" # sanke case word
# handle 1st upper character
if word[0].isupper():
word = word[0].lower() + word[1:]
for w in word:
# Only letter can be upper
if w.isupper():
res += "_" + w.lower()
else:
res += w
print(res)
>>> camel_case_word
if word = "camelCase3Wor& - > >>> camel_case3_wor&
no need for loop use regex
import re
name = 'parselTongue'
name = re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
print(name) # camel_case_name
Adjust the slice on word
empty_string = ""
word = input()
if word.islower() == 1:
empty_string = empty_string + word
print(empty_string)
else:
for char in word:
char = str(char)
if char.isupper() == 1:
x = char
y = word.find(x)
print(char.replace(char, word[0:y] + "_" + char.lower()+ word[y+1:]))
prints the following for the input parselTongue
praselTongue
prasel_tongue
The best practice may be using regex:
fooBarBaz -> foo_bar_baz
re.sub(r'([A-Z])',lambda match:'_'+match.group(1).lower(),'fooBarBaz')
foo_bar_baz -> fooBarBaz
re.sub(r'_([a-z])',lambda match:match.group(1).upper(),'foo_bar_baz')
import re
camel_case = 'miaBau'
snake_case = re.sub(r'([A-Z])', r'_\1', camel_case).lower()
I'm very new to python and I'm trying to make a hangman game. I currently have a line of code saying word = (random.choice(open("Level1py.txt").readline())).
I'm getting the error 'str' object does not support item assignment.
Here is the rest of my code (sorry for the mess):
import random
def checkLetter(letter, word, guess_word):
for c in word:
if c == letter:
guess_word[word.index(c)] = c
word[word.index(c)] = '*'
print(guess_word)
word = (random.choice(open("Level1py.txt").readline().split()))
guess_word = ['_' for x in word]
print(guess_word)
while '_' in guess_word:
guess = input('Letter: ')
print(checkLetter(guess, word, guess_word))
Strings are immutable in python. An easy workaround is to use lists, which are mutable:
st = "hello"
ls = list(st)
ls[3] = 'r'
st = ''.join(ls)
print(st)
Outputs
helro
Edit: here's how you would implement it in your own code
import random
def checkLetter(letter, word, guess_word):
for c in word:
if c == letter:
guess_word[word.index(c)] = c
word_list = list(word)
word_list[word.index(c)] = "*"
word = ''.join(word_list)
print(guess_word)
word = 'test'
guess_word = ['_' for x in word]
print(guess_word)
while '_' in guess_word:
guess = input('Letter: ')
print(checkLetter(guess, word, guess_word))
Note that there are still other issues that have nothing to do with this, like printing None and duplicate printing
You can also solve your problem using a dictionary:
word = "my string" #replace this with your random word
guess_word = {i: '_' for i in set(word)} # initially assign _ to all unique letters
guess_word[' '] = ' ' # exclude white space from the game
wrong_attempts = 0
while '_' in guess_word.values():
guess = input('Letter: ')
if guess in guess_word.keys():
guess_word[guess] = guess
else:
wrong_attempts += 1
if wrong_attempts > 11:
break
printable = [guess_word[i] for i in word]
print(' '.join(printable))
if '_' in guess_word.values():
print('you lost')
else:
print('congratulation, you won')
I'm trying to solve a problem that can be found in the Book The Coder's Apprentice by Pieter Spronck, in section 13.2.4. This is the code I wrote so far:
english_dutch = {"last":"laatst", "week":"week", "the":"de", "royal":"koninklijk",
"festival":"feast", "hall":"hal", "saw":"zaag", "first":"eerst", "performance":"optreden",
"of":"van", "a":"een", "new":"nieuw", "symphony":"symphonie", "by":"bij",
"one":"een", "world":"wereld", "leading":"leidend", "modern":"modern",
"composer":"componist", "composers:componisten" "two":"twee", "shed":"schuur", "sheds":"schuren"}
text = "Last week The Royal Festival Hall saw the first \
performance of a new symphony by one of the world's leading \
modern composers, Arthur 'Two-Sheds' Jackson."
def clean(t):
t = t.lower()
t = t.split()
new_t = ""
for word in t:
new_word = ""
for letter in word:
if "a" <= letter <= "z":
new_word += letter
if letter == "-":
new_word += " "
else:
continue
new_t += new_word + " "
return new_t
def translate(t):
translation = ""
for word in t.split():
if english_dutch.get(word):
translation += english_dutch[word] + " "
else:
translation += word + " "
return translation
def auto_correct():
news = ""
a = translate(clean(text)).split()
for word in a:
if len(word) > 1:
news += word + " "
print(news)
auto_correct()
It seems to work OK, but when I run it, the words "composers" and "two" are not translated.
You forgot a comma between the word composers and the word two. In addiotion you wrote "composers:componisten" instead of "composers":"componisten". Change your dictionary like so
english_dutch = {"last":"laatst", "week":"week",
"the":"de", "royal":"koninklijk",
"festival":"feast", "hall":"hal",
"saw":"zaag", "first":"eerst",
"performance":"optreden",
"of":"van", "a":"een",
"new":"nieuw", "symphony":"symphonie",
"by":"bij",
"one":"een", "world":"wereld",
"leading":"leidend", "modern":"modern",
"composer":"componist",
"composers":"componisten", "two":"twee", # <- HERE
"shed":"schuur", "sheds":"schuren"}
Why it passed undetected? Check this:
>>> {"composers:componisten" "two":"twee"}
{'composers:componistentwo': 'twee'}
Because the comma was missing and the colon was within the string, python concatenated the strings, creating a useless (but valid) key/value pair.
This behaviour is documented here
Multiple adjacent string literals (delimited by whitespace), possibly using different quoting conventions, are allowed, and their meaning is the same as their concatenation. Thus, "hello" 'world' is equivalent to "helloworld".
I have a problem when creating a function that's supposed to first return lowercase letters, "_" and "." and then uppercase letters, " " and "|" in that order. My version seems to return numbers and special characters like <># too which I don't want it to do, It's only supposed to read through the input string once and I don't know if that's achieved with my code.
My code is:
def split_iterative(n):
splitted_first = ""
splitted_second = ""
for i in n:
if i == i.lower() or i == "_" or i == ".":
splitted_first = splitted_first + i
elif i == i.upper() or i == " " or i == "|":
splitted_second = splitted_second + i
return splitted_first + splitted_second
if I do split_iterative("'lMiED)teD5E,_hLAe;Nm,0#Dli&Eg ,#4aI?rN#T§&e7#4E #<(S0A?<)NT8<0'")) it returns "'li)te5,_he;m,0#li&g ,#4a?r#§&e7#4 #<(0?<)8<0'MEDDELANDEINTESANT" which is incorrect as it should eliminate all those special characters and numbers. How do I fix this? It should return ('lite_hemligare', 'MEDDELANDE INTE SANT')
You could try this:
def f(input_string):
str1 = str2 = ""
for character in input_string:
if character.isalpha():
if character.islower():
str1 += character
else:
str2 += character
elif character in "_.":
str1 += character
elif character in " |":
str2 += character
return str1, str2
Output:
>>> input_string = "'lMiED)teD5E,_hLAe;Nm,0#Dli&Eg ,#4aI?rN#T§&e7#4E #<(S0A?<)NT8<0'"
>>>
>>> print f(input_string)
('lite_hemligare', 'MEDDELANDE INTE SANT')
>>>
This is because you are iterating through a string. The lowercase of the special characters is the same as the character. i.e.. '#'.lower() == '#'. hence it'll return '#' and all other special characters. you should explicitly check for alphabets using the isalpha() method on strings.
(i.isalpha() and i.lower() == i) or i == '_' or i == '.'
First, to make it return a list don't return the concatenated string but a list
Second, you are not checking or filtering out the characters, one way would be by checking if the character is a letter using isalpha() method
something like this:
def split_iterative(n):
splitted_first = ""
splitted_second = ""
for i in n:
if (i.isalpha() and i == i.lower()) or i == "_" or i == ".":
splitted_first = splitted_first + i
elif (i.isalpha() and i == i.upper()) or i == " " or i == "|":
splitted_second = splitted_second + i
#returns a list you can make it a variable if you need
return [splitted_first, splitted_second]
You can use ASCII values for the filtering of characters:
def split_iterative(n):
splitted_first = ""
splitted_second = ""
for i in n:
if ord(i) in range(97,122) or i == "_" or i == ".":
splitted_first = splitted_first + i
elif ord(i) in range(65,90) or i == " " or i == "|":
splitted_second = splitted_second + i
return (splitted_first , splitted_second)
You can make use of two lists while walking through characters of your text.
You can append lowercase, underscore, and stop characters to one list then uppercase, space and pipe characters to the other.
Finally return a tuple of each list joined as strings.
def splittext(txt):
slug, uppercase_letters = [], []
slug_symbols = {'_', '.'}
uppercase_symbols = {' ', '|'}
for letter in txt:
if letter.islower() or letter in slug_symbols:
slug.append(letter)
if letter.isupper() or letter in uppercase_symbols:
uppercase_letters.append(letter)
return ''.join(slug), ''.join(uppercase_letters)
txt="'lMiED)teD5E,_hLAe;Nm,0#Dli&Eg ,#4aI?rN#T§&e7#4E #<(S0A?<)NT8<0'"
assert splittext(txt) == ("lite_hemligare", "MEDDELANDE INTE SANT")
Here is the standard pig latin code used in codeacademy. It works well but it's shortcoming is that it only works for one word at a time:
pyg = 'ay'
original = raw_input('Enter a word or phrase:')
if len(original) > 0 and original.isalpha():
word = original.lower()
translate = word[1:] + word[0]
if word[0] != "a" and word[0] != "e" and word[0] != "i" and word[0] != "o" and word[0] != "u":
new_word = translate + pyg
print new_word
else:
new_word = word + pyg
print new_word
else:
print 'Input is empty or illegal'
so I wanted to make it so that it could phrases. This is what I came up with:
pyg = 'ay'
count = 0
original_input = raw_input('Enter a word or phrase:')
original = original_input
original_list = []
#converts to a list
while " " in original:
if count > 50:
break
word = original[0:original.index(" ")]
original_list.append(word)
space = original.index(" ")
space += 1
original = original[space:]
count += 1
#this works great until there is a word left and no spaces i.e. the last word
if len(original) > 0:
original_list.append(original)
#this adds the last word
print original_list
def pyglatin(phrase):
#old code doesn't work because phrase is a list
#now I have to translate BACK to a string
for words in phrase:
new_word = str(words)
"""this works for one word, how do I assign a new variable for every word if I don't know the phrase length ahead of time"""
so that brings me to my question: How do I assign a variable for every item when I don't know how many items I'm going to need, and then be able to call that code back (through the old pyglatin translator)?
As Maxime mentioned, lists are useful in this instance, and the string can be converted to a list much easier. To account for phrases, I would rewrite the code as follows:
def trans_word(original):
if len(original) > 0 and original.isalpha():
word = original.lower()
translate = word[1:] + word[0]
if word[0] != "a" and word[0] != "e" and word[0] != "i" and word[0] != "o" and word[0] != "u":
new_word = translate + pyg
return new_word
else:
new_word = word + pyg
return new_word
else:
return "Input is empty or illegal"
def pyglatin(phrase):
if len(phrase) > 0:
return " ".join(trans_word(word) for word in phrase)
else:
return "Input is empty or illegal"
pyg = 'ay'
count = 0
original_input = raw_input('Enter a word or phrase:')
original_list = original_input.split()
print pyglatin(original_list)
Maybe something like this?
def latinize(word):
word = word.lower()
translate = word[1:] + word[0]
return (translate if word[0] in 'aeiou' else word) + 'ay'
original = raw_input('Enter a word or phrase:')
print ' '.join(latinize(word) for word in original.split())
Example input and output:
Enter a word or phrase:Gallia est omnis divisa in partes tres
galliaay steay mnisoay divisaay niay partesay tresay
But shouldn't you actually move all initial consonants to the end, and not only the first?
Edit:
If you want to move all initial consonants to the end, you can use:
def latinize(word):
word = word.lower()
firstvowel = min (word.index (v) if v in word else 42042 for v in 'aeiou')
if firstvowel == 42042: raise Exception ('No vowel in word')
return word [firstvowel:] + word [:firstvowel] + 'ay'
original = raw_input('Enter a word or phrase:')
print ' '.join(latinize (word) for word in original.split () )
Sample input and output:
Enter a word or phrase:star chick mess string
arstay ickchay essmay ingstray