Im doing an exercise, where im defining a function that takes two inputs - a sentence and a word, that will be replaced by stars in the sentence input.
Problem is, I cant get the final output to put spaces in between words, ie it prints all the words crammed together. Any help please ?
def censor(text, word):
lis = text.split()
output =""
p = []
for w in lis:
if w != word:
p.append(w)
else:
l = len(w)
y = "*" * l
p.append(y)
output = output.join(p)
print output
censor("Hello world televison", "world")
You don't need to initialize output to an empty string first. You can just do
output = " ".join(p)
Notice the " ".join(), that is what determines how you are joining your strings. In this case, it's a single space. Also, you need to return something from your function, so instead of using print you should do
return output
Here's another solution, even though it's a little tricky, it should handle all the different cases that can occur:
def censor(text, word):
text = '.' + text + '.'
for i in range(len(text)):
if text[i].lower() == word[0].lower():
toCensor = True
for j in range(len(word)):
if text[i + j].lower() != word[j].lower():
toCensor = False
break
if toCensor:
if (ord(text[i - 1]) < ord('A') or ord(text[i - 1]) > ord('z'))\
and (ord(text[i + len(word)]) < ord('A') or ord(text[i + len(word)]) > ord('z')):
lst = list(text)
for j in range(len(word)):
lst[i + j] = '*'
text = "".join(lst)
lst = list(text)
lst = lst[1 : -1]
return "".join(lst)
censor("World worlds world television", "world")
>>> ***** worlds ***** television
It handles capital letters and all the punctuation.
Related
im trying to return all the middle letters in a string, eg, list = ["Guesss", "what", "idk"] which would return ead where if list[i] is odd it gets the middle letter and if list[i] is even it gets the second middle letter like in what the middle letters are ha and returns the second letter a.
How can I do this using recursion? - with no loops
This is what I've come up so far:
def get_middle_letters(words):
if words == []:
return ""
if len(words[0]) % 2 == 1:
middle = len(words[0]) // 2
return (words[0][middle]) + (get_middle_letters(words[1:]))
elif len(words[0]) % 2 == 0:
middle = len(words[0]) // 2
return ((words[0][middle + 1]) + (get_middle_letters(words[1:])))
words = ['Humans', 'are', 'lazy']
print(get_middle_letters(words))
print(get_middle_letters([]), "#EMPTY")
print(get_middle_letters(['words']))
def middle_letters(words):
if len(words) == 0:
return ""
else:
return words[0][len(words[0])//2] + middle_letters(words[1:])
print(middle_letters(["Guesss", "what", "idk"])) # sad
The answer should be 'sad' according to your logic.
'lazy' has four characters, so the middle == 2.
'lazy'[2 + 1] == 'y', but you wanted z, which is at index 2.
You don't need the + 1.
That being said, you don't need to check even/odd at all. Your odd length strings already work.
A possible recursive approach:
def middle_letters(words: list):
# base case
if not words:
return ''
# recursive case
last = words.pop()
return middle_letters(words) + last[len(last) // 2]
Behold, the power of a one-liner:
def middle_letters(words: list):
return (middle_letters(words[:-1]) + words[-1][len(words[-1]) // 2]) if words else ''
Test
print(repr(middle_letters([])))
print(repr(middle_letters(['Humans', 'are', 'lazy'])))
print(repr(middle_letters(["Guesss", "what", "idk"])))
Out[1]:
''
'arz'
'sad'
I need to split the string from the end.
For example, I have
word = '3640000'
And it is easy to split it from the begin of the string using list generator and .join method:
word = ' '.join([word[i:i + 3] for i in range(0, len(word), 3)])
In this case I get result: '364 000 0'
but I need get: "3 640 000"
How can I solve this task?
I tried something like this, but it is not working for me if a word is not divisible by 3 without remainder
list1 = []
for i in range(len(word) - 1, -1, -3):
print(word[i-2:i+1])
list1.append(word[i-2:i+1])
list1.reverse()
It's a bit hacky, we can use Python's string formatting to do the grouping, then replace the separator (Python only allows "," and "_" as grouping characters).
>>> w = '3640000'
>>> f'{int(w):,d}'.replace(',', ' ')
'3 640 000'
This is somewhat inefficient, but based on what you did initially, you can reverse the word and then split/join with spaces, then reverse it back:
word = '3640000'
word = word[::-1]
word = ' '.join([word[i:i + 3] for i in range(0, len(word), 3)])
print(word[::-1])
Where n is 3 in this example.
If you take the first part that is irregular first, it allows you to process the remaining part from front to back without hacks as before.
Use the modulo operator % to calculate the required length for the first part:
first_length = len(word) % 3
if first_length > 0:
result = word[:first_length] + ' '
else:
result = ''
result += ' '.join(word[i:i+3] for i in range(first_length, len(word), 3))
This can be made somewhat more generic and elegant by writing a generator function:
def split_from_right(word, n):
first_length = len(word) % n
if first_length > 0:
yield word[:first_length]
for i in range(first_length, len(word), n):
yield word[i:i + n]
result = ' '.join(split_from_right(word, 3))
I'm trying to make a Pig Latin translator but if you type in more then two words for an input the .pop function starts to go nuts and I cant figure out why. Information and a fix would be helpful. Thanks.
x = input("Type phrase or word you would like to be translated to pig latin:")
x = x.strip()
y = x.split()
z = []
n = len(y) -1
a = 0
for i in range(0, n):
first_word = y.pop(a)
pig_latin = first_word[1:len(first_word)] + first_word[0] + "ay"
a += 1
z.append(pig_latin)
print(pig_latin)
You have several problems. First, you keep reducing the size of the list with pop(a) but also increment a. a eventually exceeds the size of the now-diminished list and you get the error. As a first cut, we can fix the bugs in the original
x = input("Type phrase or word you would like to be translated to pig latin:")
x = x.strip()
y = x.split()
z = []
#n = len(y) -1
n = len(y)
#a = 0
for i in range(0, n):
first_word = y.pop(0)
pig_latin = first_word[1:len(first_word)] + first_word[0] + "ay"
#a += 1
z.append(pig_latin)
#print(pig_latin)
print(" ".join(z))
But there is no advantage to doing the error prone indexing. We could shorten the program to
x = input("Type phrase or word you would like to be translated to pig latin:")
y = x.strip().split()
z = []
for word in y:
pig_latin = word[1:] + word[0] + "ay"
z.append(pig_latin)
print(" ".join(z))
Or use list comprehensions to reduce it further still
x = input("Type phrase or word you would like to be translated to pig latin:")
z = [word[1:] + word[0] + "ay" for word in x.strip().split()]
print(" ".join(z))
I want to create a new string from a given string with alternate uppercase and lowercase.
I have tried iterating over the string and changing first to uppercase into a new string and then to lower case into another new string again.
def myfunc(x):
even = x.upper()
lst = list(even)
for itemno in lst:
if (itemno % 2) !=0:
even1=lst[1::2].lowercase()
itemno=itemno+1
even2=str(even1)
print(even2)
Since I cant change the given string I need a good way of creating a new string alternate caps.
Here's a onliner
"".join([x.upper() if i%2 else x.lower() for i,x in enumerate(mystring)])
You can simply randomly choose for each letter in the old string if you should lowercase or uppercase it, like this:
import random
def myfunc2(old):
new = ''
for c in old:
lower = random.randint(0, 1)
if lower:
new += c.lower()
else:
new += c.upper()
return new
Here's one that returns a new string using with alternate caps:
def myfunc(x):
seq = []
for i, v in enumerate(x):
seq.append(v.upper() if i % 2 == 0 else v.lower())
return ''.join(seq)
This does the job also
def foo(input_message):
c = 0
output_message = ""
for m in input_message:
if (c%2==0):
output_message = output_message + m.lower()
else:
output_message = output_message + m.upper()
c = c + 1
return output_message
Here's a solution using itertools which utilizes string slicing:
from itertools import chain, zip_longest
x = 'inputstring'
zipper = zip_longest(x[::2].lower(), x[1::2].upper(), fillvalue='')
res = ''.join(chain.from_iterable(zipper))
# 'iNpUtStRiNg'
Using a string slicing:
from itertools import zip_longest
s = 'example'
new_s = ''.join(x.upper() + y.lower()
for x, y in zip_longest(s[::2], s[1::2], fillvalue=''))
# ExAmPlE
Using an iterator:
s_iter = iter(s)
new_s = ''.join(x.upper() + y.lower()
for x, y in zip_longest(s_iter, s_iter, fillvalue=''))
# ExAmPlE
Using the function reduce():
def func(x, y):
if x[-1].islower():
return x + y.upper()
else:
return x + y.lower()
new_s = reduce(func, s) # eXaMpLe
This code also returns alternative caps string:-
def alternative_strings(strings):
for i,x in enumerate(strings):
if i % 2 == 0:
print(x.upper(), end="")
else:
print(x.lower(), end= "")
return ''
print(alternative_strings("Testing String"))
def myfunc(string):
# Un-hash print statements to watch python build out the string.
# Script is an elementary example of using an enumerate function.
# An enumerate function tracks an index integer and its associated value as it moves along the string.
# In this example we use arithmetic to determine odd and even index counts, then modify the associated variable.
# After modifying the upper/lower case of the character, it starts adding the string back together.
# The end of the function then returns back with the new modified string.
#print(string)
retval = ''
for space, letter in enumerate(string):
if space %2==0:
retval = retval + letter.upper()
#print(retval)
else:
retval = retval + letter.lower()
#print(retval)
print(retval)
return retval
myfunc('Thisisanamazingscript')
I have already completed the task but in its most basic form looking for help shortening it and so it can apply to any word not just one with eight letters, here's what I've got so far (bit long for what it does):
alpha = map(chr, range(97, 123))
word = "computer"
word_list = list(word)
one = word[0]
two = word[1]
three = word[2]
four = word[3]
five = word[4]
six = word[5]
seven = word[6]
eight = word[7]
one_index = str(alpha.index(one))
two_index = str(alpha.index(two))
three_index = str(alpha.index(three))
four_index = str(alpha.index(four))
five_index = str(alpha.index(five))
six_index = str(alpha.index(six))
seven_index = str(alpha.index(seven))
eight_index = str(alpha.index(eight))
print (one + "=" + one_index)
print (two + "=" + two_index)
print (three + "=" + three_index)
print (four + "=" + four_index)
print (five + "=" + five_index)
print (six + "=" + six_index)
print (seven + "=" + seven_index)
print (eight + "=" + eight_index)
What you are probably looking for is a for-loop.
Using a for-loop your code could look like this:
word = "computer"
for letter in word:
index = ord(letter)-97
if (index<0) or (index>25):
print ("'{}' is not in the lowercase alphabet.".format(letter))
else:
print ("{}={}".format(letter, str(index+1))) # +1 to make a=1
If you use
for letter in word:
#code
the following code will be executed for every letter in the word (or element in word if word is a list for example).
A good start to learn more about loops is here: https://en.wikibooks.org/wiki/Python_Programming/Loops
You can find tons of ressources in the internet covering this topic.
Use for loop for loop,
alpha = map(chr, range(97, 123))
word = "computer"
for l in word:
print '{} = {}'.format(l,alpha.index(l.lower()))
Result
c = 2
o = 14
m = 12
p = 15
u = 20
t = 19
e = 4
r = 17
Start with a dict that maps each letter to its number.
import string
d = dict((c, ord(c)-ord('a')) for c in string.lowercase)
Then pair each letter of your string to the appropriate index.
result = [(c, d[c]) for c in word]
thanks for the help managed to solve it myself in a different way using a function and a while loop, not as short but will work for all lower case words:
alpha = map(chr, range (97,123))
word = "computer"
count = 0
y = 0
def indexfinder (number):
o = word[number]
i = str(alpha.index(o))
print (o + "=" + i)
while count < len(word):
count = count + 1
indexfinder (y)
y = y+1