Capitalise and ignore comma - python

I have this code:
def reverse (word):
newword = ''
letterflag = -1
for numletter in word:
newword += word[letterflag]
letterflag-=1
s=newword
s.upper()
return newword
def isPalindrome(word, ignorecase=False):
"""
>>> type(isPalindrome("bob"))
<type 'bool'>
>>> isPalindrome("abc")
False
>>> isPalindrome("bob")
True
>>> isPalindrome("a man a plan a canal, panama")
True
>>> isPalindrome("A man a plan a canal, Panama")
False
>>> isPalindrome("A man a plan a canal, Panama", ignorecase=True)
True
"""
word = str (word)
newword = reverse(word)
if word == newword:
return True
else:
return False
When I type "Bob", I want it to return true because of the capital B.

Just make your input always lower case that way you can avoid that problem altogether.
word = str(word)
word = word.lower()
word = word.replace(',', '') # removes any commas from the string
newword = word[::-1] # reverse string
if word == newword:
return True
else:
return False

The best way to learn what is being done in this answer is to try individual parts of it in the Python console.
To fix your reverse() do this:
def reverse (word):
newword = ''
letterflag = -1
for numletter in word:
newword += word[letterflag]
letterflag-=1
return newword
Notice I also took out the .upper() parts since they are not effective and reverse is not the correct place to have it since you can not compare a reversed upper case word with the original word. Also s.upper() does not work like you think it does. It returns an upper case copy of s without modifying s. You would only to do return newword.upper() to make it work.
Additionally, the letterflag is not needed, you could simply do:
def reverse (word):
newword = ''
for letter in word:
newword = letter + newword #adds each new letter to beginning
return newword
However the simplest way to do a reverse functions is:
def reverse (word):
return word[::-1]
Your isPalendrome needs to be this to basically work:
def isPalindrome(word, ignorecase=False):
word = word.replace(',', '').replace(' ', '') #removes ,'s and spaces
if ignorecase:
return word.lower() == reverse(word).lower()
else:
return word == reverse(word)
Here is a more advanced solution that will ignore anything that is not a letter with an option to ignore case. This version does need reverse.
def isPalindrome(word, ignorecase=False):
abcs = 'abcdefghijklmnopqrstuvwxyz'
word = [c for c in word.lower()*ignorecase or word if c in abcs]
return word == word[::-1] #no need for reverse

If you want to have the option to be case sensitive, or the option to be case insensitive, add an IF statement in the isPalindrome() function:
if ignorecase == True:
word = word.lower()
It should look like this when you are done:
import string
def reverse (word):
newword = ''
letterflag = -1
for numletter in word:
newword += word[letterflag]
letterflag-=1
s=newword
s.upper()
return newword
def isPalindrome(word, ignorecase=False):
"""
>>> type(isPalindrome("bob"))
<type 'bool'>
>>> isPalindrome("abc")
False
>>> isPalindrome("bob")
True
>>> isPalindrome("a man a plan a canal, panama")
True
>>> isPalindrome("A man a plan a canal, Panama")
False
>>> isPalindrome("A man a plan a canal, Panama", ignorecase=True)
True
"""
if ignorecase == True:
word = word.lower()
word = word.replace(',', '')
word = word.replace(' ', '')
newword = reverse(word)
if word == newword:
return True
else:
return False
That code gives me the following feedback:
isPalindrome('Bob', ignorecase=True)
Out[34]: True
isPalindrome('Bob')
Out[35]: False

Related

Best approach for converting lowerCamelCase to snake_case

