I don't know if you're familiar with the P-language or if it's something that's just known in my country. Basically, everytime you come across a vowel in a word, you replace the vowel the same vowel + p + the vowel again.
So 'home' would be 'hopomepe' in the p-language.
Now I'm tasked to decipher the p-language and turn sentences that are written in the p-language back to normal.
p = str(input())
for letter in range(1, len(p)):
if p[letter]=='.':
break
if p[letter-1]==p[letter+1] and p[letter]=='p':
p = p[:letter-1] + p[letter+1:]
print(p)
This is my code so far, it works except I don't know how to make it work for double vowel sounds like 'io' in scorpion (scoporpiopion) for example.
Also when a sentence starts with a vowel, this code doesn't work on that vowel.
For example 'Apan epelepephapant' becomes 'Apan elephant' with my code.
And my code crashes with string index out of bounds when it doesn't end on '.' but it crashes everytime when I don't have that if for the '.' case.
TLDR; How can I get change my code so it works for double vowels and at the start of my sentence.
EDIT: To clarify, like in my example, combination vowels should count as 1 vowel. Scorpion would be Scoporpiopion instead of Scoporpipiopon, boat would be boapoat, boot would be boopoot, ...
You can do it using regular expressions:
import re
def decodePLanguage(p):
return re.subn(r'([aeiou]+)p\1', r'\1', p, flags=re.IGNORECASE)[0]
In [1]: decodePLanguage('Apan epelepephapant')
Out[1]: 'An elephant'
In [2]: decodePLanguage('scoporpiopion')
Out[2]: 'scorpion'
This uses re.subn function to replace all regex matches.
In r'([aeiou]+)p\1', the [aeiou]+ part matches several vowels in a row, and \1 ensures you have the same combination after a p.
Then r'\1' is used to replace the whole match with the first vowel group.
EDIT: working code
def decipher(p):
result = ''
while len(p) > 2:
# first strip out all the consecutive consonants each iteration
idx = 0
while p[idx].lower() not in 'aeiou' and idx < len(p) - 2:
idx += 1
result += p[:idx]
p = p[idx:]
# if there is any string remaining to process, that starts with a vowel
if len(p) > 2:
idx = 0
# scan forward until 'p'
while p[idx].lower() != 'p':
idx += 1
# sanity check
if len(p) < (idx*2 + 1) or p[:idx].lower() != p[idx+1:2*idx+1].lower():
raise ValueError
result += p[:idx]
p = p[2*idx+1:]
result += p
return result
In your example input 'Apan epelepephapant', you compare 'A' == 'a' and get False. It seems you want to compare 'a' == 'a', that is, the str.lower() of each.
It also seems you don't check if the character before the p and after the p is a vowel; that is, if you come across the string hph, as written, your function deciphers it to simply h.
Earlier version of code below:
def decipher(p):
while len(p) > 2:
if p[0].lower() in 'aeiou' and p[0].lower() == p[2].lower() and p[1] == 'p':
result += p[0]
p = p[3:]
else:
result += p[0]
p = p[1:]
result += p
return result
called as e.g.
p = str(input())
print(decipher(p))
Since #Kolmar already gave a regex solution, I'm going to add one without regex
To help think through this, I'm going to first show you my solution to encode a regular string into p-language. In this approach, I group the characters in the string by whether or not they are vowels using itertools.groupby(). This function groups consecutive elements having the same key in the same group.
def p_encode(s):
vowels = {'a', 'e', 'i', 'o', 'u'}
s_groups = [(k, list(v)) for k, v in itertools.groupby(s, lambda c: c.lower() in vowels)]
# For scorpion, this will look like this:
# [(False, ['s', 'c']),
# (True, ['o']),
# (False, ['r', 'p']),
# (True, ['i', 'o']),
# (False, ['n'])]
p_output = []
# Now, we go over each group and do the encoding for the vowels.
for is_vowel_group, group_chars in s_groups:
p_output.extend(group_chars) # Add these chars to the output
if is_vowel_group: # Special treatment for vowel groups
p_output.append("p")
p_output.extend(c.lower() for c in group_chars)
return "".join(p_output)
I added a list comprehension to define s_groups to show you how it works. You can skip the list comprehension and directly iterate for is_vowel_group, group_chars in itertools.groupby(s, lambda c: c.lower() in vowels)
Now, to decode this, we can do something similar in reverse, but this time manually do the grouping because we need to process ps differently when they're in the middle of a vowel group.
I suggest you don't modify the string as you're iterating over it. At best, you'll have written some code that's hard to understand. At worst, you'll have bugs because the loop will try to iterate over more indices than actually exist.
Also, you iterate over 1..len(p), and then try to access p[i+1]. In the last iteration this will throw an IndexError. And because you want repeated vowels to count as a single group, this doesn't work. You're going to have to group the vowels and non-vowels separately, and then join them into a single string.
def p_decode(p):
vowels = {'a', 'e', 'i', 'o', 'u'}
p_groups = []
current_group = None
for c in p:
if current_group is not None:
# If the 'vowelness' of the current group is the same as this character
# or ( the current group is a vowel group
# and the current character is a 'p'
# and the current group doesn't contain a 'p' already )
if (c.lower() in vowels) == current_group[0] or \
( current_group[0] and
c.lower() == 'p' and
'p' not in current_group[1]):
current_group[1].append(c) # Add c to the current group
else:
current_group = None # Reset the current group to None so you can make it later
if current_group is None:
current_group = (c.lower() in vowels, [c]) # Make the current group
p_groups.append(current_group) # Append it to the list
# For scorpion => scoporpiopion
# p_groups looks like this:
# [(False, ['s', 'c']),
# (True, ['o', 'p', 'o']),
# (False, ['r', 'p']),
# (True, ['i', 'o', 'p', 'i', 'o']),
# (False, ['n'])]
p_output = []
for is_vowel_group, group_chars in p_groups:
if is_vowel_group:
h1 = group_chars[:len(group_chars)//2] # First half of the group
h2 = group_chars[-len(group_chars)//2+1:] # Second half of the group, excluding the p
# Add the first half to the output
p_output.extend(h1)
if h1 != h2:
# The second half of this group is not repeated characters
# so something in the input was wrong!
raise ValueError(f"Invalid input '{p}' to p_decode(): vowels before and after 'p' are not the same in group '{''.join(group_chars)}'")
else:
# Add all chars in non-vowel groups to the output
p_output.extend(group_chars)
return "".join(p_output)
And now, we have:
words = ["An elephant", "scorpion", "boat", "boot", "Hello World", "stupid"]
for w in words:
p = p_encode(w)
d = p_decode(p)
print(w, p, d, sep=" | ")
Which gives (prettification mine):
Word
Encoded
Decoded
An elephant
Apan epelepephapant
An elephant
scorpion
scoporpiopion
scorpion
boat
boapoat
boat
boot
boopoot
boot
Hello World
Hepellopo Woporld
Hello World
stupid
stupupipid
stupid
Also, words that aren't actually encoded correctly (such as "stupid") throw a ValueError
>>> p_decode("stupid")
ValueError: Invalid input 'stupid' to p_decode(): vowels before and after 'p' are not the same in group 'upi'
Related
Write a while loop that takes a string and counts the vowels. Use the string “May the force be with you.” Print the results. (Answer: 8)
Any help with this would be greatly appreciated! I kept coming up with a continuous loop. It has to use a while loop and print the number of vowels (8). Thank you!!
count = 0
vowels = ['a', 'e', 'i', 'o', 'u']
s = "May the force be with you."
while i in s:
if i in vowels:
count += 1
print(count)
The statement:
while i in s:
does not do what you think. Were that while a for, it would iterate over the string one character at a time, and probably work.
However, the expression i in s (which is what that is in a while statement) simply checks if i is one of the things in the s "collection" and gives you true or false. It does not iterate i over the s collection.
If i had been set to something, the while loop would either execute infinitely or never, depending on the value of i. If i is not bound to a value, you'll get a run-time error.
As a solution, you can iterate over the characters in a string with something like (from an actual transcript):
>>> str = "pax"
>>> for ch in str:
... print(ch)
...
p
a
x
The equivalent while version would be:
>>> str = "pax"
>>> idx = 0 # OR: idx, slen = 0, len(str)
>>> while idx < len(str): # while idx < slen:
... print str[idx]
... idx += 1
...
p
a
x
though the for variant is generally considered more Pythonic for this sort of task.
Further, you can detect if a character is one of a set of characters by using in, such as in the following transcript:
>>> str = "pax"
>>> for ch in str:
... if ch in "ABCabc":
... print(f"{ch} is either a, b, or c")
...
a is either a, b, or c
So you should be able to combine that for/while loop and if statement to count the vowels and output it (with print).
Note especially the string I use for vowel checking, it also contains the upper-case vowels. And keep in mind, though your specification may only be to use the Latin-ish vowels, the Unicode world of today would not forgive this oversight. See here for example.
Since it needs to be a while, you can slice off a character at a time and loop until the string is empty. As a quick optimization, True adds as 1 and False as 0, so the interior if can be removed.
vowels = ['a', 'e', 'i', 'o', 'u']
s = "May the force be with you."
count = 0
while s:
count += s[0] in vowels
s = s[1:]
print(count)
I think you could use something like this
phrase = "May the force be with you."
vowels = 0
count = 0
while phrase[count] != ".":
if phrase[count] in 'aeiou':
vowels += 1
count+=1
print(vowels)
I am creating a program that converts a normal English word into a form of pig-latin. I need to be able to determine if the string ends (last character) in an 'e', and if it does, replace it with ë.
I can't seem to be able to get it to work using my function. For example, the code should output the word 'happy" as "appyhë" by the end of this condition.
# User Input: Ask user for a word
WordToBeTranslated = input("Please enter a word in English: ")
WordToBeTranslatedLower = WordToBeTranslated.lower()
# Condition #1: Moving the First Letter to the end
elvish = WordToBeTranslatedLower[1:] + WordToBeTranslatedLower[0]
print(elvish)
# Condition #2 + #3: Appending a Vowel / Appending 'en' to the end of a word
vowel = ['a', 'e', 'e', 'i', 'o', 'u']
import random
randomVowel = random.choice(vowel)
list = []
list.append(WordToBeTranslated)
if len(WordToBeTranslated) > 4:
elvish += randomVowel
else:
elvish = elvish + 'en'
# Condition #4: change all k's to c's
elvish = elvish.replace('k', 'c')
print(elvish)
# Condition #5: Replace 'e' at end of the word with ë
if elvish[-1] == 'e':
elvish = elvish[-1].replace('e', 'ë')
else:
elvish = elvish
You can try:
your_string.endswith("e")
You can also use a RegEx to substitute the "e" with "ë".
import re
your_string = re.sub(r"e$", "ë")
This code:
elvish = elvish[-1].replace('e', 'ë')
doesn't at all do what you want. It reassigns elvish with just the last letter, replacing the e if necessary.
Now, you know inside this if block that the last letter is an e, so you always need to replace it. What you want to do then is to take the original string minus the last letter, and append ë. So:
elvish = elvish[:-1] + 'ë'
Also, you don't need an else block; yours does nothing, you can just remove it.
Right now I'm trying to create an oppish translator. That is, after a consonant or several consonants in a row, you add 'op' to those letters. As an example, cow would become copowop or street which would become stropeetop. This is what I have so far:
def oppish(phrase): #with this function I'm going to append 'op' or 'Op' to a string.
consonants = ['b','c','d','f','g','h','i','j','k','l','m','n','p','q','r','s','t','v','w','x','y','z']
vowels = ['a', 'e', 'i', 'o', 'u'] #this and the preceding line create a variable for the vowels we will be looking to append 'op' to.
if phrase == '': #error case. if the input is nothing then the program will return False.
return False
phrase_List = list(' ' + phrase) # turns the input phrase into a list which allows for an index to search for consonants later on.
new_phrase_List = list() #creates new list for oppish translation
for i in range(1, len(phrase_List)):
if phrase_List[i] == phrase_List[1]:
new_phrase_List.append(phrase_List[i])
elif phrase_List[i] in consonants:
new_phrase_List.append('op') #adds op to the end of a consonant within the list and then appends it to the newlist
new_phrase_List.append(phrase_List[i]) #if the indexed letter is not a consonant it is appended to the new_phrase_list.
print 'Translation: ' + ''.join(new_phrase_List)
oppish('street')
The only problem here is that the above code yields this
Translation: ssoptopreeopt
I'm not sure what I've done wrong, I've tried going through a visualizer but to no avail. All help is appreciated! :)
This is well suited for itertools.groupby, which will let you group items in an iterable using a key function. The group will accumulate until the return value of the key function changes, at which point group by will yield return value of the key function and an iterator over the accumulated group. In this case, we want our key function to return True if a letter is a vowel. That way, we'll get groups of consecutive consonants, and groups of consecutive vowels back from groupby:
from itertools import groupby
vowels = {'a', 'e', 'i', 'o', 'u'} # set instead of list, because lookups are O(1)
def oppish(phrase):
if not phrase:
return False
out = []
for is_vowel, letters in groupby(phrase, lambda x: x in vowels):
out.append(''.join(list(letters)))
if not is_vowel:
out.append('op')
return ''.join(out)
print oppish('street')
print oppish('cow')
Output:
stropeetop
copowop
I think the problem is in your approach to the problem.
Try to do something like this:
EDIT: Although there's a better (pythonic) answer in this question (thanks to dano), this one does not require additional libraries
vowels = ['a', 'e', 'i', 'o', 'u']
def oppish(word):
result = []
first = True
prev_vowel = False
for letter in list(word):
if (letter in vowels) and (not first) and (not prev_vowel):
result.append('op')
prev_vowel = True
else:
prev_vowel = False
result.append(letter)
first = False
if not prev_vowel:
result.append('op')
print ''.join(result)
oppish('street')
#> stropeetop
TIP: Don't waste your time defining both vowels and consonants. in fact, there are vowels and non-vowels
I am wondering how to write a function that replaces a letter with a word without using any built in functions. For example, eyeForI(“William”) returns “Weyelleyeam” which replaces every i with eye.
I know how to do this with a built in function which I already wrote something similar here (though in this case it changes a word with a different word):
def stringChange(s):
for old, new in (
("can't", "can not"),
("shouldn't", "should not"),
("don't", "do not"),
("won't", "will not"),
):
s = s.replace(old, new)
if "!" in s:
s=s.upper()
return s
But I do not know how to write it without using any built in functions.
I know I must use a for loop.
Strings are immutable so you'll want to convert it to a list, make changes, then convert back to a string. For your example,
def eyeForI(word):
word = list(word)
j = 0
while j < len(word):
if word[j] == 'i':
word[j] = 'eye'
j += 1
word = ''.join(word)
return word
If you are just learning the control structures, it's worth mentioning that this can also be accomplished with a for loop instead of a while loop.
def eyeForI(word):
# convert the string word into a list
# word = ['W', 'i', 'l', 'l', 'i', 'a', 'm']
word = list(word)
# loop over indices of the list. len(word) = 7 so i runs from 0-6
for j in xrange(len(word)):
if word[j] == 'i': # if the j'th item in word == "i"
word[j] = 'eye' # change it to "eye"
word = ''.join(word) # join method, explained below
return word
The join method can be confusing at first. It will join all the elements of its argument (in this case word) using the string that calls it as a separator (in this case ''). So we just say, "join the elements of word using an empty string to separate them." Note that you can also build another string from scratch using the + operator and iterating through the original word string if you like (see other answers).
Here's something for you to try and take apart. Rather than a for loop, it involves generators, dictionary with a default argument to get, and join. You can iterate through a string, which means you do not need to convert it into a list first.
s1 = "William"
subs = {'i': 'eye'}
s2 = ''.join(subs.get(c, c) for c in s1)
print(s2)
Here is a solution that does not call anything that would reasonably be called a function or method. It is not very "pythonic" however. It would be difficult to extend due to the hard-coding of the condition, and repeated addition of strings is not preferred.
def eyeForI(word):
result = "" # create an empty string so we can add to it
for c in word: # c will be set to each character in turn
if c == 'i':
result += 'eye' # add the word to the end of result
else:
result += c # add the letter to the end of result
return result
assert eyeForI("William") == "Weyelleyeam" # test it works
I like list comprehensions :)
Why write a whole function if all you need is to perform an specific task which can be done in one line.
You can create a list of the letters:
>>> print [letter if letter is not 'i' else 'eye' for letter in "william" ]
['w', 'eye', 'l', 'l', 'eye', 'a', 'm']
and use the join function to put them together:
>>> print "".join([letter if letter is not 'i' else 'eye' for letter in "william" ])
weyelleyeam
My homework assignment is to Write a program that reads a string from the user and creates a list of words from the input.Create two lists, one containing the words that contain at least one upper-case letter and one of the words that don't contain any upper-case letters.
Use a single for loop to print out the words with upper-case letters in them, followed by the words with no upper-case letters in them, one word per line.
What I know is not correct:
s= input("Enter your string: ")
words = sorted(s.strip().split())
for word in words:
print (word)
Because it only sorts the sequence if the Capitol is in the first character. For this assignment a character could appear any where within a word. Such as, 'tHis is a sTring'.
I was playing around with a solution that looked similar to this, just to see if I could get the words with CAPS out..But it just wasnt working:
s = input("Please enter a sentence: ")
while True:
cap = 0
s = s.strip().split()
for c in s:
if c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
print(c[:cap])
cap += 1
else:
print("not the answer")
break
But a regular expression would probably do a better job than writing out the whole alphabet.
Any help is much appreciated. Needless to say I am new to python.
>>> w = 'AbcDefgHijkL'
>>> r = re.findall('([A-Z])', word)
>>> r
['A', 'D', 'H', 'L']
This can give you all letters in caps in a word...Just sharing the idea
>>> r = re.findall('([A-Z][a-z]+)', w)
>>> r
['Abc', 'Defg', 'Hijk']
Above will give you all words starting with Caps letter. Note: Last one not captured as it does not make a word but even that can be captured
>>> r = re.findall('([A-Z][a-z]*)', w)
>>> r
['Abc', 'Defg', 'Hijk', 'L']
This will return true if capital letter is found in the word:
>>> word = 'abcdD'
>>> bool(re.search('([A-Z])', word))
Hint: "Create two lists"
s= input("Enter your string: ")
withcap = []
without = []
for word in s.strip().split():
# your turn
The way you are using the for .. else in is wrong - the else block is executed when there is no break from the loop. The logic you are trying to do looks like this
for c in s:
if c.isupper():
# s contains a capital letter
# <do something>
break # one such letter is enough
else: # we did't `break` out of the loop
# therefore have no capital letter in s
# <do something>
which you can also write much shorter with any
if any(c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" for c in s):
# <do something>
else:
# <do something>
Sounds like regexs would be easier for the first part of the problem (a regex that just looks for [A-Z] should do the trick).
For the second part, I'd recommend using two lists, as that's an easy way to print everything out in one for loop. Have one list of non_upper_words and one of upper_words.
So, the basic outline of the program would be:
split the string into an array of words.
for each word in array: if regex returns true, add to upper_words. Else: add to non_upper_words.
print each word in the first array and then in the second.
I wrote this out in pseudo-code because it's a programming assignment, so you should really write the actual code yourself. Hope it helps!
You can use isupper method for your purpose:
text = 'sssample Text with And without'
uppers = []
lowers = []
# Note that loop below could be modified to skip ,.-\/; and etc if neccessary
for word in text.split():
uppers.append(word) if word[0].isupper() else lowers.append(word)
EDITED: You can also use islower method the following way:
text = 'sssample Text with And without'
other = []
lowers = []
# Note that loop below could be modified to skip ,.-\/; and etc if neccessary
for word in text.split():
lowers.append(word) if word.islower() else other.append(word)
OR depends on what you really need you can take a look at istitle method:
titled = []
lowers = []
for word in text.split():
titled.append(word) if word.istitle() else lower.append(word)
AND with simple if else statement:
titled = []
lowers = []
for word in text.split():
if word.istitle():
titled.append(word)
else:
lower.append(word)
You can use List Comprehensions to get all upper case characters and lower case characters.
def get_all_cap_lowercase_list(inputStr):
cap_temp_list = [c for c in inputStr if c.isupper()]
low_temp_list = [c for c in inputStr if c.islower()]
print("List of Cap {0} and List of Lower {1}".format(cap_temp_list,low_temp_list))
upper_case_count = len(cap_temp_list)
lower_case_count = len(low_temp_list)
print("Count of Cap {0} and Count of Lower {1}".format(upper_case_count,lower_case_count))
get_all_cap_lowercase_list("Hi This is demo Python program")
And The output is:
List of Cap ['H', 'T', 'P'] and List of Lower ['i', 'h', 'i', 's',
'i', 's', 'd', 'e', 'm', 'o', 'y', 't', 'h', 'o', 'n', 'p', 'r', 'o',
'g', 'r', 'a', 'm']
Count of Cap 3 and Count of Lower 22
Try doing the following:
Split the string into a list where each item is a separate word.
For every word in that list, iterate through and check for capital letters (consider the string constants such as string.uppercase). If it has a capital letter, insert it onto the front of your result list. If not, append it to the end of your result list.
Iterate through your results, printing them. Or, if you want to avoid iterating, join the items in the string using the newline character \n.
Thank you to everyone for your input and help, it was all very informative. Here is the answer that I finally submitted.
s = input("Please enter a sentence: ")
withcap = []
without = []
for word in s.split():
if word.islower():
without.append(word)
else:
withcap.append(word)
onelist = withcap + without
for word in onelist:
print (word)
I think your answer might only be searching for words where the first letter is capitalized. To find words that contain a capital letter anywhere in the word, you'd have to enumerate over each letter in the word, like this:
uin = input("Enter your text: ")
##create lists to hold upper and lower case words
up_words = []
no_up_words = []
for i, word in enumerate(uin.strip().split()):
if word.islower():
no_up_words.append(word)
else:
up_words.append(word)
print(up_words, no_up_words)
My regex:
vendor = "MyNameIsJoe. IWorkInDDFinc."
ven = re.split(r'(?<=[a-z])[A-Z]|[A-Z](?=[a-z])', vendor)
I need split word that would have happened:
My Name Is Joe. I Work In DDF inc.