I tried to run this program, but for some reason the string gets changed only to lowercase. The vowels don't turn to lowercase. Any ideas on why?
Thanks!
def changeCaps(string):
i = 0
while i < len(string):
if string[i] == 'a' or string[i] == 'e' or string[i] == 'i' or string[i] == 'o' or string[i] =='u':
print(string[i].upper())
i = i + 1
else:
print(string[i].lower())
i = i + 1
changeCaps("AlbErT")
What doubleo said in his two comments is correct: because the A and E in AlbErt are already capitalized, they aren't equal to lowercase a and e, and as such, they are made to be lowercase along with all the consonants. if you ware wanting to change the case of any letter typed, that would require a different routine. Something more along these lines:
def changeCaps(string):
i = 0
while i < len(string):
if string[i].islower():
print(string[i].upper())
i = i + 1
else:
print(string[i].lower())
i = i + 1
changeCaps("AlbErT")
This will result in any uppercase letters becoming lowercase and any lowercase letters becoming uppercase, and whether or not it is a vowel or consonant will have nothing to do with it.
Also, why not use a for loop instead? This will work just as well, and take up fewer lines of code:
def changeCaps(string):
for i in range(len(string)):
if string[i].islower():
print(string[i].upper())
else:
print(string[i].lower())
changeCaps("AlbErT")
Okay, so it only saves two lines, but it makes more sense to use a for loop in my opinion. Either way, the resultant output would be:
aLBeRt
On a final note, as Anton pointed out, you don't even really need a numeric pointer, just go over the string.
def changeCaps(string):
for c in string:
if c.islower():
print(c.upper())
else:
print(c.lower())
changeCaps("AlbErT")
(Thanks, Anton!)
Related
word = hello
dashes = '-' * len(word)
guess = input()
If guess is h I want to replace dashes[0] with h because h is word[0] how would I check to see if h is in word, and then if it is, replace the appropriate - in dashes at the index guess is in word
Then given another input() and dashes is now h---- and the input is l do the same but so that dashes becomes h-ll-
I hope this makes sense, best I can explain it.
I have tried the following after a guess is made and before another guess is given:
dashes = dashes.replace(dashes[word.index(guess)], guess)
but if guess is h, dashes becomes hhhhh
not sure why or how to fix it.
str.replace replaces every instance of - in dashes.
You can instead iterate through the dashes after zipping with the full word and replace only the character in the same position(s) as the correct guess:
dashes = ''.join(j if j==guess else i for i, j in zip(dashes, word))
def update_blanks(guess, dashes):
return ''.join(j if j==guess else i for i, j in zip(dashes, word))
guess = 'h'
dashes = update_blanks(guess, dashes)
print(dashes)
# h----
guess = 'l'
dashes = update_blanks(guess, dashes)
print(dashes)
# h-ll-
I guess this is a 'hangman-esque' game. Try this.
word = 'hello'
current = ['-']*len(hello)
guess = input()
for i in range(len(word)):
if word[i] == guess:
current[i] = word[i]
This is more efficient if you are planning to continuously update the current state of your guesses.
Since string is immutable - I will decompose the word into a list of characters, replace suitable - and then compose into a word again
word_chars = [guess if c == '-' and word[i] == guess else c
for i, c in enumerate(dashes)]
dashes = ''.join(word_chars)
If I have a string
String = 'ABCEEFGH'
How can I check what letter is beside each letter without going out of index?
for index in range(len(String)):
if String[index] == String[index+1]:
print('Double')
You can use enumerate, slicing the string up to the second last character:
String = 'ABCEEFGH'
for ind,ch in enumerate(String[:-1]):
if ch == String[ind+1]:
print('Double')
In your own code the logic would be the same len(String)-1 but enumerate is the way to go:
for index in range(len(String)-1):
if String[index] == String[index+1]:
print('Double')
The fact you seen to only want to check if any two adjacent characters are identical, maybe using any would be best:
String = 'ABCEEFGH'
if any( ch == String[ind+1] for ind, ch in enumerate(String[:-1])):
print('Double',ch)
any will short circuit and break the loop as soon the condition is Trueor else evaluate to False if we have no match.
>>> text = 'ABCEEFGH'
>>> for c1, c2 in zip(text, text[1:]):
if c1 == c2:
print 'double'
double
These kinds of problems are almost always easier if you think of comparing with the previous letter instead of the next one. It's a lot easier to remember letters you've already seen than to look ahead.
text = 'ABCEEFGH'
prev = ''
for letter in text:
if letter == prev:
print("letter duplicated:", letter)
prev = letter
You can use regular expressions:
for match in re.findall(r'([a-z])\1', your_string):
print('Double letters found here.')
This is a module in my program:
def runVowels():
# explains what this program does
print "This program will count how many vowels and consonants are"
print "in a string."
# get the string to be analyzed from user
stringToCount = input("Please enter a string: ")
# convert string to all lowercase letters
stringToCount.lower()
# sets the index count to it's first number
index = 0
# a set of lowercase vowels each element will be tested against
vowelSet = set(['a','e','i','o','u'])
# sets the vowel count to 0
vowels = 0
# sets the consonant count to 0
consonants = 0
# sets the loop to run as many times as there are characters
# in the string
while index < len(stringToCount):
# if an element in the string is in the vowels
if stringToCount[index] in vowels:
# then add 1 to the vowel count
vowels += 1
index += 1
# otherwise, add 1 to the consonant count
elif stringToCount[index] != vowels:
consonants += 1
index += 1
# any other entry is invalid
else:
print "Your entry should only include letters."
getSelection()
# prints results
print "In your string, there are:"
print " " + str(vowels) + " vowels"
print " " + str(consonants) + " consonants"
# runs the main menu again
getSelection()
However, when I test this program, I get this error:
line 28, in runVowels
stringToCount = input("Please enter a string: ")
File "<string>", line 1
PupEman dABest
^
SyntaxError: unexpected EOF while parsing
I tried adding a + 1 to the "while index < len(stringToCount)" but that didn't help either. I'm pretty new to python and I don't really understand what's wrong with my code. Any help would be appreciated.
I researched this error, all I found out was that EOF stands for end of file. This didn't help at all with resolving my problem. Also, I understand that sometimes the error isn't necessarily where python says the error is, so I double-checked my code and nothing seemed wrong in my eyes. Am I doing this the round-about way by creating a set to test the string elements against? Is there a simpler way to test if string elements are in a set?
Question resolved. Thank you to all!
Looks like you're using Python 2. Use raw_input(...) instead of input(...). The input() function will evaluate what you have typed as a Python expression, which is the reason you've got a SyntaxError.
As suggested use raw_input. Also you don't need to do this:
while index < len(stringToCount):
# if an element in the string is in the vowels
if stringToCount[index] in vowels:
# then add 1 to the vowel count
vowels += 1
index += 1
# otherwise, add 1 to the consonant count
elif stringToCount[index] != vowels:
consonants += 1
index += 1
# any other entry is invalid
else:
print "Your entry should only include letters."
getSelection()
Strings in Python are iterable, so you can just do something like this:
for character in stringToCount:
if character in vowelSet : # Careful with variable names, one is a list and one an integer, same for consonants.
vowels += 1
elif character in consonantsSet: # Need this, if something is not in vowels it could be a number.
consonants += 1
else:
print "Your entry should only include letters."
This should do just fine. Using a while is not necessary here, and very non-Pythonic imho. Use the advantage of using a nice language like Python when you can to make your life easier ;)
You can count the vowels like so:
>>> st='Testing string against a set of vowels - Python'
>>> sum(1 for c in st if c.lower() in 'aeiou')
12
You can do something similar for consonants:
>>> sum(1 for c in st if c.lower() in 'bcdfghjklmnpqrstvwxyz')
26
Also,
if stringToCount[index] in vowels:
should read
if stringToCount[index] in vowelSet:
Here's another way you could solve the same thing:
def count_vowels_consonants(s):
return (sum(1 for c in s if c.lower() in "aeiou"),
sum(1 for c in s if c.lower() in "bcdfghjklmnpqrstvwxyz"))
To wit:
>>> count_vowels_consonants("aeiou aeiou yyy")
(10, 3)
>>> count_vowels_consonants("hello there")
(4, 6)
Python truly is grand.
The errors in your file run as follows (plus some suggestions):
stringToCount = input("Please enter a string: ")
This should be raw_input if you want what the user typed in as a string.
stringToCount.lower()
The .lower() method returns a new string with its letters lowered. It doesn't modify the original:
>>> a = "HELLO"
>>> a.lower()
"hello"
>>> a
"HELLO"
vowelSet = set(['a','e','i','o','u'])
Here you could just as easily do:
vowelSet = set("aeiou")
Note you also don't strictly need a set but it is indeed more efficient in general.
# sets the vowel count to 0
vowels = 0
# sets the consonant count to 0
consonants = 0
Please, you don't need comments for such simple statements.
index = 0
while index < len(stringToCount):
You usually don't need to use a while loop like this in python. Note that all you use index for is to get the corresponding character in stringToCount. Should instead be:
for c in stringToCount:
Now instead of:
if stringToCount[index] in vowels:
vowels += 1
index += 1
You just do:
if c in vowels:
vowels += 1
elif stringToCount[index] != vowels:
consonants += 1
index += 1
# any other entry is invalid
Not quite right. You're checking that a character doesn't equal a set. Maybe you meant:
elif c not in vowels:
consonants += 1
But then there'd be no else case... Got to fix your logic here.
print "In your string, there are:"
print " " + str(vowels) + " vowels"
print " " + str(consonants) + " consonants"
The above is more pythonically written as:
print "In your string, there are: %s vowels %s consonants" % (
vowels, consonants)
# runs the main menu again
getSelection()
Not sure why you're calling that there - why not call getSelection() from whatever calls runVowel()?
Hope that helped! Enjoy learning this great language.
Bah, all that code is so slow ;). Clearly the fastest solution is:
slen = len(StringToCount)
vowels = slen - len(StringToCount.translate(None, 'aeiou'))
consonants = slen - vowels
...note that I don't claim it's the clearest... just the fastest :)
I've been working on this Palindrome program and am really close to completing it.Close to the point that it's driving me a bit crazy haha.
The program is supposed to check each 'phrase' to determine if it is a Palindrome or not and return a lowercase version with white space and punctuation removed if it is in fact a Palindrome. Otherwise, if not, it's supposed to return None.
I'm just having an issue with bringing my test data into the function. I can't seem to think of the correct way of dealing with it. It's probably pretty simple...Any ideas?
Thanks!
import string
def reverse(word):
newword = ''
letterflag = -1
for numoletter in word:
newword += word[letterflag]
letterflag -= 1
return newword
def Palindromize(phrase):
for punct in string.punctuation:
phrase= phrase.replace(punct,'')
phrase = str(phrase.lower())
firstindex = 0
secondindex = len(phrase) - 1
flag = 0
while firstindex != secondindex and firstindex < secondindex:
char1 = phrase[firstindex]
char2 = phrase[secondindex]
if char1 == char2:
flag += 1
else:
break
firstindex += 1
secondindex -= 1
if flag == len(phrase) // (2):
print phrase.strip()
else:
print None
def Main():
data = ['Murder for a jar of red rum',12321, 'nope', 'abcbA', 3443, 'what',
'Never odd or even', 'Rats live on no evil star']
for word in data:
word == word.split()
Palindromize(word)
if __name__ == '__main__':
Main()
Maybe this line is causing the problems.
for word in data:
word == word.split() # This line.
Palindromize(word)
You're testing for equality here, rather than reassigning the variable word which can be done using word = word.split(). word then becomes a list, and you might want to iterate over the list using
for elem in word:
Palindromize(elem)
Also, you seem to be calling the split method on int, which is not possible, try converting them to strings.
Also, why do you convert the phrase to lower case in the for loop, just doing it once will suffice.
At the "core" of your program, you could do much better in Python, using filter for example. Here is a quick demonstration:
>>> phrase = 'Murder for a jar of red rum!'
>>> normalized = filter(str.isalnum, phrase.lower())
>>> normalized
'murderforajarofredrum'
>>> reversed = normalized[-1::-1]
>>> reversed
'murderforajarofredrum'
# Test is it is a palindrome
>>> reversed == normalized
True
Before you go bananas, let's rethink the problem:
You have already pointed out that Palindromes only make sense in strings without punctuation, whitespace, or mixed case. Thus, you need to convert your input string, either by removing the unwanted characters or by picking the allowed ones. For the latter, one can imagine:
import string
clean_data = [ch for ch in original_data if ch in string.ascii_letters]
clean_data = ''.join(clean_data).lower()
Having the cleaned version of the input, one might consider the third parameter in slicing of strings, particularly when it's -1 ;)
Does a comparison like
if clean_data[::-1] == clean_data:
....
ring a bell?
One of the primary errors that i spotted is here:
for word in data:
word==word.split()
Here, there are two mistakes:
1. Double equals make no point here.
2. If you wish to split the contents of each iteration of data, then doing like this doesn't change the original list, since you are modifying the duplicate set called word. To achieve your list, do:
for i in range(data):
data[i]=data[i].split()
This may clear your errors
I am trying to count the number of times 'e' appears in a word.
def has_no_e(word): #counts 'e's in a word
letters = len(word)
count = 0
while letters >= 0:
if word[letters-1] == 'e':
count = count + 1
letters = letters - 1
print count
It seems to work fine except when the word ends with an 'e'. It will count that 'e' twice. I have no idea why. Any help?
I know my code may be sloppy, I'm a beginner! I'm just trying to figure out the logic behind what's happening.
>>> word = 'eeeooooohoooooeee'
>>> word.count('e')
6
Why not this?
As others mention, you can implement the test with a simple word.count('e'). Unless you're doing this as a simple exercise, this is far better than trying to reinvent the wheel.
The problem with your code is that it counts the last character twice because you are testing index -1 at the end, which in Python returns the last character in the string. Fix it by changing while letters >= 0 to while letters > 0.
There are other ways you can tidy up your code (assuming this is an exercise in learning):
Python provides a nice way of iterating over a string using a for loop. This is far more concise and easier to read than using a while loop and maintaining your own counter variable. As you've already seen here, adding complexity results in bugs. Keep it simple.
Most languages provide a += operator, which for integers adds the amount to a variable. It's more concise than count = count + 1.
Use a parameter to define which character you're counting to make it more flexible. Define a default argument for using char='e' in the parameter list when you have an obvious default.
Choose a more appropriate name for the function. The name has_no_e() makes the reader think the code checks to see if the code has no e, but what it actually does is counts the occurrences of e.
Putting this all together we get:
def count_letter(word, char='e'):
count = 0
for c in word:
if c == char:
count += 1
return count
Some tests:
>>> count_letter('tee')
2
>>> count_letter('tee', 't')
1
>>> count_letter('tee', 'f')
0
>>> count_letter('wh' + 'e'*100)
100
Why not simply
def has_no_e(word):
return sum(1 for letter in word if letter=="e")
The problem is that the last value of 'letters' in your iteration is '0', and when this happens you look at:
word[letters-1]
meaning, you look at word[-1], which in python means "last letter of the word".
so you're actually counting correctly, and adding a "bonus" one if the last letter is 'e'.
It will count it twice when ending with an e because you decrement letters one time too many (because you loop while letters >= 0 and you should be looping while letters > 0). When letters reaches zero you check word[letters-1] == word[-1] which corresponds to the last character in the word.
Many of these suggested solutions will work fine.
Know that, in Python, list[-1] will return the last element of the list.
So, in your original code, when you were referencing word[letters-1] in a while loop constrained by letters >= 0, you would count the 'e' on the end of the word twice (once when letters was the length-1 and a second time when letters was 0).
For example, if my word was "Pete" your code trace would look like this (if you printed out word[letter] each loop.
e (for word[3])
t (for word[2])
e (for word[1])
P (for word[0])
e (for word[-1])
Hope this helps to clear things up and to reveal an interesting little quirk about Python.
#marcog makes some excellent points;
in the meantime, you can do simple debugging by inserting print statements -
def has_no_e(word):
letters = len(word)
count = 0
while letters >= 0:
ch = word[letters-1] # what is it looking at?
if ch == 'e':
count = count + 1
print('{0} <-'.format(ch))
else:
print('{0}'.format(ch))
letters = letters - 1
print count
then
has_no_e('tease')
returns
e <-
s
a
e <-
t
e <-
3
from which you can see that
you are going through the string in reverse order
it is correctly recognizing e's
you are 'wrapping around' to the end of the string - hence the extra e if your string ends in one
If what you really want is 'has_no_e' then the following may be more appropriate than counting 'e's and then later checking for zero,
def has_no_e(word):
return 'e' not in word
>>> has_no_e('Adrian')
True
>>> has_no_e('test')
False
>>> has_no_e('NYSE')
True
If you want to check there are no 'E's either,
def has_no_e(word):
return 'e' not in word.lower()
>>> has_no_e('NYSE')
False
You don't have to use a while-loop. Strings can be used for-loops in Python.
def has_no_e(word):
count = 0
for letter in word:
if letter == "e":
count += 1
print count
or something simpler:
def has_no_e(word):
return sum(1 for letter in word if letter=="e")