Testing all Letters? - python

I am working on a script and the script should read a text file and test to see if the specified letters(a,a,r,d,v,a,r,k) are on each line. Im having a problem as I am trying to check for 3 different a's instead of just one. My code is below:
#Variables
advk = ['a','a','r','d','v','a','r','k']
textfile = []
number = 0
life = 0
for line in open('input.txt', 'rU'):
textfile.append(line.rstrip().lower())
while life == 0:
if all(word in textfile[number] for word in advk):
printed = number + 1
print ("Aardvark on line " + str(printed))
number+=1
if number == len(textfile):
life+=1
else:
number+=1

Everytime you want to count something in python, keep the Counter class in mind.
from collections import Counter
advk = Counter(['a','a','r','d','v','a','r','k'])
with open('input.txt', 'rU') as file:
for i, line in enumerate(file.readlines()):
if not advk - Counter(line.lower()):
print ("Aardvark on line " + str(i+1))
Given the input line
dffdaardvarksdsda
the Counter would look like these
Counter({'d': 5, 'a': 4, 'f': 2, 's': 2, 'r': 2, 'k': 1, 'v': 1})
and
Counter({'a': 3, 'r': 2, 'd': 1, 'k': 1, 'v': 1})
for your list of letters to search.
We use a trick by simply substracting the two Counters advl - Counter(line.lower()) and check if the resulting Counter has no elements left.
Other things to note:
You can use the with statement to ensure your file gets closed.
You can use enumerate instead counting the line numbers.

if advk list is variable and contents are read from somewhere else then to maintain unique elements in the list you can convert it to set and check.
advk = ['a','a','r','d','v','a','r','k']
advk = list(set(advk))
This makes advk a unique list and avoids check multiple 'a's in the line.

# If the line "ardvrk" should match, this is a solution:
chars=set('aardvark')
for nr, line in enumerate(open('input.txt', 'rU')):
if not chars-set(line): # is subset?
print 'match', nr, line,

Related

how to find the most popular letter in a string that also has the lowest ascii value

Implement the function most_popular_character(my_string), which gets the string argument my_string and returns its most frequent letter. In case of a tie, break it by returning the letter of smaller ASCII value.
Note that lowercase and uppercase letters are considered different (e.g., ‘A’ < ‘a’). You may assume my_string consists of English letters only, and is not empty.
Example 1: >>> most_popular_character("HelloWorld") >>> 'l'
Example 2: >>> most_popular_character("gggcccbb") >>> 'c'
Explanation: cee and gee appear three times each (and bee twice), but cee precedes gee lexicographically.
Hints (you may ignore these):
Build a dictionary mapping letters to their frequency;
Find the largest frequency;
Find the smallest letter having that frequency.
def most_popular_character(my_string):
char_count = {} # define dictionary
for c in my_string:
if c in char_count: #if c is in the dictionary:
char_count[c] = 1
else: # if c isn't in the dictionary - create it and put 1
char_count[c] = 1
sorted_chars = sorted(char_count) # sort the dictionary
char_count = char_count.keys() # place the dictionary in a list
max_per = 0
for i in range(len(sorted_chars) - 1):
if sorted_chars[i] >= sorted_chars[i+1]:
max_per = sorted_chars[i]
break
return max_per
my function returns 0 right now, and I think the problem is in the last for loop and if statement - but I can't figure out what the problem is..
If you have any suggestions on how to adjust the code it would be very appreciated!
Your dictionary didn't get off to a good start by you forgetting to add 1 to the character count, instead you are resetting to 1 each time.
Have a look here to get the gist of getting the maximum value from a dict: https://datagy.io/python-get-dictionary-key-with-max-value/
def most_popular_character(my_string):
# NOTE: you might want to convert the entire sting to upper or lower case, first, depending on the use
# e.g. my_string = my_string.lower()
char_count = {} # define dictionary
for c in my_string:
if c in char_count: #if c is in the dictionary:
char_count[c] += 1 # add 1 to it
else: # if c isn't in the dictionary - create it and put 1
char_count[c] = 1
# Never under estimate the power of print in debugging
print(char_count)
# max(char_count.values()) will give the highest value
# But there may be more than 1 item with the highest count, so get them all
max_keys = [key for key, value in char_count.items() if value == max(char_count.values())]
# Choose the lowest by sorting them and pick the first item
low_item = sorted(max_keys)[0]
return low_item, max(char_count.values())
print(most_popular_character("HelloWorld"))
print(most_popular_character("gggcccbb"))
print(most_popular_character("gggHHHAAAAaaaccccbb 12 3"))
Result:
{'H': 1, 'e': 1, 'l': 3, 'o': 2, 'W': 1, 'r': 1, 'd': 1}
('l', 3)
{'g': 3, 'c': 3, 'b': 2}
('c', 3)
{'g': 3, 'H': 3, 'A': 4, 'a': 3, 'c': 4, 'b': 2, ' ': 2, '1': 1, '2': 1, '3': 1}
('A', 4)
So: l and 3, c and 3, A and 4
def most_popular_character(my_string):
history_l = [l for l in my_string] #each letter in string
char_dict = {} #creating dict
for item in history_l: #for each letter in string
char_dict[item] = history_l.count(item)
return [max(char_dict.values()),min(char_dict.values())]
I didn't understand the last part of minimum frequency, so I make this function return a maximum frequency and a minimum frequency as a list!
Use a Counter to count the characters, and use the max function to select the "biggest" character according to your two criteria.
>>> from collections import Counter
>>> def most_popular_character(my_string):
... chars = Counter(my_string)
... return max(chars, key=lambda c: (chars[c], -ord(c)))
...
>>> most_popular_character("HelloWorld")
'l'
>>> most_popular_character("gggcccbb")
'c'
Note that using max is more efficient than sorting the entire dictionary, because it only needs to iterate over the dictionary once and find the single largest item, as opposed to sorting every item relative to every other item.