I came across below mentioned scenario:
Input:-
parselTongue
Expected Output:-
parsel_tongue
My code:-
empty_string = ""
word = input()
if word.islower() == 1:
empty_string = empty_string + word
print(empty_string)
else:
for char in word:
char = str(char)
if char.isupper() == 1:
x = char
y = word.find(x)
print(char.replace(char, word[0:y] + "_" + char.lower() + word[y:]))
My output:-
parsel_tTongue
Please advice where i am going wrong as my output is coming as "parsel_tTongue" and not "parsel_tongue"
The more elegant solution would be just to implement the logic using comprehension.
word = input()
output= ''.join(c if not c.isupper() else f'_{c.lower()}' for c in word)
#output: 'parsel_tongue'
I believe that this approach could be better.
It prevents from situations where word contains not only letters but also special characters or numbers.
word = "camelCaseWord"
res = "" # sanke case word
# handle 1st upper character
if word[0].isupper():
word = word[0].lower() + word[1:]
for w in word:
# Only letter can be upper
if w.isupper():
res += "_" + w.lower()
else:
res += w
print(res)
>>> camel_case_word
if word = "camelCase3Wor& - > >>> camel_case3_wor&
no need for loop use regex
import re
name = 'parselTongue'
name = re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
print(name) # camel_case_name
Adjust the slice on word
empty_string = ""
word = input()
if word.islower() == 1:
empty_string = empty_string + word
print(empty_string)
else:
for char in word:
char = str(char)
if char.isupper() == 1:
x = char
y = word.find(x)
print(char.replace(char, word[0:y] + "_" + char.lower()+ word[y+1:]))
prints the following for the input parselTongue
praselTongue
prasel_tongue
The best practice may be using regex:
fooBarBaz -> foo_bar_baz
re.sub(r'([A-Z])',lambda match:'_'+match.group(1).lower(),'fooBarBaz')
foo_bar_baz -> fooBarBaz
re.sub(r'_([a-z])',lambda match:match.group(1).upper(),'foo_bar_baz')
import re
camel_case = 'miaBau'
snake_case = re.sub(r'([A-Z])', r'_\1', camel_case).lower()

Turning random.choice into a mutable

I'm very new to python and I'm trying to make a hangman game. I currently have a line of code saying word = (random.choice(open("Level1py.txt").readline())).
I'm getting the error 'str' object does not support item assignment.
Here is the rest of my code (sorry for the mess):
import random
def checkLetter(letter, word, guess_word):
for c in word:
if c == letter:
guess_word[word.index(c)] = c
word[word.index(c)] = '*'
print(guess_word)
word = (random.choice(open("Level1py.txt").readline().split()))
guess_word = ['_' for x in word]
print(guess_word)
while '_' in guess_word:
guess = input('Letter: ')
print(checkLetter(guess, word, guess_word))
Strings are immutable in python. An easy workaround is to use lists, which are mutable:
st = "hello"
ls = list(st)
ls[3] = 'r'
st = ''.join(ls)
print(st)
Outputs
helro
Edit: here's how you would implement it in your own code
import random
def checkLetter(letter, word, guess_word):
for c in word:
if c == letter:
guess_word[word.index(c)] = c
word_list = list(word)
word_list[word.index(c)] = "*"
word = ''.join(word_list)
print(guess_word)
word = 'test'
guess_word = ['_' for x in word]
print(guess_word)
while '_' in guess_word:
guess = input('Letter: ')
print(checkLetter(guess, word, guess_word))
Note that there are still other issues that have nothing to do with this, like printing None and duplicate printing
You can also solve your problem using a dictionary:
word = "my string" #replace this with your random word
guess_word = {i: '_' for i in set(word)} # initially assign _ to all unique letters
guess_word[' '] = ' ' # exclude white space from the game
wrong_attempts = 0
while '_' in guess_word.values():
guess = input('Letter: ')
if guess in guess_word.keys():
guess_word[guess] = guess
else:
wrong_attempts += 1
if wrong_attempts > 11:
break
printable = [guess_word[i] for i in word]
print(' '.join(printable))
if '_' in guess_word.values():
print('you lost')
else:
print('congratulation, you won')

Why does this code not print the characters backwards

def anti_vowel(text):
p=''
for c in text:
if c=='a' or c=='A':
break
elif c=='e' or c=='E':
break
elif c=='i' or c=='I':
break
elif c=='o' or c=='O':
break
elif c=='u' or c=='U':
break
else:
p=p+c
print(anti_vowel('Hello you'))
You forgot to return p at the end of your function:
def anti_vowel(text):
p=''
for c in text:
if c=='a' or c=='A':
break
elif c=='e' or c=='E':
break
elif c=='i' or c=='I':
break
elif c=='o' or c=='O':
break
elif c=='u' or c=='U':
break
else:
p=p+c
return p
Without that last line all you'll ever print is None, the default return value for functions without an explicit return statement.
Of course, your function will only ever print the first consonants, as break ends the loop as soon as you find any vowels. It'll not reverse the string, ever. For your sample input, the function return 'H', because the next letter in the input is a vowel, and break then ends the loop.
You could easily re-write your function to use str.lower() and a containment test:
def anti_vowel(text):
p = ''
for c in text:
if c.lower() in 'aeiou':
break
p += c
return p
This does the same thing, return the first consonants ('H' for your sample input).
If you wanted to reverse letters, and exclude vowels, don't use break and invert where you place the remaining letters. You could use continue instead, or more simply, just invert the if test and only process a chararter if it is not a vowel:
def anti_vowel(text):
p = ''
for c in text:
if c.lower() not in 'aeiou':
p = c + p
return p
Now consonants are placed before any preceding consonants, reversing the text:
>>> def anti_vowel(text):
... p = ''
... for c in text:
... if c.lower() not in 'aeiou':
... p = c + p
... return p
...
>>> anti_vowel('Hello you')
'y llH'

