Python Hacker Rank Two Way Emunese Translator - python

This problem asks me to make a two way translator, English to Emunese(made up language) and Emunese to English - I have to take the last letter from each word and move it to the front of the word, add mu after each word, and add emu after every three words (ie. 'imu odmu tnomu emu wknomu whomu otmu emu odmu sthimu' is the English sentence 'i do not know how to do this' translated to Emunese and of course the opposite for when I'm converting the sentence to English). At first I thought this would be relatively simple. Through my own test it seems to run fine, change the sentence to Emunese and you'll see that it converts to English. The problem occurs when I plug the code into Hacker Rank. Again, the code seems to run fine on the visible test cases (Ones where I can see the output and input). The problem occurs on the hidden test cases, where two of the test cases return 'Wrong Answer'. I've been scratching my head trying to figure out what my code is missing, but I cant quite think of it.
Here is the Hack Rank link:
https://www.hackerrank.com/contests/hcpc19-div-i/challenges/hcpc-19-div-i-two-way-emunese-translator
This code can be plugged in anywhere (Under this is code that can be plugged directly into hacker rank):
sentence = ['i', 'dont', 'know','how', 'to', 'do','this']
#Which version you want to convert the sentence to
lang = 'EMU'
n = len(sentence)
if lang == 'ENG':
#Move the last letter to the front
sentence = " ".join([words[-1:] + words[:-1] + 'mu' for words in sentence])
result = []
#Add emu after every three words
for idx, word in enumerate(sentence.split()):
if idx > 1 and idx % 3 == 0:
result.append("emu")
result.append(word)
#If sentence is 3, 6, 9, etc letters long add emu to the end
if n % 3 == 0:
result.append("emu")
sentence = " ".join(result)
print(sentence)
elif lang == 'EMU':
sentence = ' '.join(sentence)
#Get rid of mu and emu
sentence = sentence.replace('mu', '')
sentence = sentence.replace('e ', '')
#Move the first letter to the end of the word
print( " ".join([words[1:] + words[0] for words in sentence.split()]))
This code has to be plugged into Hacker Rank to work (Look up for a version that can be plugged in anywhere):
if lang == 'ENG':
#Move the last letter to the front
sentence = " ".join([words[-1:] + words[:-1] + 'mu' for words in sentence])
result = []
#Add emu after every three words
for idx, word in enumerate(sentence.split()):
if idx > 1 and idx % 3 == 0:
result.append("emu")
result.append(word)
#If sentence is 3, 6, 9, etc letters long add emu to the end
if n % 3 == 0:
result.append("emu")
return " ".join(result)
elif lang == 'EMU':
sentence = ' '.join(sentence)
#Get rid of mu and emu
sentence = sentence.replace('mu', '')
sentence = sentence.replace('e ', '')
#Move the first letter to the end of the word
return " ".join([words[1:] + words[0] for words in sentence.split()])

Here is the fixed code. In the elif lang == "EMU" statement
for idx, word in enumerate(sentence):
if idx > 1 and idx % 3 == 0:
sentence.remove(word)
sentence = " ".join([words[:-2] for words in sentence])
sentence = " ".join([words[1:] + words[0] for words in sentence.split()])
print(sentence)

Related

Getting the maximum number of words in a sentence of a paragraph Python

I'm trying to get the maximum numbers of words inside a sentence of a paragraph but just can't see it.
Here is what I tried:
S = input("Enter a paragraph")
def getMaxNum(S):
if "." in S:
new_list = S.split(".")[0]
return len(new_list)
else "?" in S:
new_list = S.split("?")[0]
return len(new_list)
else "!" in S:
new_list = S.split("?")[0]
return len(new_list)
getMaxNum(S)
In the else statement I could be getting the previous sentence values but that's not what I need to get. Any ideas how can I accomplish that?
I'm not 100% certain of what your requirements are, but if I borrow Buoy Rina's input, here's a solution using regular expressions (pattern search strings):
#!/usr/bin/env python3
import re
text = "I will go school tomorrow. I eat apples. Here is a six word sentence."
max_words = 0
sentences = re.split("[.!?]", text)
for sentence in sentences:
max_words = max( len( sentence.split() ), max_words )
print(f"max_words: {max_words}")
The re.split() breaks the text (or paragraph) into sentences based on "some" end of sentence punctuation. There are likely conditions under which searching for period '.' won't yield a complete sentence, but we'll ignore that for simplicity.
The string function split() then breaks up the sentence into words based on white space (the default of split()). We then get the length of the resultant list to find the word count.
text = "I will go school tomorrow. I eat apples. I will have a very long sentence. "
def getmaxwordcount(text):
count_word = 0
is_start_word = False
counts = []
for c in text:
if c == ' ':
if is_start_word:
count_word += 1
is_start_word = False
elif c == '!' or c == '.' or c == '?':
if is_start_word:
count_word += 1
is_start_word = False
counts.append(count_word)
count_word = 0
else:
if c.isalpha():
if is_start_word == False:
is_start_word = True
return max(counts)
getmaxwordcount(text) # 7
import re
text = "I will go school tomorrow. I eat apples."
def foo(txt):
max_count=0
for i in re.split('[!.?]',txt):
if len(i.split()) > max_count:
max_count = len(i.split())
return max_count
print(foo(text)) # returns 5
code
import re
paragraph = "Two words. Three other words? Finally four another words!"
all_lengths_in_paragraph = [f"Length of {n+1}th sentence is {len(list(filter(None, x.split(' '))))}" for n, x in enumerate(list(filter(None, re.split('\.|!|\?', paragraph))))]
max_length = max([len(list(filter(None, x.split(' ')))) for x in list(filter(None, re.split('\.|!|\?', paragraph)))])
for one_length in all_lengths_in_paragraph:
print(r)
print('maximum length is', max_length)
output
Length of 1th sentence is 2
Length of 2th sentence is 3
Length of 3th sentence is 4
maximum length is 4

Convert the string to a string in which the words are separated by spaces and only the first word starts with an uppercase letter [duplicate]

This question already has answers here:
Split a string at uppercase letters
(22 answers)
Closed 2 years ago.
I am trying to make a script that will accept a string as input in which all of the words are run together, but the first character of each word is uppercase. It should convert the string to a string in which the words are separated by spaces and only the first word starts with an uppercase letter.
For Example (The Input):
"StopWhateverYouAreDoingInterestingIDontCare"
The expected output:
"Stop whatever you are doing interesting I dont care"
Here is the one I wrote so far:
string_input = "StopWhateverYouAreDoingInterestingIDontCare"
def organize_string():
start_sentence = string_input[0]
index_of_i = string_input.index("I")
for i in string_input[1:]:
if i == "I" and string_input[index_of_i + 1].isupper():
start_sentence += ' ' + i
elif i.isupper():
start_sentence += ' ' + i.lower()
else:
start_sentence += i
return start_sentence
While this takes care of some parts, I am struggling with differentiating if the letter "I" is single or a whole word. Here is my output:
"Stop whatever you are doing interesting i dont care"
Single "I" needs to be uppercased, while the "I" in the word "Interesting" should be lowercased "interesting".
I will really appreciate all the help!
A regular expression will do in this example.
import re
s = "StopWhateverYouAreDoingInterestingIDontCare"
t = re.sub(r'(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z])', ' ', s)
Explained:
(?<=[a-z])(?=[A-Z]) - a lookbehind for a lowercase letter followed by a lookahead uppercase letter
| - (signifies or)
(?<=[A-Z])(?=[A-Z]) - a lookbehind for a uppercase letter followed by a lookahead uppercase letter
This regex substitutes a space when there is a lowercase letter followed by an uppercase letter, OR, when there is an uppercase letter followed by an uppercase letter.
UPDATE: This doesn't correctly lowercase the words (with the exception of I and the first_word)
UPDATE2: The fix to this is:
import re
s = "StopWhateverYouAreDoingInterestingIDontCare"
first_word, *rest = re.split(r'(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z])', s)
rest = [word.lower() if word != 'I' else word for word in rest]
print(first_word, ' '.join(rest))
Prints:
Stop whatever you are doing interesting I dont care
Update 3: I looked at why your code failed to correctly form the sentence (which I should have done in the first place instead of posting my own solution :-)).
Here is the corrected code with some remarks about the changes.
string_input = "StopWhateverYouAreDoingInterestingIDontCare"
def organize_string():
start_sentence = string_input[0]
#index_of_i = string_input.index("I")
for i, char in enumerate(string_input[1:], start=1):
if char == "I" and string_input[i + 1].isupper():
start_sentence += ' ' + char
elif char.isupper():
start_sentence += ' ' + char.lower()
else:
start_sentence += char
return start_sentence
print(organize_string())
!. I commented out the line index_of_i = string_input.index("I") as it doesn't do what you need (it finds the index of the first capital I and not an I that should stand alone (it finds the index of the I in Interesting instead of the IDont further in the string_input string). It is not a correct statement.
for i, char in enumerate(string_input[1:], 1) enumerate states the index of the letters in the string starting at 1 (since string_input[1:] starts at index 1 so they are in sync). i is the index of a letter in string_input.
I changed the i's to char to make it clearer that char is the character. Other than these changes, the code stands as you wrote it.
Now the program gives the correct output.
string_input = "StopWhateverYouAreDoingInterestingIDontCare"
counter = 1
def organize_string():
global counter
start_sentence = string_input[0]
for i in string_input[1:]:
if i == "I" and string_input[counter+1].isupper():
start_sentence += ' ' + i
elif i.isupper():
start_sentence += ' ' + i.lower()
else:
start_sentence += i
counter += 1
print(start_sentence)
organize_string()
I made some changes to your program. I used a counter to check the index position. I get your expected output:
Stop whatever you are doing interesting I dont care
s = 'StopWhateverYouAreDoingInterestingIDontCare'
ss = ' '
res = ''.join(ss + x if x.isupper() else x for x in s).strip(ss).split(ss)
sr = ''
for w in res:
sr = sr + w.lower() + ' '
print(sr[0].upper() + sr[1:])
output
Stop whatever you are doing interesting i dont care
I hope this will work fine :-
string_input = "StopWhateverYouAreDoingInterestingIDontCare"
def organize_string():
i=0
while i<len(string_input):
if string_input[i]==string_input[i].upper() and i==0 :
print(' ',end='')
print(string_input[i].upper(),end='')
elif string_input[i]==string_input[i].upper() and string_input[i+1]==string_input[i+1].upper():
print(' ',end='')
print(string_input[i].upper(),end='')
elif string_input[i]==string_input[i].upper() and i!=0:
print(' ',end='')
print(string_input[i].lower(),end='')
if string_input[i]!=string_input[i].upper():
print(string_input[i],end='')
i=i+1
organize_string()
Here is one solution utilising the re package to split the string based on the upper case characters. [Docs]
import re
text = "StopWhateverYouAreDoingInterestingIDontCare"
# Split text by upper character
text_splitted = re.split('([A-Z])', text)
print(text_splitted)
As we see in the output below the separator (The upper case character) and the text before and after is kept. This means that the upper case character is always followed by the rest of the word. The empty first string originates from the first upper case character, which is the first separator.
# Output of print
[
'',
'S', 'top',
'W', 'hatever',
'Y', 'ou',
'A', 're',
'D', 'oing',
'I', 'nteresting',
'I', '',
'D', 'ont',
'C', 'are'
]
As we have seen the first character is always followed by the rest of the word. By combining the two we have the splitted words. This also allows us to easily handle your special case with the I
# Remove first character because it is always empty if first char is always upper
text_splitted = text_splitted[1:]
result = []
for i in range(0, len(text_splitted), 2):
word = text_splitted[i]+text_splitted[i+1]
if (i > 0) and (word != 'I') :
word = word.lower()
result.append(word)
result = ' '.join(result)
split the sentence into individual words. If you find the word "I" in this list, leave it alone. Leave the first word alone. All of the other words, you cast to lower case.
You have to use some string manipulation like this:
output=string_input[0]
for l in string_input[1:]:
if l.islower():
new_s+=l
else:
new_s+=' '+l.lower()
print(output)

