Define the get_triples_dict() function which is passed a string of text
as a parameter. The function first converts the parameter string to
lower case and then returns a dictionary with keys which are all the
unique consecutive three alphabetic characters from the text, and the
corresponding values are the number of times the three consecutive
alphabetic characters appear in the text. Use the isalpha() method to
check if a character is alphabetic or not. The dictionary should only
contain entries which occur more than once. After your dictionary has
been created and populated, you need to remove any key-value pairs which
have a corresponding value of 1.
I need help with coding this get_triples_dict function:
def get_triples_dict(text):
def test_get_triples_dict():
print("1.")
print_dict_in_key_order(get_triples_dict('super, duper'))
print("\n2.")
print_dict_in_key_order(get_triples_dict("ABC ABC ABC"))
print("\n3.")
print_dict_in_key_order(get_triples_dict("Sometimes the smallest things make more room in your heart"))
print("\n4.")
print_dict_in_key_order(get_triples_dict("My favourite painting is the painting i did of my dog in that painting in my den"))
I am not going to complete your assignment for you, but below is a good start to what you need to do. I believe you can write the code that sorts the words and prints out the dictionary. Make sure to study each line and then once you get the general idea, write your own version.
def get_triples_dict(text):
d = dict()
text = text.lower().replace(' ', '') # set to lowercase and remove spaces
for i in range(len(text) - 2): # stops early to prevent index out of bounds exception
bit = text[i: i + 3] # characters in groups of 3
if all(c.isalpha() for c in bit): # all characters must be alphabetic
if not bit in d: # if there's no entry
d[bit] = 0
d[bit] += 1
copy = d.copy() # we cannot remove items from a list we are looping over (concurrent modification exception)
for key, value in copy.items():
if value == 1: # remove items with counts of 1
d.pop(key)
return d
Related
Challenge: Take 2 strings s1 and s2 including only letters from a to z. Return a new sorted string, the longest possible, containing distinct letters - each taken only once - coming from s1 or s2.
# Examples
a = "xyaabbbccccdefww"
b = "xxxxyyyyabklmopq"
assert longest(a, b) == "abcdefklmopqwxy"
a = "abcdefghijklmnopqrstuvwxyz"
assert longest(a, a) == "abcdefghijklmnopqrstuvwxyz"
So I am just starting to learn, but so far I have this:
def longest(a1, a2):
for letter in max(a1, a2):
return ''.join(sorted(a1+a2))
which returns all the letters but I am trying to filter out the duplicates.
This is my first time on stack overflow so please forgive anything I did wrong. I am trying to figure all this out.
I also do not know how to indent in the code section if anyone could help with that.
You have two options here. The first is the answer you want and the second is an alternative method
To filter out duplicates, you can make a blank string, and then go through the returned string. For each character, if the character is already in the string, move onto the next otherwise add it
out = ""
for i in returned_string:
if i not in out:
out += i
return out
This would be empedded inside a function
The second option you have is to use Pythons sets. For what you want to do you can consider them as lists with no dulicate elements in them. You could simplify your function to
def longest(a: str, b: str):
return "".join(set(a).union(set(b)))
This makes a set from all the characters in a, and then another one with all the characters in b. It then "joins" them together (union) and you get another set. You can them join all the characters together in this final set to get your string. Hope this helps
I think I was close to figuring out how to print out all the possible words based on user input from my set dictionary. it's based on the assumption that the user input is 'ART' so the possible words I have in my dictionary are ART, RAT, TART, and TAR but only the three letter combinations are printing out. can anyone tell me where I am going wrong? Thanks!
Dictionary = ["tar","art","tart","rat"] #creates dictionary of set words
StoredLetters = input('input your word here: ') #allows the user to input any word
list(StoredLetters)
def characters(word):
Dictionary = {}
for i in word:
Dictionary[i] = Dictionary.get(i, 0) + 1
return Dictionary
def all_words(StoredLetters, wordSet):
for word in StoredLetters:
flag = 1
words = characters(word)
for key in words:
if key not in wordSet:
flag = 0
else:
if wordSet.count(key) != words[key]:
flag = 0
if flag == 1:
print(word)
if __name__ == "__main__":
print(all_words(Dictionary, StoredLetters))
It appears there are a few things that could contribute to this.
You are swapping the parameters on all words def allwords(Dictionary, StoredLetters): when you call it in main allwords(StoredLetters, Dictionary). Without specifying the name (look up named parameters in python) you would be swapping the input.
In the characters function it would appear you are resetting the dictionary variable. Try using unique names when creating new variables. This is causing the dictionary of words you set at the top to be emptied out when characters(word) is called
First off, you are confusing things by having the name of your variable StoredLetters also being the name of one of the arguments to your all_words function.
Second, you are actually passing in StoredLetters, which is art, as the 2nd argument to the function, so it is wordSet in the function, not StoredLetters!
You should really keep things more clear by using different variable names, and making it obvious what are you using for which argument. words isn't really words, it's a dictionary with letters as keys, and how many times they appear as the values! Making code clear and understandable goes a long way to making it easy to debug. You have word, StoredLetters, wordSet, another StoredLetters argument, words = characters(word) which doesn't do what is expected. This could all use a good cleanup.
As for the functionality, with art, each letter only appears once, so for tart, which has t twice, if wordSet.count(key) != words[key] will evaluate as True, and flag will be set to 0, and the word will not be printed.
Hope that helps, and happy coding!
Based on the follow-up comments, the rule is that we must use all characters in the target word, but we can use each character as many times as we want.
I'd set up the lookup "dictionary" data structure as a Python dict which maps sorted, unique characters as tuples in each dictionary word to a list of the actual words that can be formed from those characters.
Next, I'd handle the lookups as follows:
Sort the unique characters of the user input (target word) and index into the dictionary to get the list of words it could make. Using a set means that we allow repetition and sorting the characters means we normalize for all of the possible permutations of those letters.
The above alone can give false positives, so we filter the resulting word list to remove any actual result words that are shorter than the target word. This ensures that we handle a target word like "artt" correctly and prevent it from matching "art".
Code:
from collections import defaultdict
class Dictionary:
def __init__(self, words):
self.dictionary = defaultdict(list)
for word in words:
self.dictionary[tuple(sorted(set(word)))].append(word)
def search(self, target):
candidates = self.dictionary[tuple(sorted(set(target)))]
return [x for x in candidates if len(x) >= len(target)]
if __name__ == "__main__":
dictionary = Dictionary(["tar", "art", "tart", "rat"])
tests = ["art", "artt", "ar", "arttt", "aret"]
for test in tests:
print(f"{test}\t=> {dictionary.search(test)}")
Output:
art => ['tar', 'art', 'tart', 'rat']
artt => ['tart']
ar => []
arttt => []
aret => []
The issues in the original code have been addressed nicely in the other answers. The logic doesn't seem clear since it's comparing characters to words and variable names often don't match the logic represented by the code.
It's fine to use a frequency counter, but you'll be stuck iterating over the dictionary, and you'll need to check that each count of a character in a dictionary word is greater than the corresponding count in the target word. I doubt the code I'm offering is optimal, but it should be much faster than the counter approach, I think.
def flames(l,l1):
for i in l:
if i in l1:
l.remove(str(i))
l1.remove(str(i))
n1=input("Enter first name:")
n2=input("Enter Second name:")
l=list(n1)
l1=list(n2)
flames(l,l1)
print(l)
print(l1)
I didn't completed my code entirely.But i am done with removing matched character.But the problem is its removing only first matched character.It's not removing remaining match characters.What is the problem in my code?
You might find it easier to use a dict instead of a list to keep track of the letters left in each name. For instance, if the name is "Billy", the dict would be: {"b":1, "i":1, "l":2, "y":1}. In this way you can easily remove all instances of the letter because they're all stored in the same location.
Easiest way to create the dictionaries for each name would be dictionary comprehension:
n1 = input("Enter first name: ").lower()
d1 = { char:n1.count(char) for char in n1 }
Of course, the order of these letters doesn't matter and will likely appear in a different order. Also notice that the "B" in "Billy" becomes "b" in the dictionary. This might be a matter of preference for purposes of this game, but generally you would want to convert all characters to lowercase so upper and lower case letters are not treated as distinct.
There's one more thing to consider when using a dict rather than a list to store the characters: you can't modify the dictionary as you're iterating over it, you'll get a RuntimeError. So as you're iterating through d1 (the characters in the first name) and deleting the matching characters in d2, you'll have to remember the matched characters so you can delete them from d1 later.
d1ToDel = []
for k in d1:
if k in d2:
del d2[k]
d1ToDel.append(k)
for k in d1ToDel:
del d1[k]
After that, you just have to sum up the values remaining in each dictionary, which will give you the remaining number of characters after removing all matches. And then do a little modulo arithmetic to figure out which of the "Flames" characters the pair will land on.
Hello I have already done a through search before asking this question as I always do. I am trying to do use a dictionary to go from a written word to each individual letters corresponding letter on a phone key board using a dictionary in python. This is easy to do without a dictionary, but using a dictionary although faster to code is quite confusing to me. Help would be appreciated. My code so far is
def phone (word):
d = {'A''B''C':2,'D''E''F':3,'G''H''I':4,'J''K''L':5}
for i in range (len(word)):
word.split ()
return d[word]
the word I am trying to use is 'ADGJ' just as a test.
my errors that I am getting:
File "<pyshell#13>", line 1, in <module>
phone('ADGJ')
File "C:\Users\Christopher\Desktop\pratice.py", line 195, in phone
return d[word]
KeyError: 'ADGJ'
I have a key error I thought the word.split would take care of any issues but it doesn't. any suggestions?
thank you
I changed the code up a bit: I now have this:
def phone (word):
d = {'A':2, 'B':3}
word = word.split()
return d[word]
but I get a new error:
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
phone ('ABABBAA')
File "C:\Users\Christopher\Desktop\pratice.py", line 194, in phone
return d[word]
TypeError: unhashable type: 'list'
the word I am using just consits of 'ABBABABA' just because that is all I have defined in my dictionary since this is a test of understanding.
I guess I still need something to make the connection for the dictionary function thing to work but still trying to figure out what that is...
This is not valid Python
d = {'A''B''C':2,'D''E''F':3,'G''H''I':4,'J''K''L':5}
You would need to define each key, value pair
d = {
'A':2, 'B':2, 'C':2,
'D':3, 'E':3, ... etc
}
You can then convert the word into the corresponding digits
def getNums(word):
return ''.join(str(d[i]) for i in word)
>>> getNums('ADGJ')
'2345'
Your syntax is a little off; you can't let assignment in a dictionary fall through like in a switch statement.
Try this:
d = {'A':2,'B':2,'C':2,'D':3,'E':3,'F':3,'G':4,'H':4,'I':4,'J':5,'K':5,'L':5}
OK, so let me try to help you.
This is your current code:
def phone (word):
d = {'A':2, 'B':3}
word = word.split()
return d[word]
The first line defines your function signature, that means you've got a function called phone which takes a parameter called word. My first comment is: chose appropriate names for functions and variables. phone is not a "function", since a function is kind of an instruction or a command like thing, but never mind (letters_to_phonenumber would be better I think).
The second line defines a dictionary, which maps 'A' to 2, 'B' to '3'. That's OK for now.
The third line overwrites your word variable with the return value of the split() function, which is a method of the string class. Let's look up the documentation for this: https://docs.python.org/2/library/stdtypes.html#str.split
str.split([sep[, maxsplit]]):
Return a list of the words in the string, using sep as the delimiter string.
Since you obviously did not define a sep(arator), we have to figure out what the function will do. Reading further says:
If sep is not specified or is None, a different splitting algorithm is
applied: runs of consecutive whitespace are regarded as a single
separator, and the result will contain no empty strings at the start
or end if the string has leading or trailing whitespace. Consequently,
splitting an empty string or a string consisting of just whitespace
with a None separator returns [].
So it will look for whitespace within your string. You don't know what a whitespace is? Let's google: http://en.wikipedia.org/wiki/Whitespace_character
In computer science, whitespace is any character or series of
whitespace characters that represent horizontal or vertical space in
typography. When rendered, a whitespace character does not correspond
to a visible mark, but typically does occupy an area on a page.
OK, now we know, that whitespace is like space or tab etc. A string like "ABABBAA" does not contain any whitespace, so split() will obviously return only a list with exactly one item in it: the input string itself.
Let's fire up the python interpreter to check this (this is a common way of debugging):
>>> 'ABABBAA'.split()
['ABABBAA']
The next line in your code is return d[word]. So the function terminates here and returns an output value, namely d[word]. But what is the value of d[word]? Well, d is a dictionary (with the keys 'A' and 'B') and you try to find the value of the key ['ABABBAA']. But there is no such key in your dictionary d, let alone there is no way to create a key for a dictionary, since a key has to be a hashable object. What is a hashable object? Let's google: https://docs.python.org/2/glossary.html
hashable: An object is hashable if it has a hash value which never
changes during its lifetime (it needs a hash() method), and can be
compared to other objects (it needs an eq() or cmp() method).
Hashable objects which compare equal must have the same hash value.
Hashability makes an object usable as a dictionary key and a set
member, because these data structures use the hash value internally.
All of Python’s immutable built-in objects are hashable, while no
mutable containers (such as lists or dictionaries) are. Objects which
are instances of user-defined classes are hashable by default; they
all compare unequal (except with themselves), and their hash value is
their id().
OK, so 'A' would be hashable ;-) and any kind of number of string etc. but not a list, in this sense.
So what now? You have to find a way to somehow separate the letters in your input word. This can be easily done with slicing, or simply iterating over the string (in Python, strings are iterable):
for letter in word:
# this loop will iterate over word and assign each of its letters to
# the variable `letter`, which you can use in this scope
But how do we actually return the phone number? This will not work:
def phone (word):
d = {'A':2, 'B':3}
for letter in word:
return d[letter]
Why? Because it will stop at the first letter and terminate the function (remember the return statement?).
The way to go is to collect all the numbers and when we're done, simply put all together and return them. This is a common way to handle such problems. We first initialise a list, which we can manipulate in each for-iteration:
def phone (word):
d = {'A':2, 'B':3}
digits = []
for letter in word:
digits.append(d[letter])
return digits
Great! Looks better now:
>>> phone('ABA')
[2, 3, 2]
Now try to figure out how to return a real number instead of a list.
This is btw. kind of a basic workflow of a programmer. A lot of research and look-up in (API) documentation, solving puzzles and looking at few lines of code hours long. If you don't love it, you'll never become a programmer.
i'm super duper new in python. I'm kinda stuck for one of my class exercises.
The question goes something like this: You have a file that contains characters i.e. words. (I'm still at the stage where all the terms get mixed up, I apologize if that is not the correct term)
Example of the file.txt content: accbd
The question asks me to import the file to python editor and make sure that no letter occurs more than letter that comes later than it in the alphabet. e.g. a cannot occur more frequently than b; b cannot occur more than c, and so on. In the example file, c occurs more frequently than d, so I need to raise an error message.
Here's my pathetic attempt :
def main():
f=open('.txt','r') # 1st import the file and open it.
data = f.read() #2nd read the file
words = list(data) #3rd create a list that contains every letter
newwords = sorted(words) # sort according to alphabetical order
I'm stuck at the last part which is to count that the former word doesn't occur more than the later word, and so on. I tried two ways but neither is working. Here's trial 1:
from collections import counter
for i in newwords:
try:
if counter(i) <=counter(i+1):
print 'ok'
else:
print 'not ok between indexes %d and %d' % (i, i+1)
except:
pass
The 2nd trial is similar
for i in newwords:
try:
if newwords.count(i) <= newwords.count(i+1):
print 'ok'
else:
print 'ok between indexes %d and %d' % (i, i+1)
except:
pass
What is the correct way to compare the count for each word in sequential order?
I had posted an answer, but I see it's for an assignment, so I'll try to explain instead of just splatting a solution here.
My suggestion would be to solve it in three steps:
1) in the first line, create a list of sorted characters that appear in the string:
from the data string you can use set(data) to pick every unique character
if you use sort() on this set you can create a list of characters, sorted alphabetically.
2) then use this list in a for loop (or list comprehension) to create a second list, of their number of occurrences in data, using data.count(<letter in the list>); note that the elements in this second list are technically sorted based on the alphabetical order of the letters in the first list you made (because of the for loop).
3) compare this second list of values with a sorted version of itself (now sorted by values), and see if they match or not. If they don't match, it's because some of the initial letters appears too many times compared to the next ones.
To be a little more clear:
In [2]: string = 'accbd'
In [3]: import collections
In [4]: collections.Counter(string)
Out[4]: Counter({'c': 2, 'a': 1, 'b': 1, 'd': 1})
Then it's just a for loop with enumerate(list_).