Assign a new variable for every item in list - Python

Here is the standard pig latin code used in codeacademy. It works well but it's shortcoming is that it only works for one word at a time:
pyg = 'ay'
original = raw_input('Enter a word or phrase:')
if len(original) > 0 and original.isalpha():
word = original.lower()
translate = word[1:] + word[0]
if word[0] != "a" and word[0] != "e" and word[0] != "i" and word[0] != "o" and word[0] != "u":
new_word = translate + pyg
print new_word
else:
new_word = word + pyg
print new_word
else:
print 'Input is empty or illegal'
so I wanted to make it so that it could phrases. This is what I came up with:
pyg = 'ay'
count = 0
original_input = raw_input('Enter a word or phrase:')
original = original_input
original_list = []
#converts to a list
while " " in original:
if count > 50:
break
word = original[0:original.index(" ")]
original_list.append(word)
space = original.index(" ")
space += 1
original = original[space:]
count += 1
#this works great until there is a word left and no spaces i.e. the last word
if len(original) > 0:
original_list.append(original)
#this adds the last word
print original_list
def pyglatin(phrase):
#old code doesn't work because phrase is a list
#now I have to translate BACK to a string
for words in phrase:
new_word = str(words)
"""this works for one word, how do I assign a new variable for every word if I don't know the phrase length ahead of time"""
so that brings me to my question: How do I assign a variable for every item when I don't know how many items I'm going to need, and then be able to call that code back (through the old pyglatin translator)?
As Maxime mentioned, lists are useful in this instance, and the string can be converted to a list much easier. To account for phrases, I would rewrite the code as follows:
def trans_word(original):
if len(original) > 0 and original.isalpha():
word = original.lower()
translate = word[1:] + word[0]
if word[0] != "a" and word[0] != "e" and word[0] != "i" and word[0] != "o" and word[0] != "u":
new_word = translate + pyg
return new_word
else:
new_word = word + pyg
return new_word
else:
return "Input is empty or illegal"
def pyglatin(phrase):
if len(phrase) > 0:
return " ".join(trans_word(word) for word in phrase)
else:
return "Input is empty or illegal"
pyg = 'ay'
count = 0
original_input = raw_input('Enter a word or phrase:')
original_list = original_input.split()
print pyglatin(original_list)
Maybe something like this?
def latinize(word):
word = word.lower()
translate = word[1:] + word[0]
return (translate if word[0] in 'aeiou' else word) + 'ay'
original = raw_input('Enter a word or phrase:')
print ' '.join(latinize(word) for word in original.split())
Example input and output:
Enter a word or phrase:Gallia est omnis divisa in partes tres
galliaay steay mnisoay divisaay niay partesay tresay
But shouldn't you actually move all initial consonants to the end, and not only the first?
Edit:
If you want to move all initial consonants to the end, you can use:
def latinize(word):
word = word.lower()
firstvowel = min (word.index (v) if v in word else 42042 for v in 'aeiou')
if firstvowel == 42042: raise Exception ('No vowel in word')
return word [firstvowel:] + word [:firstvowel] + 'ay'
original = raw_input('Enter a word or phrase:')
print ' '.join(latinize (word) for word in original.split () )
Sample input and output:
Enter a word or phrase:star chick mess string
arstay ickchay essmay ingstray

Translating sentences into pig latin

