How do I fix my Pig Latin encryption code? - python

I'm trying to fix the ' if w[0] not in vowel: ' portion of my code (for handling words that start with consonants. BUT the return values are not what they should be and I don't know why!
def encrypt(w):
'''
encrypt to pig latin
'''
Lstw = list(w)
y = 0
if w[0:2] == 'qu':
PLw = []
for element in vowel:
#find first occurence of vowel in 'qu...'
y = w.find(element)
#if vowel found, y = 0
if y != -1:
#terminate loop and continue to line 22
break
x = w[0:y]
PLw.append(w[y:] + '-' + x + 'ay')
return PLw[0]
if w[0] in vowel:
PLw = []
PLw.append(w + '-way')
return PLw[0]
if w[0] not in vowel:
PLw = []
for element in vowel:
v = w.find(element)
if v != -1:
break
PLw.append(w[v:] + '-' + w[0:v] + 'ay')
return PLw[0]
else:
if w[1] in vowel:
PLw = []
x = w[0]
PLw.append(w[1:] + '-' + x + 'ay')
return PLw[0]
print(encrypt('yesterday'))
print(encrypt('STRENGTH'))
should return
>>> esterday-yay
>>> ENGTH-STRay
Currently returning
>>> ay-yesterday
>>> H-STRENGTay

I see three bugs right away; there might be more.
Your vowel-seeking loop is looking for the first vowel in the vowel list, not the first vowel in the word.
I'm guessing your vowel list is lowercase-only, which is why it breaks for allcaps input.
Your loop that looks for the first vowel doesn't account for the case where there is no vowel at all, which is why the breakage from (2) is not obvious.

Related

I'm trying to perform some manual encoding of strings using python

Probelm Description:
sms_encoding() which accepts a sentence and converts it into an abbreviated sentence to be sent as SMS and returns the abbreviated sentence.
Rules are as follows:
a. Spaces are to be retained as is
b. Each word should be encoded separately
If a word has only vowels then retain the word as is
If a word has a consonant (at least 1) then retain only those consonants
My Code:
#PF-Assgn-50
def sms_encoding(data):
#start writing your code here
vowels=set("aeiouAEIOU")
v_list=[]
c_list=[]
final_list=[]
new_string=''
word=data.split()
word2=[]
for i in range(0,len(word)):
ch=word[i]
#print(ch)
if ch in vowels:
v_list.append(ch)
for letter in word[i]:
if letter not in vowels:
c_list.append(letter)
c_list.append(" ")
new_string=''.join(v_list)+''.join(c_list)
final_list.append(new_string)
#print(v_list)
return ' '.join(final_list)
data="Have a Nice Day"
print(sms_encoding(data))
My Output:
aHv **<2spaces>** Nc **<1space>** Dy
Expected Output:
Hv a Nc Dy (contains only 1 space)
You could iterate over words in the sentence taking only consonants only if the word contains atleast one consonant:
data = "Have a Nice Day"
splitted = data.split()
for i, x in enumerate(splitted):
if not all(y in 'aeiou' for y in x.lower()):
splitted[i] = ''.join([y for y in x if y.lower() not in 'aeiou'])
print(' '.join(splitted))
# Hv a Nc Dy
This will work for all cases... retains all except vowels when even 1 character in a string is not vowel.
def sms_encoding(data):
vowels = set("aeiouAEIOU")
words = data.split()
encoded_words = []
for i in range(0,len(words)):
vow_count = 0
cons_word = []
for x in words[i]:
if x in vowels:
vow_count =vow_count+1
elif x not in vowels:
cons_word.append(x)
if vow_count == len(words[i]):
encoded_words.append(words[i])
elif vow_count != len(words[i]):
encoded_words.append("".join(cons_word))
encoded_msg = " ".join(encoded_words)
return encoded_msg
data=input("Kindly enter your message for sms encoding : ")
print(sms_encoding(data))
Try and let me know!
def sms_encoding(data):
vowel = "aeiouAEIOU"
list1 = data.split()
list2 = []
for i in list1:
length=len(i)
if length == 1:
list2.append(i)
list2.append(" ")#to add spaces between the words
else:
count=0
for a in i:
if a in vowel:
count+=1
if count==length: #to check if all the letters are vowels
list2.append(i)
list2.append(" ")
for a in i:
if a not in vowel:
list2.append(a)
list2.append(" ")
list2.pop() #to remove the extra space at the end of the whole sentence
q="".join(list2)
return q
data = "I love Python aeio"
print(sms_encoding(data))
try this code it will work the question is from infytq
def sms_encoding(data):
data=data.lower()
a=data.split()
v1=""
for i in range(0,len(a)):
z=a[i]
v=""
c1=0
for j in z:
if j not in ('a','e','i','o','u'):
v=v+j
elif j in ('a','e','i','o','u'):
c1=c1+1
if(c1!=len(z)):
v1=v1+v+" "
elif(c1==len(z)):
v1=v1+z+" "
word=v1[0:len(v1)-1]
return word
data="I love Python"
print(sms_encoding(data))
def sms_encoding(new_s):
encrypt_string = []
consonant_list = []
vowel_set = set("aeiouAEIOU")
for word in range(0, len(new_s)):
v_letter = new_s[word]
if v_letter in vowel_set:
encrypt_string.append(v_letter)
for letter in v_letter:
if letter not in vowel_set:
consonant = " ".join(letter)
encrypt_string.append(consonant)
encrypt_string.append(" ")
encrypt_string = "".join(encrypt_string)
print(encrypt_string)
s = input("Enter a string ")
new_s = s.split()
sms_encoding(new_s)

