def countchar() to find frequency of letters in one sentence [closed] - python-2.7

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
def countchar(str):
list1 = [0]*26
for i in range(0,len(str)):
if (str[i] >= 'a' and str[i] <='z'):
***list1[ord(str[i])-0] += 1***
print list1
if __name__ == "__main__":
str = " GOOD morning and have a nice day"
str = str.lower()
print countchar(str)
there is an error in my code so I can achieve my goal.

Your main issue was that you needed to be subtracting ord("a") (which is 97) from each character to find its index in list1, not 0.
But I cleaned up the rest of your code too, since there were a lot of other inefficiencies and bad practices and stuff.
def countchar(sentence):
list1 = [0 for i in range(26)]
for c in sentence:
if 'a' <= c <= 'z':
list1[ord(c) - ord("a")] += 1
return list1
if __name__ == "__main__":
string = " GOOD morning and have a nice day"
string = string.lower()
print countchar(string)
In particular, it's bad practice to use keywords like str as variable names.
Also, depending on what you're planning to do with this, it's likely that a dictionary would work better for your purposes than a list.
Here's a quick rewrite (with the additional functionality that it'll count all characters, not just lowercase letters) using a dictionary:
def countchar(sentence):
char_dict = {}
for c in sentence:
if c in char_dict:
char_dict[c] += 1
else:
char_dict[c] = 1
return char_dict
if __name__ == "__main__":
string = " GOOD morning and have a nice day!!"
print "With uppercase (and punctuation, etc):"
print countchar(string)
print "All lowercase (and punctuation, etc):"
string = string.lower()
print countchar(string)
As requested in a comment, here is some clarification of the following line:
list1[ord(c) - ord("a")] += 1
First let's look at the inside, ord(c) - ord("a"). c is a string with only a single character in it, so ord(c) gives you the ASCII value for that string. Since you're mapping lowercase letters to the numbers 0, 1, ..., 25, we need to make sure that the letter "a" gets mapped to 0. Since, in ASCII, the letters are sequential (a=97, b=98, ..., z=122), then we can just subtract the smallest one from each one in order to map them:
a --> 97-97 = 0
b --> 98-97 = 1
c --> 99-97 = 2
...
z --> 122-97 = 25
So that's what ord(c) - ord("a") is doing. It's subtracting that 97 (which is the value of ord("a")) from each value, and giving a number between 0 and 25.
Then list1[ that number between 0 and 25 ] += 1 just increments the proper index in list1.

Related

Is there a pythonic way to count the number of leading matching characters in two strings?

For two given strings, is there a pythonic way to count how many consecutive characters of both strings (starting at postion 0 of the strings) are identical?
For example in aaa_Hello and aa_World the "leading matching characters" are aa, having a length of 2. In another and example there are no leading matching characters, which would give a length of 0.
I have written a function to achive this, which uses a for loop and thus seems very unpythonic to me:
def matchlen(string0, string1): # Note: does not work if a string is ''
for counter in range(min(len(string0), len(string1))):
# run until there is a mismatch between the characters in the strings
if string0[counter] != string1[counter]:
# in this case the function terminates
return(counter)
return(counter+1)
matchlen(string0='aaa_Hello', string1='aa_World') # returns 2
matchlen(string0='another', string1='example') # returns 0
You could use zip and enumerate:
def matchlen(str1, str2):
i = -1 # needed if you don't enter the loop (an empty string)
for i, (char1, char2) in enumerate(zip(str1, str2)):
if char1 != char2:
return i
return i+1
An unexpected function in os.path, commonprefix, can help (because it is not limited to file paths, any strings work). It can also take in more than 2 input strings.
Return the longest path prefix (taken character-by-character) that is a prefix of all paths in list. If list is empty, return the empty string ('').
from os.path import commonprefix
print(len(commonprefix(["aaa_Hello","aa_World"])))
output:
2
from itertools import takewhile
common_prefix_length = sum(
1 for _ in takewhile(lambda x: x[0]==x[1], zip(string0, string1)))
zip will pair up letters from the two strings; takewhile will yield them as long as they're equal; and sum will see how many there are.
As bobble bubble says, this indeed does exactly the same thing as your loopy thing. Its sole pro (and also its sole con) is that it is a one-liner. Take it as you will.

Repeat a function every 5 times a loop runs