using a while True loop

Problem 1.
This problem provides practice using a while True loop. Write a function named
twoWords that gets and returns two words from a user. The first word is of a
specified length, and the second word begins with a specified letter.
The function twoWords takes two parameters:
an integer, length, that is the length of the first word and
a character, firstLetter, that is the first letter of the second word.
The second word may begin with either an upper or lower case instance of
firstLetter. The function twoWords should return the two words in a list. Use
a while True loop and a break statement in the implementation of twoWords. The
following is an example of the execution of twoWords:
print(twoWords(4, 'B')):
A 4-letter word please two
A 4-letter word please one
A 4-letter word please four
A word beginning with B please apple
A word beginning with B please pear
A word beginning with B please banana
['four', 'banana']
This is what I have so far, but it keeps asking me the first question over again
even if I have the right word length. What am I doing wrong?
def twoWords(length, firstLetter):
wordLen = input('A 4-letter word please ')
while len(wordLen) != int(length):
wordlen = input('A 4-letter word please ')
word = input('A word beginning with ' + firstLetter + ' please ')
while word[0] != firstLetter:
word = input('A word beginning with ' + firstLetter + ' please ')
return[wordLen, word]
def twoWords(length,firstLetter):
firstWord = ""
secondWord= ""
while True:
firstWord = input('A ' + str(length) + '-letter word please.')
if length == len(firstWord):
break
while True:
secondWord = input('A word beginning with ' + firstLetter+ ' please')
if secondWord[0] == firstLetter.upper() or secondWord[0] == firstLetter.lower():
break
return [firstWord,secondWord]
print(twoWords(4,'B'))
def twoWord(length, firstLetter):
while True:
word1=(input("Enter a "+ str(length)+"-letter word please:"))
if len(word1)==int(length):
break
while True:
word2=input("Please enter the word beginning with "+firstLetter+" please:")
if word2[0].upper()==firstLetter or word2[0].lower()==firstLetter:
break
return word1, word2
print(twoWord(5, 'b'))

