Code wars : Title Case with python - python

def title_case(title, minor_words = 0):
title = title.lower().split(" ")
title_change = []
temp = []
if minor_words != 0 :
minor_words = minor_words.lower().split(" ")
for i in range(len(title)):
if (i != 0 and title[i] not in minor_words) or (i == 0 and title[i] in minor_words):
temp = list(title[i].lower())
temp[0] = temp[0].upper()
title_change.append("".join(temp))
else:
title_change.append(title[i])
temp = []
else:
for i in range(len(title)):
temp = list(title[i])
temp[0] = temp[0].upper()
title_change.append("".join(temp))
temp = []
return " ".join(title_change)
Hello,this is my python code here.
This is the question:
A string is considered to be in title case if each word in the string is either (a) capitalised (that is, only the first letter of the word is in upper case) or (b) considered to be an exception and put entirely into lower case unless it is the first word, which is always capitalised.
Write a function that will convert a string into title case, given an optional list of exceptions (minor words). The list of minor words will be given as a string with each word separated by a space. Your function should ignore the case of the minor words string -- it should behave in the same way even if the case of the minor word string is changed.
I am trying not to use capitalize() to do this.It seems my code works fine on my computer,but the code wars just prompted "IndexError: list index out of range".

Your code will break if title has leading or trailing spaces, or two consecutive spaces, such as "foo bar". It will also break on an empty string. That's because title.lower().split(" ") on any of those kinds of titles will give you an empty string as one of your "words", and then temp[0] will cause an IndexError later on.
You can avoid the issue by using split() with no argument. It will split on any kind of whitespace in any combinations. Multiple spaces will be treated just like one space, and leading or trailing whitespace will be ignored. An empty string will become an empty list when split is called, rather than a list with one empty string in it.

Just as a supplement to #Blckknght's explanation, here is an illuminating console session that steps through what's happening to your variable.
>>> title = ''
>>> title = title.lower().split(' ')
>>> title
['']
>>> temp = list(title[0])
>>> temp
[]
>>> temp[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
I tried your solution on other (non-whitespace) inputs, and it works fine.

Related

I have a problem with the task of reversing words and removing parentheses

Task
Write a program that will decode the secret message by reversing text
between square brackets. The message may contain nested brackets (that
is, brackets within brackets, such as One[owT[Three[ruoF]]]). In
this case, innermost brackets take precedence, similar to parentheses
in mathematical expressions, e.g. you could decode the aforementioned
example like this:
One[owT[Three[ruoF]]]
One[owT[ThreeFour]]
One[owTruoFeerhT]
OneThreeFourTwo
In order to make your own task slightly easier and less tricky, you
have already replaced all whitespaces in the original text with
underscores (“_”) while copying it from the paper version.
Input description
The first and only line of the standard input
consists of a non-empty string of up to 2 · 106 characters which may
be letters, digits, basic punctuation (“,.?!’-;:”), underscores (“_”)
and square brackets (“[]”). You can safely assume that all square
brackets are paired correctly, i.e. every opening bracket has exactly
one closing bracket matching it and vice versa.
Output description
The standard output should contain one line – the
decoded secret message without any square brackets.
Example
For sample input:
A[W_[y,[]]oh]o[dlr][!]
the correct output is:
Ahoy,_World!
Explanation
This example contains empty brackets. Of course, an empty string, when
reversed, remains empty, so we can simply ignore them. Then, as
previously, we can decode this example in stages, first reversing the
innermost brackets to obtain A[W_,yoh]o[dlr][!]. Afterwards, there
are no longer any nested brackets, so the remainder of the task is
trivial.
Below is my program that doesn't quite work
word = input("print something: ")
word_reverse = word[::-1]
while("[" in word and "]" in word):
open_brackets_index = word.index("[")
close_brackets_index = word_reverse.index("]")*(-1)-1
# print(word)
# print(open_brackets_index)
# print(close_brackets_index)
reverse_word_into_quotes = word[open_brackets_index+1:close_brackets_index:][::-1]
word = word[:close_brackets_index]
word = word[:open_brackets_index]
word = word+reverse_word_into_quotes
word = word.replace("[","]").replace("]","[")
print(word)
print(word)
Unfortunately my code only works with one pair of parentheses and I don't know how to fix it.
Thank you in advance for your help
Assuming the re module can be used, this code does the job:
import re
text = 'A[W_[y,[]]oh]o[dlr][!]'
# This scary regular expresion does all the work:
# It says find a sequence that starts with [ and ends with ] and
# contains anything BUT [ and ]
pattern = re.compile('\[([^\[\]]*)\]')
while True:
m = re.search(pattern, text)
if m:
# Here a single pattern like [String], if any, is replaced with gnirtS
text = re.sub(pattern, m[1][::-1], text, count=1)
else:
break
print(text)
Which prints this line:
Ahoy,_World!
I realize the my previous answer has been accepted but, for completeness, I'm submitting a second solution that does NOT use the re module:
text = 'A[W_[y,[]]oh]o[dlr][!]'
def find_pattern(text):
# Find [...] and return the locations of [ (start) ] (end)
# and the in-between str (content)
content = ''
for i,c in enumerate(text):
if c == '[':
content = ''
start = i
elif c == ']':
end = i
return start, end, content
else:
content += c
return None, None, None
while True:
start, end, content = find_pattern(text)
if start is None:
break
# Replace the content between [] with its reverse
text = "".join((text[:start], content[::-1], text[end+1:]))
print(text)

Using replace method in python 3.6

I need to replace "!##$%^&*()\n{}[]()_-+=<>?\xa0;'/.," with a blank. I am using replace method but it seems it is deprecated on python 3.6. word_list = [] is a list which will have all the words extracted from the webpage. Then clean_up_list method will clean the symbols and replace them with blank space.
I used for to loop through the length of symbols and replace symbols with blank. I used
word = word.replace(symbols[i],"") ; Any help on how to use the replace method so that symbols are replaced and words are printed without symbols between them.
Error:
AttributeError: 'list' object has no attribute 'replace'
My Code:
url = urllib.request.urlopen("https://www.servicenow.com/solutions-by-category.html").read()
word_list = []
soup = bs.BeautifulSoup(url,'lxml')
word_list.append([element.get_text() for element in soup.select('a')])
print(word_list)
def clean_up_list(word_list):
clean_word_list = []
for word in word_list:
symbols = "!##$%^&*()\n{}[]()_-+=<>?\xa0;'/.,"
for i in range(0,len(symbols)):
word = word.replace(symbols[i],"")
#print(type(word))
#print(type(word))
#word.replace(symbols[i]," ")
if(len(word) > 0):
#print(word)
clean_word_list.append(word)
There are two errors here: first you do not construct a list of strings, but a list of lists of strings. This line:
word_list.append([element.get_text() for element in soup.select('a')])
should be:
word_list.extend([element.get_text() for element in soup.select('a')])
Furthermore you cannot call replace on the list directly (it is not a method of a list object). You need to this for every entry.
Next you also specify (correctly) than you then have to call replace(..) for every character in the symbols string. Which is of course inefficient. You can however use translate(..) for that.
So you can replace the entire for loop with with list comprehension:
symbols = "!##$%^&*()\n{}[]()_-+=<>?\xa0;'/.,"
clean_word_list = [word.translate(None,symbols) for word in word_list]
Try explicitly converting the word to a string, as the error code you're receiving mentions the object is a 'list' not string and that the replace method cannot be called on lists. For example (notice the second to last line):
def clean_up_list(word_list):
clean_word_list = []
for word in word_list:
word = str(word)
symbols = "!##$%^&*()\n{}[]()_-+=<>?\xa0;'/.,"

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))