Print top 3 scores and bottom 3 scores in a file

#Name,Scores
a,6
b,8
c,2
k,23
d,18
r,13
w,4
h,9
The code should print the Name and Scores of the top 3 bands in order (starting with top, to bottom).
The code should then print the Name and Scores of the bottom 3 bands in order (starting with bottom, to top).
How do I do this?
Thank you in advance.
You should make them variables and store the values into the variables, then use a while True: line and add a line that compares one variable with another, then use print() to print all the top 3 first then print() the bottom 3.
Something like this:
with open ('data.txt') as f:
lines = [l.strip() for l in f.readlines()]
lines = [tuple(l.split(',')) for l in lines]
lines.sort(key=lambda tup: int(tup[1]))
print(lines[:3])
lines[-3:].reverse()
print(lines[-3:])
where data.txt is
a,6
b,8
c,2
k,23
d,18
r,13
w,4
h,9
You Can use list of tuples and use slicing to obtain the results
lt = [('a',6),
('b',8),
('c',2),
('k',23),
('d',18),
('r',13),
('w',4),
('h',9)]
print(lt[:3]) #for first three
print(lt[-3:]) #for last three
convert it into dictionary, then sort the dictionary and then print top and bottom bands.
team = {'a': 6, 'b': 8, 'c': 2, 'k': 23, 'd': 18, 'r': 13, 'w': 4, 'h': 9}
team = sorted(team.items(), key =
lambda kv:(kv[1], kv[0]), reverse=True)
print(team)
print("Top 3 Bands")
print(team[:3])
print("Bottom 3 Bands")
print(team[-3:])

Counting only the frequency of letters in a string

I am trying to make my program count everything but numbers in a string, and store it in a dictionary.
So far I have this:
string = str(input("Enter a string: "))
stringUpper = string.upper()
dict = {}
for n in stringUpper:
keys = dict.keys()
if n in keys:
dict[n] += 1
else:
dict[n] = 1
print(dict)
I just want the alphabetical numbers quantified, but I cannot figure out how to exclude the non-alphabetical characters.
Basically there are multiple steps involved:
Getting rid of the chars that you don't want to count
Count the remaining
You have several options available to do these. I'll just present one option, but keep in mind that there might be other (and better) alternatives.
from collections import Counter
the_input = input('Enter something')
Counter(char for char in the_input.upper() if char.isalpha())
For example:
Enter something: aashkfze3f8237rhbjasdkvjuhb
Counter({'A': 3,
'B': 2,
'D': 1,
'E': 1,
'F': 2,
'H': 3,
'J': 2,
'K': 2,
'R': 1,
'S': 2,
'U': 1,
'V': 1,
'Z': 1})
So it obviously worked. Here I used collections.Counter to count and a generator expression using str.isalpha as condition to get rid of the unwanted characters.
Note that there are several bad habits in your code that will make your life more complicated than it needs to be:
dict = {} will shadow the built-in dict. So it's better to choose a different name.
string is the name of a built-in module, so here a different name might be better (but not str which is a built-in name as well).
stringUpper = string.upper(). In Python you generally don't use camelCase but use _ to seperate word (i.e. string_upper) but since you only use it to loop over you might as well use for n in string.upper(): directly.
Variable names like n aren't very helpful. Usually you can name them char or character when iterating over a string or item when iterating over a "general" iterable.
You can use re to replace all non-alphabetical characters before doing any manipulation:
regex = re.compile('[^a-zA-Z]')
#First parameter is the replacement, second parameter is your input string
regex.sub('', stringUpper )
string = str(input("Enter a string: "))
stringUpper = string.upper()
dict = {}
for n in stringUpper:
if n not in '0123456789':
keys = dict.keys()
if n in keys:
dict[n] += 1
else:
dict[n] = 1
print(dict)
for n in stringUpper:
if n.isalpha()
dict[n] += 1
else:
dict[n] = 1
print(dict)
You can check string for alphanumeric
n.isalnum()
for aphabetic:
n.isalpha()
So your code will be like:
dict = {}
for n in stringUpper:
if n.isalpha():
keys = dict.keys()
if n in keys:
dict[n] += 1
else:
dict[n] = 1
print(dict)
else:
#do something....
While iterating, check if the lower() and upper() is the same for a character. If they are different from each other, then it is an alphabetical letter.
if n.upper() == n.lower():
continue
This should do it.