Letter Change using Python

Problem statement:
Have the function LetterChanges(str) take the str parameter being passed and modify it using the following algorithm. Replace every letter in the string with the letter following it in the alphabet (ie. c becomes d, z becomes a). Then capitalize every vowel in this new string (a, e, i, o, u) and finally return this modified string.
My Python program is:
def LetterChanges(str):
for i in range(0,len(str)):
a=ord(str[i])
if a==122:
str=str.replace(str[i],'a',1)
elif a==90:
str=str.replace(str[i],'a',1)
elif (a>=65 and a<=90) or (a>=97 and a<=122):
a=a+1
char=chr(a)
str=str.replace(str[i],char,1)
for i in range(0,len(str)):
if str[i]=='a':
str=str.replace(str[i],'A',1)
elif str[i]=='e':
str=str.replace(str[i],'E',1)
elif str[i]=='i':
str=str.replace(str[i],'I',1)
elif str[i]=='o':
str=str.replace(str[i],'O',1)
elif str[i]=='u':
str=str.replace(str[i],'U',1)
return(str)
print LetterChanges(raw_input())
The problem with my code is that, when I input sen, the output was tfo which was correct.
But when I gave sent as my input, I got the wrong output.
Your mistake is here :silpa
when you are replacing you have not cared about indices where character is replacing so how it is going when you give sent input
after replacing n we get string like tfot now in next iteration next letter you encounter in your original string is t so it will replace the first letter that is t in the replaced string so . "tfot" becomes "ufot" and last t is not being replaced
here an another try :
def prgrm(n):
k = ""
for i in n:
nxt = chr(97 if i == 'z' else ord(i)+1)
if nxt in ('a', 'e', 'i', 'o', 'u'):
nxt = nxt.capitalize()
k += nxt
print(k)
prgrm('sen')
A functional programming take, without using ord() or a loop, will work with presence of other non alphabetic characters I think:
def LetterChanges(str):
vowels = "aeiou"
lowers = "abcdefghijklmnopqrstuvwxyza"
all = lowers.upper() + lowers
# Map all alphabetical characters
nxt_str = "".join(map(lambda x: all[all.index(x) + 1] if x in all else x, str))
# Map the vowels
return "".join(map(lambda x: x.upper() if x in vowels else x, nxt_str))
print(LetterChanges("sentdZ"))
tfOUEA
You are processing the 't' twice in your string, first the s is replaced by 't' and after that 't' is replaced again by 'u' also the first replacement in the string
def LetterChanges(line):
result = ""
for i in line:
a=ord(i)
if a == 122 or a == 90:
result += 'A'
elif (a >= 65 and a <= 90) or (a >= 97 and a <= 122):
a = a + 1
char = chr(a)
if char in ('e', 'i', 'o', 'u'):
char = char.upper()
result += char
else:
result += i
return(result)
Here is another way with using re:
import re
def letter_changes(my_string):
in_letters = "abcdefghijklmnopqrstuvxyz"
out_letters = "bcdefghijklmnopqrstuvxyza"
letter_dict1 = {x:y for x,y in zip(in_letters, out_letters)}
letter_dict2 = {'a':'A', 'e':'E', 'i':'I', 'o':'O', 'u':'U'}
for l_dict in [letter_dict1, letter_dict2]:
pattern = re.compile("|".join(l_dict.keys()))
my_string = pattern.sub(lambda m: l_dict[re.escape(m.group(0))], my_string)
return my_string
This is another way to write your code:-
def rep_cap(sent):
sent_rp = ''.join([chr(c) for c in [x+1 for x in [ord(c) for c in sent]]]).replace('{','a') #This thing is done to convert a to b .... z to a
final_output = ""
vowels = ['a','e','i','o','u']
for i in sent_rp:
if i in vowels:
final_output = final_output+i.upper() #convert vowels to upper case
else :
final_output = final_output+i
return final_output
sent = raw_input("Enter a sentence:")
print rep_cap(sent)
replace this line
str=str.replace(str[i],char,1) with
str = str[:i] + char + str[i+1:]
Reason for this problem answered by #Pankaj78691 is correct!!
Here is my version of the algorithm.
def LetterChanges(str):
result = ''
vowels = ['a','e','i','o','u']
for s in str:
if s.isalpha():
if ord(s) == 122: #ASCII code of 'z'
next_letter = chr(97)
else:
next_letter = chr(ord(s)+1)
if next_letter in vowels:
result += next_letter.upper()
else:
result += next_letter
else:
result += s
return result