How to assign the last character of a string to a variable?

I'm trying to store the last character of a string in a variable without knowing beforehand how long the string is (the string is originally read from a list). I have:
last = record[-1]
lastInd = len(last) - 1
lastChar = last[lastInd]
But I get the following error:
lastChar = last[lastInd]
IndexError: string index out of range
If I try:
lastChar = last[-1]
I get the same error:
lastChar = last[-1]
IndexError: string index out of range
I don't really understand what's going wrong here? Am I not getting the index right?
As inspectorG4dget says, the only way you can get this exception from last[-1] is if last is an empty string.
If you want to know how to deal with it… well, it depends on what you're trying to do.
Normally, if you're trying to get the last character of a string, you expect it to be non-empty, so it should be an error if it is unexpectedly empty.
But if you want to get the last character if the string is npt empty, or an empty string if it is, there are three ways to do it, in (what I think is) declining order of pythonic-ness, at least in code written by a novice.
First, there's EAFP ("Easier to Ask for Forgiveness than Permission). Assume it'll work, try it, and deal with unexpected failure as appropriate:
try:
lastChar = last[-1]
except IndexError:
lastChar = ''
Then there's LBYL (Look Before You Leap). Check for unexpected cases in advance:
if last:
lastChar = last[-1]
else:
lastChar = ''
Finally, there's being overly clever. Write code that you won't understand three months from now without thinking it through:
lastChar = last[-1:]
This returns all characters from the last one to the end. If there are any characters, that's the same as the last one. If there are no characters, that's nothing.
Note that this only really works as intended because a string's individual elements are themselves strings. If you tried to get the last element from a list like this, you'd get a list of 1 element or an empty list, not a single possible-empty element.
This is because last is an empty string.
Check this out:
>>> last = 'a'
>>> last[-1]
'a'
>>> last = ''
>>> last[-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
If you want an empty string for your last character, just in case you have an empty string as your last record, then you could try this:
if last == '': # or `if not last`
lastChar = ''
Alternatively, you could use the ternary operator:
lastChar = last[-1] if last else ''

Python: Remove First Character of each Word in String

I am trying to figure out how to remove the first character of a words in a string.
My program reads in a string.
Suppose the input is :
this is demo
My intention is to remove the first character of each word of the string, that is
tid, leaving his s emo.
I have tried
Using a for loop and traversing the string
Checking for space in the string using isspace() function.
Storing the index of the letter which is encountered after the
space, i = char + 1, where char is the index of space.
Then, trying to remove the empty space using str_replaced = str[i:].
But it removed the entire string except the last one.
List comprehensions is your friend. This is the most basic version, in just one line
str = "this is demo";
print " ".join([x[1:] for x in str.split(" ")]);
output:
his s emo
In case the input string can have not only spaces, but also newlines or tabs, I'd use regex.
In [1]: inp = '''Suppose we have a
...: multiline input...'''
In [2]: import re
In [3]: print re.sub(r'(?<=\b)\w', '', inp)
uppose e ave
ultiline nput...
You can simply using python comprehension
str = 'this is demo'
mstr = ' '.join([s[1:] for s in str.split(' ')])
then mstr variable will contains these values 'his s emo'
This method is a bit long, but easy to understand. The flag variable stores if the character is a space. If it is, the next letter must be removed
s = "alpha beta charlie"
t = ""
flag = 0
for x in range(1,len(s)):
if(flag==0):
t+=s[x]
else:
flag = 0
if(s[x]==" "):
flag = 1
print(t)
output
lpha eta harlie

Categories

Resources