Is there a way to repeat a single function in a while loop one in every 5 times the loop runs? I am trying to create a bot to help me with my Latin revision but I don't want the option to close the program to crop up every time I answer a question, it would be better if it only happened 1 out of 10 times.
import random
exit = "no"
print "welcome to latin learner v1"
wordtype = raw_input("what would you like to learn (nouns verbs everything)")
if wordtype == "nouns":
declension = raw_input("declension 1-5")
if declension == "1":
while "no" in exit:
wordno = random.randint(1,30)
noun1L = ["ancilla","aqua","cena","copiae","cura","dea","domina","epistula","femina","filia","hora","ianua","insula","ira","nauta","patria","pecunia","poena","porta","puella","regina","Roma","silva","taberna","terra","turba","via","victoria","villa","vita"]
answer = raw_input(noun1L[wordno])
noun1E = ["slave-girl" or"slave-woman","water","dinner" or "meal","forces" or "troops","care" or "worry","goddess","mistress","letter","woman","daughter","hour","door","island" or "block of flats","anger","sailor","country" or "homeland","money","punishment","gate","girl","queen","Rome","wood","shop" or "inn","ground" or "land" or "country","crowd","street" or "road" or "way","victory","house" or "country villa","life"]
if noun1E[wordno] == answer:
print "correct"
else:
print "incorrect"
print noun1E[wordno]
for i in range[1,5]:
exit = raw_input("would you like to quit (yes/no)")
To solve your issue, we can add a question counter and use the modulus operator (%) to trigger the exit option on every fifth question.
However, there are some other problems to address. For example, this:
,"dinner" or "meal",
is just wishful thinking -- it doesn't work that way. We can turn this into a list of possible answers. Next, whenever we have parallel arrays like noun1L and noun1E, it usually means we're missing a data structure. Finally, don't store the data in the code, separate them.
Here's my rework of your code addressing the above issues:
import random
noun1 = {
"ancilla": ["slave-girl", "slave-woman"],
"aqua": ["water"],
"cena": ["dinner", "meal"],
"copiae": ["forces", "troops"],
"cura": ["care", "worry"],
"dea": ["goddess"],
"domina": ["mistress"],
"epistula": ["letter"],
"femina": ["woman"],
"filia": ["daughter"],
"hora": ["hour"],
"ianua": ["door"],
"insula": ["island", "block of flats"],
"ira": ["anger"],
"nauta": ["sailor"],
"patria": ["country", "homeland"],
"pecunia": ["money"],
"poena": ["punishment"],
"porta": ["gate"],
"puella": ["girl"],
"regina": ["queen"],
"Roma": ["Rome"],
"silva": ["wood"],
"taberna": ["shop", "inn"],
"terra": ["ground", "land", "country"],
"turba": ["crowd"],
"via": ["street", "road", "way"],
"victoria": ["victory"],
"villa": ["house", "country villa"],
"vita": ["life"],
}
print("Welcome to Latin Learner v1")
wordtype = raw_input("What would you like to learn (nouns verbs everything): ")
if wordtype == "nouns" or wordtype == "everything":
declension = raw_input("Declension 1-5: ")
if declension == "1":
count = 1
while True:
word = random.choice(list(noun1))
answer = raw_input(word +": ")
if answer.lower() in noun1[word]:
print("Correct.")
else:
print("Incorrect: " + ", ".join(noun1[word]))
if count % 5 == 0:
answer = raw_input("would you like to quit (yes/no): ")
if "y" in answer.lower():
break
count += 1

Python - Obtain the most frequent word in a sentence, if there is a tie return the word that appears first in alphabetical order

I have written the following code below. It works without errors, the problem that I am facing is that if there are 2 words in a sentence that have been repeated the same number of times, the code does not return the first word in alphabetical order. Can anyone please suggest any alternatives? This code is going to be evaluated in Python 2.7.
"""Quiz: Most Frequent Word"""
def most_frequent(s):
"""Return the most frequently occuring word in s."""
""" Step 1 - The following assumptions have been made:
- Space is the default delimiter
- There are no other punctuation marks that need removing
- Convert all letters into lower case"""
word_list_array = s.split()
"""Step 2 - sort the list alphabetically"""
word_sort = sorted(word_list_array, key=str.lower)
"""Step 3 - count the number of times word has been repeated in the word_sort array.
create another array containing the word and the frequency in which it is repeated"""
wordfreq = []
freq_wordsort = []
for w in word_sort:
wordfreq.append(word_sort.count(w))
freq_wordsort = zip(wordfreq, word_sort)
"""Step 4 - output the array having the maximum first index variable and output the word in that array"""
max_word = max(freq_wordsort)
word = max_word[-1]
result = word
return result
def test_run():
"""Test most_frequent() with some inputs."""
print most_frequent("london bridge is falling down falling down falling down london bridge is falling down my fair lady") # output: 'bridge'
print most_frequent("betty bought a bit of butter but the butter was bitter") # output: 'butter'
if __name__ == '__main__':
test_run()
Without messing too much around with your code, I find that a good solution can be achieved through the use of the index method.
After having found the word with the highest frequency (max_word), you simply call the index method on wordfreq providing max_word as input, which returns its position in the list; then you return the word associated to this index in word_sort.
Code example is below (I removed the zip function as it is not needed anymore, and added two simpler examples):
"""Quiz: Most Frequent Word"""
def most_frequent(s):
"""Return the most frequently occuring word in s."""
""" Step 1 - The following assumptions have been made:
- Space is the default delimiter
- There are no other punctuation marks that need removing
- Convert all letters into lower case"""
word_list_array = s.split()
"""Step 2 - sort the list alphabetically"""
word_sort = sorted(word_list_array, key=str.lower)
"""Step 3 - count the number of times word has been repeated in the word_sort array.
create another array containing the word and the frequency in which it is repeated"""
wordfreq = []
# freq_wordsort = []
for w in word_sort:
wordfreq.append(word_sort.count(w))
# freq_wordsort = zip(wordfreq, word_sort)
"""Step 4 - output the array having the maximum first index variable and output the word in that array"""
max_word = max(wordfreq)
word = word_sort[wordfreq.index(max_word)] # <--- solution!
result = word
return result
def test_run():
"""Test most_frequent() with some inputs."""
print(most_frequent("london bridge is falling down falling down falling down london bridge is falling down my fair lady")) # output: 'down'
print(most_frequent("betty bought a bit of butter but the butter was bitter")) # output: 'butter'
print(most_frequent("a a a a b b b b")) #output: 'a'
print(most_frequent("z z j j z j z j")) #output: 'j'
if __name__ == '__main__':
test_run()