SO i have this assignment to translate multiple words into pig latin. assume that the user will always input lowercase and only letters and spaces.
#----------------global variables
sentence = input("What do you want to translate into piglattin? ")
sentence = list(sentence)
sentence.insert(0, ' ')
length = len(sentence)
sentence.append(' ')
pigLattin = sentence
false = 0
true = 1
consonant = []
a = 0
b = 0
c = 0
d = 0
e = 0
f = 0
j = 0
x = 0
y = 0
#----------------main functions
def testSpace(sentence, i):
if sentence[i] == ' ':
a = true
else:
a = false
return a
def testVowel(sentence, i):
if sentence[i] == 'a' or sentence[i] == 'e' or sentence[i] == 'i' or sentence[i] == 'o' or sentence[i] == 'u' or sentence[i] == 'y':
b = true
else:
b = false
return b
def testStartWord(sentence, i):
x = 0
if sentence[i].isalpha() and sentence[i-1] == ' ':
c = true
x = 1
if x == 1 and sentence[i] != 'a' and sentence[i] != 'e' and sentence[i] != 'i' and sentence[i] != 'o' and sentence[i] != 'u' and sentence[i] != 'y':
c = true
else:
c = false
return c
def testWordEnd(sentence, i):
if sentence[i].isalpha() and sentence[i+1] == ' ':
d = true
else:
d = false
return d
#----------------main loop
for i in range(1,length):
x = 0
space = testSpace(sentence, i)
vowel = testVowel(sentence, i)
word = testStartWord(sentence, i)
end = testWordEnd(sentence, i)
if vowel == false and space == false and word == true:
e = i
consonant.append(sentence[i])
pigLattin.pop(e)
f = f + 1
if end == true:
consonant.append('a')
consonant.append('y')
consLength = len(consonant)
for x in range(consLength):
y = i + j - f
pigLattin.insert(y,consonant[x])
j = j + 1
del consonant[:]
pigLength = len(pigLattin)
for b in range (pigLength):
print(pigLattin[b], end='')
this is what i have so far. it gets kinda messy when trying to remove items. im sort of stuck here and its not working.
OK i got it working now this is an updated version
sentence = input("Please enter a sentence: ")
vowels = ("a", "e", "i", "o", "u", "A", "E", "I", "O", "U")
words = sentence.split()
count = 0
def find_vowel(word):
for i in range(len(word)):
if word[i] in vowels:
return i
return -1
for word in words:
vowel = find_vowel(word)
if(vowel == -1):
print(word, ' ', end='')
elif(vowel == 0):
print(word + "ay", ' ', end='')
else:
print(word[vowel:] + word[:vowel] + "ay", ' ', end='')
Instead of using testSpace eliminate the spaces by using sentence = sentence.split(). This will split all your words into strings in a list. Then iterate through the words in your list.
Instead of using testStartWord, use an if statement:
for word in sentence:
if word[0] in ["a","e","i","o","u"]:
word[:(len(word)-1)] = word[0]
#More Code...
At the end, where you print the output, use print sentence.join()
Here's an alternate version. I use a regular expression to find words in the input string, pass them to a callback function, and substitute them back into the original string. This allows me to preserve numbers, spacing and punctuation:
import re
import sys
# Python 2/3 compatibility shim
inp = input if sys.hexversion >= 0x3000000 else raw_input
VOWELS = set('aeiouyAEIOUY')
YS = set('yY')
def pig_word(word):
"""
Given a word, convert it to Pig Latin
"""
if hasattr(word, 'group'):
# pull the text out of a regex match object
word = word.group()
# find the first vowel and what it is
vowel, where = None, None
for i,ch in enumerate(word):
if ch in VOWELS:
vowel, where = ch, i
break
if vowel is None:
# No vowels found
return word
elif where == 0 and vowel not in YS:
# Starts with a vowel - end in 'way'
# (leading y is treated as a consonant)
return word + 'way'
else:
# Starts with consonants - move to end and follow with 'ay'
# check capitalization
uppercase = word.isupper() and len(word) > 1
titlecase = word[:1].isupper() and not uppercase
# rearrange word
word = word[where:] + word[:where] + 'ay'
# repair capitalization
if uppercase:
word = word.upper()
elif titlecase:
# don't use str.title() because it screws up words with apostrophes
word = word[:1].upper() + word[1:].lower()
return word
def pig_latin(s, reg=re.compile('[a-z\']+', re.IGNORECASE)):
"""
Translate a sentence into Pig Latin
"""
# find each word in the sentence, pass it to pig_word, and insert the result back into the string
return reg.sub(pig_word, s)
def main():
while True:
s = inp('Enter a sentence to translate (or Enter to quit): ')
if s.strip():
print(pig_latin(s))
print('')
else:
break
if __name__=="__main__":
main()
then
Enter a sentence to translate (or Enter to quit):
>>> Hey, this is really COOL! Let's try it 3 or 4 times...
Eyhay, isthay isway eallyray OOLCAY! Et'slay ytray itway 3 orway 4 imestay...

Categories