Program is repeating itself -can't figure out why

This is my program so far...it takes a message (input from user) and tells the user how many A's are in the program, how many B's, etc. Except when I input a message such as "Dad", it'll tell me how many D's there are twice instead of just saying everything once.
It says:
D ... 2
A ... 1
D ... 2
I want it to say:
A ... 1
D ... 2
How do I fix this without using zip, and without importing anything?
message=input("what is your message?").upper()
alphabet=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
count=[0]*len(alphabet)
for i in message:
if i in alphabet:
count[alphabet.index(i)]+=1
for i in message:
print (i,"...",count[alphabet.index(i)])
(Thanks to Uriel Eli for helping me get the program this far btw).
I don't agree with your approach here. You have actually over complicated this. The proper way to solve this is to actually use a dictionary to keep track of all the letters in the string and keep a count every time the same character comes up. Note, this also sticks to the rule of not importing anything.
Furthermore, this removes the necessity to have a list of letters to check against as well.
Also, if you need to count upper and lower case characters separtely, do not call upper at the end of your input. Just remove it. If you have to count upper and lower case as the same character, then you can leave it.
message=input("what is your message?").upper()
d = {}
for c in message:
if c in d:
d[c] += 1
else:
d[c] = 1
Demo
what is your message?thisisastringofthings
{'H': 1, 'F': 0, 'O': 0, 'R': 0, 'G': 1, 'S': 3, 'T': 2, 'A': 0, 'I': 3, 'N': 1}
To provide an output similar to what you are expecting, you just need to iterate through your final result and print:
for character, count in d.items():
print("{} ... {}".format(character, count))
Finally, just for the sake of showing the best way to do this, is to actually use Counter from collections:
>>> from collections import Counter
>>> Counter("thisisastring")
Counter({'s': 3, 'i': 3, 't': 2, 'h': 1, 'n': 1, 'a': 1, 'r': 1, 'g': 1})
Just for future reference, and I know that you CANT import anything now. The best way probably would be:
from collections import Counter
message=input("what is your message?").upper()
print(Counter(message))
# Counter({'D': 2, 'A': 1})
Your second for loop is iterating through message, so if the user input DAD (well... after upper casing it), you're gonna get:
message == DAD
i = D --> Shows 2
i = A --> Shows 1
i = D --> Shows 2 (again)
Maybe you'd want to iterate through count, keeping the index that you are iterating (to use it latter to match it with the alphabet list). Something like that:
for index, num_occurences in enumerate(count):
if num_occurences > 0:
print("Match found at i=%s which corresponds with alphabet[%s]=%s" %
(index, index, alphabet[index]))
print(alphabet[index], "...", num_occurences)
You should check what enumerate does.
If you still want to iterate through message, you can do it, keeping track of what letter did you already display using an auxiliary set (so you don't show the same letter again)
already_shown_letters = set()
for i in message:
if i not in already_shown_letters:
print (i,"...",count[alphabet.index(i)])
already_shown_letters.add(i)

key error: 'x' --> adding key value pair in for loop, key being char

I am a beginner in python and I am trying to solve a coding problem, got this error. Don't understand why ? I went through a couple of Q/A's here but they don't seem to solve my problem. Essentially what I am trying to do is iterate over a string, through its characters and fill these characters in a dictionary. With characters being the keys and values being the number of times these characters appeared. So I'm trying the following:
def myfunc(mystring):
for i in mystring:
if charCounter[i]:
charCounter[i] += 1
charCounter[i] = 1
mystring = "hello! how are you ?"
myfunc(mystring)
and Im getting following error:
File "xyq.py", line 3, in myfunc
if CharCounter[i]:
KeyError: 'h'
Can someone please suggest, where am I going wrong ? And if possible how can I improve the code ?
Thanks
You need to check if i is in charCounter before you try to retrieve it:
if i in charCounter:
charCounter[i] += 1
else:
charCounter[i] = 1
Or alternatively:
if charCounter.get(i):
...
if charCounter[i]:
throws KeyError if the key does not exist. What you want to do isuse if i in charCounter: instead:
if i in char_counter:
char_counter[i] += 1
else:
char_counter[i] = 1
Alternatively you could use get which gets the value if it exists, or returns the second (optional) value if it didn't exist:
char_counter[i] = char_counter.get(i, 0) + 1
However this counting pattern is so popular that a whole class exists for it: collections.Counter:
from collections import Counter
def my_func(my_string):
return Counter(my_string)
Example:
>>> counts = my_func('hello! how are you ?')
>>> counts
Counter({' ': 4, 'o': 3, 'h': 2, 'l': 2, 'e': 2, '!': 1, 'r': 1, 'a': 1,
'?': 1, 'w': 1, 'u': 1, 'y': 1})
>>> counts[' ']
4
collections.Counter is a subclass of dictionary, so it would behave in the same way that an ordinary dictionary would do with item access and so forth.

Categories