I've got the following which takes multiple lines of user input such as 'English Bob Luke' to store a Set in a Dictionary about which people speak which language. I've used a Dictionary to hold the multiple lines of input to create multiple Sets, but I now need to compare the difference between Sets to see if someone only speaks one language.
languages = {}
while True:
info = input('Line: ').split()
if info != []:
languages[info[0]] = set(info[1:])
else:
break
I can print the sets using the code below, but it doesn't seem to really get me anywhere!
for tongue in languages:
print(set(languages[tongue]))
Totally stuck - any help would be greatly appreciated!
UPDATE
Here in example of what I am trying to achieve:
Line: English Tim Nicky James John Ben
Line: German Nicky Tim Tara
Line: Mandarin Tim John
Line:
James is monolingual.
Tara is monolingual.
Ben is monolingual.
SOLUTION
Completely re-though my approach and ditched the Dictionary! :
english = input("Line: ").split()
en_speakers = set(english[1:len(english)])
multi_speakers = set()
while True:
language = input("Line: ").split()
lan_speakers = language[1:len(language)]
if language == []:
break
else:
multi_speakers |= set(lan_speakers)
monolinguals = en_speakers.difference(multi_speakers)
for person in monolinguals:
print(person, 'is monolingual.')
if multi_speakers == en_speakers:
print ('Everyone is multilingual!')
I'd reverse the order of keys and values in your dictionary, because it makes the problem so much easier. So rather than storing per language the different users that speak it, just create a per user profile of all the languages that person speaks:
from collections import defaultdict
user_langs = defaultdict(list)
while True:
info = map(lambda s: s.strip(), raw_input('Line: ').split())
if info:
for user in info[1:]:
user_langs[user].append(info[0])
else:
break
for user in user_langs:
if len(user_langs[user]) < 2:
print("{} is monolingual.".format(user))
languages[toungue] is already a set, you don't need to set(languages[touge]).
Also you don't need to loop the dictionary you can simply get those set from dictionary by lanuages.values().
Not entirely sure what you want to achieve here though. At a wild guess, you may want the unique value from the languages values?
You can achieve this by updating values to a new set:
Change this:
for tongue in languages:
print(set(languages[tongue]))
To this:
new_set = set()
for v in languages.values():
new_set.update(v)
new_set # dummy lanugages
{'English', 'Japanese', 'whatever', 'yeah'}
Updated
To achieve what you want, you can use Counter and return the key if value == 1.
A more detailed explanation is that, under a for/loop you are going to compare 1 set to another set. But what you actually need,is to compare all sets, so I choose to use c to update all individual set values under a for/loop, and afterward do whatever you want out from that c. I use Counter here as what you want to count if anyone has only got 1 language.
from collections import Counter
c = Counter()
for v in languages.values():
c.update(v)
for k,v in c.iteritems():
if v == 1:
print k, " is monolingual"
Ben is monolingual
James is monolingual
Tara is monolingual
The c looks like this:
c
Counter({'Tim': 3, 'Nicky': 2, 'John': 2, 'Ben': 1, 'James': 1, 'Tara': 1})
Related
I know this is relatively a basic question. I am trying to verify if given two sentences are synonym based on the given dictionary.
For example if dictionary is [(movie, film), (john, jack)] then "john likes movie" and "jack likes film" are synonym thus the function below will return true.
I changed each of two strings into the list of words by using lower/strip/split, then I tried to compare both lists by using for and if condition. I can't figure out where I did wrong.
def synonym_checker(synonyms, sentences):
a=sentences[0][0]
b=sentences[0][1]
a.lower()
b.lower()
a.strip()
b.strip()
aw=a.split()
bw=b.split()
import string
at = a.maketrans('','',string.punctuation)
bt = b.maketrans('','',string.punctuation)
ase = [w.translate(at) for w in aw]
bs = [w.translate(bt) for w in bw]
dictionary = dict(synonyms)
this = True
for i in range(0, min(len(ase), len(bs))):
if ase[i] != bs[i]:
if (bs[i] != dictionary[ase[i]]) and bs[i] not in [first for first, second in dictionary.items() if second == ase[i]]:
this = False
if (len(ase) != len(bs)):
this = False
is_synonym = this
print(ase)
print(bs)
return is_synonym # boolean
a = [("film", "movie"), ("revadfsdfs", "ads")]
b = [("I really want to watch that movie, as it had good fdf.", "I really want to watch that film, as it had good fdsaa")]
print(synonym_checker(a, b))
So, your error happened on
dictionary[ase[i]]
Because what you did here is actually
{'film': 'movie', 'revadfsdfs': 'ads'}['movie']
When your "movie" is not a key, but a value.
{'film': 'movie', 'revadfsdfs': 'ads'}
.. ^......... ^.............. ^ ............ ^
key .....value ....... key ....... value
The true problem here in my opinion is, your approach is not correct. Because dictionary is a one-way information, so when you want to check both 'film' to 'movie' and 'movie' to 'film', don't use a dictionary.
It also looks like you are trying to do something unnecessarily complicated for what you are trying to achieve.
a.lower()
b.lower()
a.strip()
b.strip()
Does not do anything to the actual program
The way you named your variables are also very hard to read, so maybe pick a proper name instead.
tuplelist = [('John', 'David', 'Roger'), ('Linda', 'Jane', 'Siri')]
counter = 0
for x in tuplelist:
if counter != 0:
print(' likes ' + x[0])
print(x[0], end='')
counter += 1
I'm trying to find a good way to print the following using the list of tuples from the code above:
John likes Linda
David likes Jane
Roger likes Siri
The code above is my current attempt, which only prints "John likes Linda". I haven't found a solution to do this all at once. I could technically copy-paste the code twice and insert x[1] and x[2] in each block respectively. However, I've read that repetitious code is not good practice, so I was hoping some of you could help me in figuring out a more elegant solution.
Thank you very much for your help in advance
You can use build-in function zip
for man, woman in zip(*tuplelist):
print(man, 'likes', woman)
Although I think the answer by Relandom is the better and more pythonic appraoch, I would like to give you a second answer, pursuing the appraoch you tried (and might be easier to understand for beginners):
tuplelist = [('John', 'David', 'Roger'), ('Linda', 'Jane', 'Siri')]
counter = 0
for y in tuplelist[0]:
print(f'{y} likes {tuplelist[1][counter]}')
counter += 1
As you can see, we're still iterating over something. This time not the tuplelist, but the first tuple in this list (the male names). Sticking to your concept of a counter variable within the loop, we use this variable to access the second tuple (tuplelist[1]) in your list and get the respective value (=female name).
tools = {"Wooden_Sword1" : 10, "Bronze_Helmet1 : 20}
I have code written to add items, i'm adding an item like so:
tools[key_to_find] = int(b)
the key_to_find is the tool and the b is the durability and i need to find a way so if i'm adding and Wooden_Sword1 already exists it adds a Wooden_Sword2 instead. This has to work with other items as well
As user3483203 and ShadowRanger commented, it's probably a bad idea to use numbers in your key string as part of the data. Manipulating those numbers will be awkward, and there are better alternatives. For instance, rather than storing a single value for each numbered key, use simple keys and store a list. The index into the list will take the place of the number in the key.
Here's how you could implement it:
tools = {"Wooden_Sword" : [10], "Bronze_Helmet" : [20]}
Add a new wooden sword with durability 10:
tools.setdefault("Wooden_Sword", []).append(10)
Find how many bronze helmets we have:
helmets = tools.get("Bronze_Helmet", [])
print("we have {} helmets".format(len(helmets)))
Find the first bronze helmet with a non-zero durability, and reduce it by 1:
helmets = tools.get("Bronze_Helmet", [])
for i, durability in helmets:
if durability > 0:
helmets[i] -= 1
break
else: # this runs if the break statement was never reached and the loop ran to completion
take_extra_damage() # or whatever
You could simplify some of this code by using a collections.defaultdict instead of a regular dictionary, but if you learn how to use get and setdefault it's not too hard to get by with the regular dict.
To ensure a key name is not taken yet, and add a number if it is, create the new name and test. Then increment the number if it is already in your list. Just repeat until none is found.
In code:
def next_name(basename, lookup):
if basename not in lookup:
return basename
number = 1
while basename+str(number) in lookup:
number += 1
return basename+str(number)
While this code does what you ask, you may want to look at other methods. A possible drawback is that there is no association between, say, WoodenShoe1 and WoodenShoe55 – if 'all wooden shoes' need their price increased, you'd have to iterate over all possible names between 1 and 55, just in case these existed at some time.
From what I understand of the question, your keys have 2 parts: "Name" and "ID". The ID is just an integer that starts at 1, so you can initialize a counter for every name:
numOfWoodenSwords = 0
And to add to the array:
numOfWoodenSwords += 1
tools["wodden_sword" + str(numOfWoodenSwords)] = int(b)
If you need to have an unknown amount of tools, I recommend looking at the re module: https://docs.python.org/3/library/re.html.
Or you could iterate over tools.keys to see if the entry exists.
You could write a function that determines if a character is a letter:
def is_letter(char):
return 65 <= ord(char) <= 90 or 97 <= ord(char) <= 122
Then when you are looking at a key in your dictionary, simply:
if is_letter(key[-1]):
...
I am new to python and really programming in general and am learning python through a website called rosalind.info, which is a website that aims to teach through problem solving.
Here is the problem, wherein you're asked to calculate the percentage of guanine and thymine to the string of DNA given to for each ID, then return the ID of the sample with the greatest percentage.
I'm working on the sample problem on the page and am experiencing some difficulty. I know my code is probably really inefficient and cumbersome but I take it that's to be expected for those who are new to programming.
Anyway, here is my code.
gc = open("rosalind_gcsamp.txt","r")
biz = gc.readlines()
i = 0
gcc = 0
d = {}
for i in xrange(biz.__len__()):
if biz[i].startswith(">"):
biz[i] = biz[i].replace("\n","")
biz[i+1] = biz[i+1].replace("\n","") + biz[i+2].replace("\n","")
del biz[i+2]
What I'm trying to accomplish here is, given input such as this:
>Rosalind_6404
CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCC
TCCCACTAATAATTCTGAGG
Break what's given into a list based on the lines and concatenate the two lines of DNA like so:
['>Rosalind_6404', 'CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCCTCCCACTAATAATTCTGAGG', 'TCCCACTAATAATTCTGAGG\n']
And delete the entry two indices after the ID, which is >Rosalind. What I do with it later I still need to figure out.
However, I keep getting an index error and can't, for the life of me, figure out why. I'm sure it's a trivial reason, I just need some help.
I've even attempted the following to limited success:
for i in xrange(biz.__len__()):
if biz[i].startswith(">"):
biz[i] = biz[i].replace("\n","")
biz[i+1] = biz[i+1].replace("\n","") + biz[i+2].replace("\n","")
elif biz[i].startswith("A" or "C" or "G" or "T") and biz[i+1].startswith(">"):
del biz[i]
which still gives me an index error but at least gives me the biz value I want.
Thanks in advance.
It is very easy do with itertools.groupby using lines that start with > as the keys and as the delimiters:
from itertools import groupby
with open("rosalind_gcsamp.txt","r") as gc:
# group elements using lines that start with ">" as the delimiter
groups = groupby(gc, key=lambda x: not x.startswith(">"))
d = {}
for k,v in groups:
# if k is False we a non match to our not x.startswith(">")
# so use the value v as the key and call next on the grouper object
# to get the next value
if not k:
key, val = list(v)[0].rstrip(), "".join(map(str.rstrip,next(groups)[1],""))
d[key] = val
print(d)
{'>Rosalind_0808': 'CCACCCTCGTGGTATGGCTAGGCATTCAGGAACCGGAGAACGCTTCAGACCAGCCCGGACTGGGAACCTGCGGGCAGTAGGTGGAAT', '>Rosalind_5959': 'CCATCGGTAGCGCATCCTTAGTCCAATTAAGTCCCTATCCAGGCGCTCCGCCGAAGGTCTATATCCATTTGTCAGCAGACACGC', '>Rosalind_6404': 'CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCCTCCCACTAATAATTCTGAGG'}
If you need order use a collections.OrderedDict in place of d.
You are looping over the length of biz. So in your last iteration biz[i+1] and biz[i+2] don't exist. There is no item after the last.
Using Python 3.3
Hi, I'm pretty new to programming/Python, so please don't go into too in-depth/complex methods of solving this problem.
I have a dictionary in which the keys are the person's name, and each of the key's values is a list of the names of the person's friends. For example:
friends_of_person = {'Albus': ['Ron', 'Hermione'], 'Harry': ['Ron', 'Hermione', 'Neville']}
This dictionary can be longer.
What my question is, how do I write a for loop or code that will loop through the values and compare each of the values to each of the values of another key's values. To make this clearer, let's use the above example. Albus is a friend to Harry, Ron, and Hermione. Harry is a friend to Ron and Hermione.
But I want to compare 'Ron' to the 'Ron', 'Hermione', and 'Neville' from the key Harry.
And then what I want is to see if 'Ron' is a friend of Harry. IF and ONLY if Ron is a friend of Harry, then I want to make 'Harry' as a potential friend of 'Albus'. The case applies to when comparing 'Hermione' to the 'Ron' and 'Hermione' from Harry's values. - this is like mutual friends.
The following is the code I've written, but it didn't seem to yield the correct answer.
friends_of_person = {'Albus': ['Ron', 'Hermione'], 'Harry': ['Ron', 'Hermione', 'Neville']}
for person in friends_of_person:
friends_list = friends_of_person[person]
for friend in friends_list:
recommendation = ''
for another_person in friends_of_person:
if friend in friends_of_person[another_person]:
recommendation = another_person
It doesn't seem correct. But if anyone can give me hints/tips to put me on the right direction, it'll be greatly appreciated!
Thank you in advance :)
Use set to check the intersection of people's friend list:
In [352]: lst1=friends_of_person['Albus']
In [353]: lst2=friends_of_person['Harry']
In [354]: lst1
Out[354]: ['Ron', 'Hermione']
In [355]: lst2
Out[355]: ['Ron', 'Hermione', 'Neville']
In [356]: set(lst1)&set(lst2)
Out[356]: set(['Hermione', 'Ron'])
If you want approach using only simple iterations and basic features, here you go:
for friend in friends_of_person['Albus']:
recommendation = []
for person, friends in friends_of_person.items():
if person == 'Albus':
continue # we don't need anyone who already is his friend
for potential in friends:
if potential in friends_of_person['Albus'] and potential not in recommendation:
recommendation.append(potential)
print(potential)
...:
Neville
PS. It's ugly, but that's what OP wanted...
#zhangxaochen's answer using sets is in my opinion the neatest. Nonetheless, if you want to use lists you could do something like:
friends = {'Albus': ['Ron', 'Hermione'], 'Harry': ['Ron', 'Hermione', 'Neville']}
def mutual_friends(a, b):
return [x for x in friends[a] if x in friends[b]]
Note that's re-coding set intersection (EDIT: if you have been instructed not to use set intersection then this solution is good since you code it yourself :)).
So
def recommendations(x):
result = []
for f in friends.keys():
if f != x and mutual_friends(x, f) > 1:
result.append(f)
return result
Basically, for a given person x, find all the people that have more than one mutual friend with them. You could change it to == 2 if you want exactly 2 mutual friends.