Why are wrong meanings returned in this implementation of the Simplified Lesk Algorithm?

The Simplified Lesk algorithm, in trying to disambiguate the meaning of a word in a given sentence does the following:
context <- all the words except the target word from the sentence.
signature <- words appearing in the dictionary definition of target word + any words appearing in the examples used to illustrate usage of the word.
Finally, that meaning is selected for which there are maximum number of common words between context and signature
My problem is that given two different meanings of the word time (for example) that have the same value of count, is there a way to get the correct meaning?
My code when used for the sentence "Time flies like an arrow" is unable to return the correct interpretation of the words.
import string
from nltk.corpus import wordnet as wn
def printMeaning(valid, word, sense, maxCount):
if valid == "Found":
print("The word '" + word + "' has meaning :'" + sense + "' and count :" +str(maxCount))
return
elif valid =="Default":
print("The word '" + word + "' has meaning :'" + sense +". Default meaning selected since results were inconclusive" )
return
elif valid =="Standard":
print("The word '" + word + "' has no disambiguity")
return
def findSense(sentence):
for word in sentence.split(" "):
# Strip word of any punctuations and make it lower case
exclude = set(string.punctuation)
word = ''.join(ch for ch in word if ch not in exclude)
word.lower()
# If word is a stop word, continue to next iteration.
skip_words = ['a', 'an', 'the', 'this', 'that', 'and']
if skip_words.__contains__(word):
printMeaning("Standard", word, "", 0)
continue
# Get the context
context = sentence.split(" ")
if word in context:
context.remove(word)
# Initialize maxCount and sense of the word to default values.
maxCount = 0
count = 0
sense = "Nothing makes sense"
example_words = []
# For every meaning of the word,
for meaning in wn.synsets(word):
# Generate 'signature' by adding words from definition and examples.
for each_usage in meaning.examples():
example_words += each_usage.split(" ")
definition_words = meaning.definition().split(" ")
signature = example_words + definition_words
# How many times do the context words appear in the signature?
for w in context:
count += signature.count(w)
# If count exceeds current maxCount then, update the sense of the word
if count > maxCount:
sense = meaning.definition()
maxCount = count
count = 0
# If the count remained 0 for the word, pick the most common meaning from WordNet if it exists
if sense == "Nothing makes sense":
firstMeaning = wn.synsets(word)
if len(firstMeaning) == 0: # word doesn't exist in our dictionary
printMeaning("Default", word, "word not found in our dictionary", 0)
continue
else:
printMeaning("Default", word, firstMeaning[0].definition(), 0)
continue
# Print the calculated meaning of the word
printMeaning("Found", word, sense, maxCount)
if __name__ == '__main__':
sentence = input("Enter sentence: ")
findSense(sentence)