If the last word in 's' starts with a consonant, it will say index out of range. How do I change the program to change that?

def to_pig_latin(s):
j = 0 # points to first character in word
i = 0
new_sentence_1 = '' # variable to store strings being changed
vowel_position = 0 # show the position of the first vowel
number_of_words = 0
number_of_spaces = s.count(" ")
number_of_words = number_of_spaces + 1
space_position = s.find(" ") # find the position of the first space
sent = s[:space_position] # slice the first word of the sentence
old_sent = s[len(sent)+1:] # stores the old sentence without the first word of s
while number_of_spaces >= 0:
if sent[j] in ["a", "e", "i", "o", "u"]: # checks if first character is a vowel
new_sentence = sent + "way" # adds 'way' to the first word
new_sentence_1 = new_sentence_1 + ' ' + new_sentence # adds the words
else: # if first character is not equal to a vowel
for i in range(len(sent)):
# check to see if first character in s is a vowel
if s[i] == 'a':
break
if s[i] == 'e':
break
if s[i] == 'i':
break
if s[i] == 'o':
break
if s[i] == 'u':
break
vowel_position = i # takes position of first vowel reached in word
consonant_sequence = sent[:vowel_position] # stores all the consonants up to the first vowel, but not the first vowel
sent = sent[vowel_position:] # slices the word from the first vowel to the end
new_sentence = sent + 'a' + consonant_sequence + 'ay' # adds strings
new_sentence_1 = new_sentence_1 + ' ' + new_sentence # adds the words
s = old_sent # takes the value of old_sent
space_position = s.find(" ") # find the position of the first space
How do I change the part below in order to for it to check even if there is one word in s? Or if the last word in the string s ends with a word that begins with one or more consonant?
if space_position == -1:
space_position = len(s)
sent = s[:space_position]
if sent[j] in ["a", "e", "i", "o", "u"]:
new_sentence = sent + "way"
new_sentence_1 = new_sentence_1 + ' ' + new_sentence
break
else:
for i in range(len(sent)):
if s[i] == 'a':
break
if s[i] == 'e':
break
if s[i] == 'i':
break
if s[i] == 'o':
break
if s[i] == 'u':
break
vowel_position = i
consonant_sequence = sent[:vowel_position]
sent = sent[vowel_position:]
new_sentence = sent + 'a' + consonant_sequence + 'ay'
new_sentence_1 = new_sentence_1 + ' ' + new_sentence
sent = s[:space_position]
old_sent = s[len(sent)+1:]
number_of_spaces = s.count(" ")
number_of_words = number_of_spaces + 1
return new_sentence_1[1:]
test program for english/piglatin translator:
import piglatin
choice = input ("(E)nglish or (P)ig Latin?\n")
action = choice[:1]
if action == 'E':
s = input("Enter an English sentence:\n")
new_s = piglatin.to_pig_latin(s)
print("Pig-Latin:")
print(new_s)
elif action =='P':
s = input("Enter a Pig Latin sentence:\n")
new_s = piglatin.to_english(s)
print("English:")
print(new_s)
Output:
(E)nglish or (P)ig Latin? E
Enter an English sentence: My friend next to me is wearing a shoe
Traceback (most recent call last):
File "/Applications/Wing101.app/Contents/Resources/src/debug/tserver/_sandbox.py",
line 9, in <module>
File "/Users/azhar/Desktop/Computer Science/Assignments/Assignment 4 (Functions & Strings)/piglatin.py", line 46, in to_pig_latin
if sent[j] in ["a", "e", "i", "o", "u"]: # checks if first value in j is equal to a vowel
builtins.IndexError: string index out of range
I think, rather than fixing that specific problem, it would be easier to simplify the code.
First, you can split the sentence with s.split(), which will give you a list of words split on whitespace. Second, you can use s.find() to find the index of a given string. Third, you can use ' '.join(sen) to join a list of strings using spaces.
So using these, your code reduces to this (I also added handling of capitalization):
def to_pig_latin(sen):
senlst = sen.lower().split() # split into list of words
for i, word in enumerate(senlst):
if word[0] in 'aeiou':
senlst[i] += 'way'
else:
for vow in 'aeiou':
ind = word.find(vow)
if ind >= 0:
break
if ind < 0: # no vowel in word
continue
senlst[i] = word[ind:]+'a'+word[:ind]
newsen = ' '.join(senlst) # combine list of words into sentence
if sen[0].isupper(): # make capitalization like original
newsen = newsen.capitalize()
return newsen
However, if you really want to check if there is a word at all, you can do if s.strip():. What this will do is strip out and leading or trailing whitespace. If there are no words, this will leave you with an empty string. In python, an empty string (or empty list or tuple) is considered False, so you can use it in an if test to then do whatever sort of handling of that situation you want.