Python Iterating through a string to look for a Palindrome

So I have looked around this site and others for information on how to iterate through a string on Python, find a specific substring, reverse it and check if the two equaled in order to get a Palindrome. This is the problem though since some of the test cases are challenging to get and have confused me on how to find them through indexing.
This is my code that works for all, but two test cases:
def countPalindromes(s):
count = 0
firstindex = 0
lastindex = len(str)-1
while firstindex != lastindex and firstindex <= lastindex:
ch1 = s[firstindex:lastindex]
ch2 = s[lastindex:firstindex:-1]
if ch1 == ch2:
count +=1
firstindex +=1
lastindex -=1
return count
This code works for the following Palindromes: "racecar", " ", and "abqc".
It does not work for these Palindromes "aaaa" and "abacccaba".
For "aaaa" there are 6 palindromes and for "abacccaba" there are 8 palindromes. This is where my problem occurs, and I simply can't figure it out. For the 6 palindromes for "aaaa" I get aaaa, aaa, aa, twice for each. For "abacccaba" the 8 palindromes I have no idea as I get abacccaba, bacccab, accca, ccc, aba, aba.
I understand this is a confusing question, but I am lost how to approach the problem since I only get 2 for the "aaaa" and 4 for "abacccaba". Any ideas how I would cut out the substrings and get these values?
Thanks in advance!
while firstindex != lastindex and firstindex <= lastindex: misses the case of a single character palindrome.
You're also missing the case where aa contains three palindromes, 0:1, 0:2 and 1:2.
I think you're missing some palindromes for aaaa; there are 10:
aaaa
a
a
a
a
aa
aa
aa
aaa
aaa
If single-character palindromes do not count, then we have 6.
Either way, you need to consider all substrings as possible palindromes; not only the ones in the middle. Comparing a string against its reversed self is very easy to do in Python: s == s[::-1].
Getting all the substrings is easy too:
def get_all_substrings(input_string):
length = len(input_string)
return [input_string[i:j+1] for i in range(length) for j in range(i,length)]
and filtering out strings of length < 2 is also easy:
substrings = [a for a in get_all_substrings(string) if len(a) > 1]
Combining these should be fairly straight forward:
len([a for a in get_all_substrings(string) if len(a) > 1 and a == a[::-1]])
I think you should write a function(f) individually to check if a string is a palindrome.
Then make a function(g) that selects sub-strings of letters.
Eg: in string abcd, g will select a, b, c, d, ab, bc, cd, abc, bcd, abcd. Then apply f on each of these strings individually to get the number of palindromes.

how to loop a set amount of times

Im writing a code that simulates the game word scrabble. What im trying to do is that it asks the user to unscrabble the word, and if they fail at it once they get another chance and so on for 3 chances. after 3 chances the program should tell them that they couldn't guess it within the chances limit and the program should tell them the word.
rand_artist = artist_names[random.randrange(len(artist_names))]
tries = 0
while tries < 3:
rand_input = enterbox("Unscrabble the following: {}".
format(txt), "Word Scrabble")
if rand_input != rand_artist:
msgbox("Try again!", "Word Scrabble")
tries +=1
elif rand_input == rand_artist:
msgbox("Congratulations! You guessed the word!")
tries +=3
elif tries > 2:
msgbox("You used up three chances! The word was {}".
format(txt), "Word Scrabble!")
Your code had several problems, some noted in my comment on the question. The following works as you seem to want.
from random import choice, shuffle
artist_names = ['Renoir', 'VanGogh', 'Rembrant', 'Homer', 'Pyle',]
artist = choice(artist_names)
alist = list(artist)
shuffle(alist)
scram = ''.join(alist)
for tries in range(1, 4):
guess = input("Unscrabble {}: ".format(scram))
if guess == artist:
print("Congratulations! You guessed the word!")
break
elif tries < 3:
print("Try again!")
else:
print("Failed three chances! The word was {}.".format(artist))