Translating Pig Latin into English Using Python 3

As you will see in my code below, I have already made a program that translates from English into Pig Latin. It follows two rules:
If the word begins with a vowel, "way" should be appended (example: apple becomes appleway)
If the word begins with a sequence of consonants, this sequence should be moved to the end, prefixed with "a" and followed by "ay" (example: please becomes easeaplay)
I know this is an odd way to do it, but just humour me.
The issue: when translating into English, I can't think of a way to let the code know at exactly which point it should separate the root of the original word from the suffix because some words begin with 1 consonant, others with 2 consonants, etc.
Any help would be appreciated. Please bear in mind that I am a novice.
vowels = ('AEIOUaeiou')
def toPigLatin(s):
sentence = s.split(" ")
latin = ""
for word in sentence:
if word[0] in vowels:
latin += word + "way" + " "
else:
vowel_index = 0
for letter in word:
if letter not in vowels:
vowel_index += 1
continue
else:
break
latin += word[vowel_index:] + "a" + word[:vowel_index] + "ay" + " "
return latin[:len(latin) - 1]
def toEnglish(s):
sentence = s.split(" ")
english = ""
for word in sentence:
if word[:len(word) - 4:-1] == 'yaw':
english += word[:len(word) - 3] + " "
else:
#here's where I'm stuck
return english
Thanks in advance!
Kevin wis right about completely unambiguous translation being impossible, but I think this is probably what you're looking for:
def toEnglish(s):
sentence = s.split(" ")
english = ""
for word in sentence:
if word[:len(word) - 4:-1] == 'yaw':
english += word[:len(word) - 3] + " "
else:
noay = word[:len(word) - 2]
firstconsonants = noay.split("a")[-1]
consonantsremoved = noay[:len(noay) - (len(firstconsonants)+1)]
english += firstconsonants + consonantsremoved + " "
return english
Although this will not succeed for every pig latin word, as Kevin and ghoti have noted, you can get pretty close by looking for that special 'a' you are adding.
First, get rid of the extra 'ay' at the end, since it will throw off the search for your special 'a':
>>> tmp = word[:-2]
>>> tmp
'easeapl'
Then, use find or index in order to get the location of that special 'a'. Note that it will search from the beginning of the string, so you should reverse the string temporarily:
>>> tmp = tmp[::-1]
>>> tmp
'lpaesae'
>>> ind = tmp.index('a')
>>> ind
2
Now, take the part to the left of that index and the part to the right of that index, reverse each of them, and reassemble. These slices start to get pretty tricky, so bear with me:
>>> prefix = tmp[ind-1::-1]
>>> prefix
'pl'
>>> suffix = tmp[:ind:-1]
>>> suffix
'ease'
>>> english = prefix + suffix
>>> english
'please'
For some more info on slicing, see this great answer.
I do see your problem.
strap -> apstray seems pretty straightforward. But by your rules it might reverse to rapst or traps.
Perhaps one way to do this is to cycle through possibilities until you find a word that matches a word in English. You could make a word list:
with open("/usr/share/dict/words","r") as f:
wordlist = f.read().splitlines()
Then in toEnglish, step back through each iteration of the mutation (add a if word in wordlist: to test each of rapst, traps, etc). and settle on a word if it's in the list.
This method is guaranteed to fail on words like "strap". :-) YMMV.
def toEnglish(s):
sentence = s.split(" ")
english = ""
for word in sentence:
if word[:len(word) - 4:-1] == 'yaw':
english += word[:len(word) - 3] + " "
else:
index = -3
# count consonent between two last a
for letter in reversed(word[:-3]):
if letter is not 'a':
index-=1
else:
break
english += word[index:-2] + word[:index-1] + " "
return english
Should to the trick :)
Well, for me, I just do this:
word = "python"
word = word[1:len(word)] + word[0] + "ay"

Categories