PigLatin translator for words starting with multiple consonants[Python]

VOWELS = ('a', 'e', 'i', 'o', 'u')
def pigLatin(word):
first_letter = word[0]
if first_letter in VOWELS: # if word starts with a vowel...
return word + "hay" # then keep it as it is and add hay to the end
else:
return word[1:] + word[0] + "ay"
def findFirstVowel(word):
novowel = False
if novowel == False:
for c in word:
if c in VOWELS:
return c
I need to write a piglatin translator that can handle words that start with multiple consonants.
For example, the output I get currently when I enter "string" is:
PigLatin("string") = tringsay
I would want the output:
PigLatin("string") = ingstray
To write this, I wrote an additional function to iterate through the word and find the first vowel, but after that I am not sure how to proceed.
Any help would be appreciated.
After finding the first vowel, get its index in the string by doing word.index(c). Then, slice the whole word from the beginning to the index of the vowel
With that slice, put it at the end of the word and add 'ay', as you did in your first function.
You need to find the index of a consonant and slice on it.
Here's an example:
def isvowel(letter): return letter.lower() in "aeiou"
def pigLatin(word):
if isvowel(word[0]): # if word starts with a vowel...
return word + "hay" # then keep it as it is and add hay to the end
else:
first_vowel_position = get_first_vowel_position(word)
return word[first_vowel_position:] + word[:first_vowel_position] + "ay"
def get_first_vowel_position(word):
for position, letter in enumerate(word):
if isvowel(letter):
return position
return -1
There are probably more eloquent ways of doing this but this is my solution. Hopefully it helps!
def pigLatin(aString):
index = 0
stringLength = len(aString)
consonants = ''
# if aString starts with a vowel then just add 'way' to the end
if isVowel(aString[index]):
return aString + 'way'
else:
# the first letter is added to the list of consonants
consonants += aString[index]
index += 1
# if the next character of aString is a vowel, then from the index
# of the vowel onwards + any consonants + 'ay' is returned
while index < stringLength:
if isVowel(aString[index]):
return aString[index:stringLength] + consonants + 'ay'
else:
consonants += aString[index]
index += 1
return 'This word does contain any vowels.'
def isVowel(character):
vowels = 'aeiou'
return character in vowels

Python skipping my if statement

For some reason, this code doesn't work:
def pyglatin(word):
output = ""
wordlenedit = len(word)-1
wordlen = len(word)
fixer = 0
while fixer == 0:
for i in word:
if i == 'a' or i == 'e' or i == 'o' or i == 'i' or i == 'u':
fixer = 1
else:
wordlenedit -= 1
else:
output = word[wordlenedit:wordlen:1] + '-' + word[0:wordlenedit:1] + 'ay'
return output
To see the issues, click here. The problem appears to be that it's skipping the if statement that identifies vowels, but I'm not sure why. This results in some very odd outputs.
Your function does not work because you walk through the word, decrementing the splitting index for each consonant you encounter, starting at wordlenedit = len(word)-1.
At the end of your for loop, wordlenedit is equal to (length of the word) - 1 - (number of consonants). The function will only work if the first index of vowel in the word (starting at 0) is equal to the number of vowels - 1.
Also, the while loop is useless here, as you walk through the entire word in the for loop. It is even worse than that: the while loop will be an infinite loop if you have a word with no vowels (like "fly", as you don't check the "y")
This is a corrected version of your function, using the keyword break:
def pyglatin2(word):
output = ""
wordlenedit = 0
wordlen = len(word)
for l in word:
if l == 'a' or l == 'e' or l == 'o' or l == 'i' or l == 'u':
break
else:
wordlenedit += 1
output = word[wordlenedit:wordlen:1] + '-' + word[0:wordlenedit:1] + 'ay'
return output
However this function can be written in a much more concise/simple way, using Regular Expressions, like this:
import re
def pyglatin3(word):
# Get the first index of one of these: a, e, i, o, u
start = re.search("[aeiou]", word).start()
# Split the word
return word[start:] + "-" + word[0:start] + "ay"
If you want to do this without using regular expressions, the simplest way is to use enumerate:
def pyglatin(word):
for i, ch in enumerate(word):
if ch in 'aeiou':
return word[i:] + '-' + word[:i] + 'ay'

Categories