Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Python Collections (2016, retired 2019) Sets Set Math

Dominik Holter
Dominik Holter
1,388 Points

Sets.py code challenge task 1 failing.

The callenge asks to: So, first, write a function named covers that accepts a single parameter, a set of topics. Have the function return a list of courses from COURSES where the supplied set and the course's value (also a set) overlap. For example, covers({"Python"}) would return ["Python Basics"].

My code is below. It works in Workspaces (to my understanding of the task), but not in the code challenge interface.

Here is the link to the code challenge: https://teamtreehouse.com/library/python-collections-2/sets/set-math

Any ideas what I a doing wrong?

sets.py
COURSES = {
    "Python Basics": {"Python", "functions", "variables",
                      "booleans", "integers", "floats",
                      "arrays", "strings", "exceptions",
                      "conditions", "input", "loops"},
    "Java Basics": {"Java", "strings", "variables",
                    "input", "exceptions", "integers",
                    "booleans", "loops"},
    "PHP Basics": {"PHP", "variables", "conditions",
                   "integers", "floats", "strings",
                   "booleans", "HTML"},
    "Ruby Basics": {"Ruby", "strings", "floats",
                    "integers", "conditions",
                    "functions", "input"}
}

def covers(set1):
    final_list = []
    for course in COURSES:
        if set1 <= COURSES[course]:
            final_list.append(course)
    return final_list

11 Answers

The task is to find the course or courses(which are keys in the COURSES dict). Notice also, that the value for each course is a set with several elements(topics) in it. Change your for loop to loop through each key, value in the COURSES items. By doing this we have access to the keys and values in our COURSES dict. Inside the loop check if the parameter(the set of topics) supplied overlaps with the courses values i.e if they have any element in common (intersection). If so, append the key to your final_list and return this list.

Hi Dominik, was this helpful? If so, please feel free to mark as best answer.

Matt Breeland
Matt Breeland
1,458 Points

I was only able to make this work by casting the values list inside the COURSES dictionary to a set, and then using intersection. This makes this task quite confusing for beginners.

def covers(p):
    ret = []
    for k, v in COURSES.items():
        setv = set(v)
        if p.intersection(setv):
            ret.append(k)
    return ret
Aaron Jeffries
Aaron Jeffries
11,057 Points

'This makes this task quite confusing for beginners.'

Agreed. The Pythons class has been pretty bad about that in my humble opinion.

Daniele Santos
Daniele Santos
16,536 Points

Oh, Gosh! I would never have guessed that I would have to cast the values list. Really confusing! Thanks for sharing that with us! <3

Mubarig CISMAN
seal-mask
.a{fill-rule:evenodd;}techdegree
Mubarig CISMAN
Python Web Development Techdegree Student 2,547 Points

I think it should be done in the way sets work in Python. My Code is as follows and it run smoothly

  def covers(topics):
    courses_list = []    
    for course in COURSES:
        if COURSES[course] & topics:   # Here the & sign finds the overlaps of the two sets.
            courses_list.append(course)
    return courses_list
slavster
slavster
1,551 Points

This is definitely the best solution. The task is asking only for a list of complete course titles to be returned (that is the keys, and NOT any of the values from the dictionary). This code seems pretty efficient as it looks for any overlap between the supplied set and course titles, and in the event any overlap exists, it adds the course title to the list.

Daniel Escobar
Daniel Escobar
2,580 Points

This is definetly the Best Answer ! Thanks for the help.

Mischa Yartsev
Mischa Yartsev
20,562 Points

Hey Michael Lutz

I've managed to pass first challange with your code.

The only problem you had in there is redundant check for equality in if condition. Probably, it was also generated strange behaviors.

So I replace:

if value&set2 == set2:

to

if value & set2:

And it should do the trick!

Hey Mischa

Thanks for the help! I was starting to pull my hair out! Funny thing is my solution actually worked for the second part of the challenge, so looks like I over-engineered it? In any case, glad to have closed this item.

Cheers Mike

Lucas Diz
Lucas Diz
4,804 Points

Hi Everyone, I did something similar but in order to use what we just learn I used "intersection". I worked very well.

def covers(arg):
    final = set()
    for key , value in COURSES.items():
        if value.intersection(arg):
            final.update({key})
    return list(final)
Dominik Holter
Dominik Holter
1,388 Points

Thank you, Andrew! That did the trick - much appreciated!

Hi

I have a different solution that works in my terminal window but I'm also getting the "Bummer!" error message in the challenge interface. Any idea what went wrong with my code?

COURSES = {
    "Python Basics": {"Python", "functions", "variables",
                      "booleans", "integers", "floats",
                      "arrays", "strings", "exceptions",
                      "conditions", "input", "loops"},
    "Java Basics": {"Java", "strings", "variables",
                    "input", "exceptions", "integers",
                    "booleans", "loops"},
    "PHP Basics": {"PHP", "variables", "conditions",
                   "integers", "floats", "strings",
                   "booleans", "HTML"},
    "Ruby Basics": {"Ruby", "strings", "floats",
                    "integers", "conditions",
                    "functions", "input"}
}

def covers(*args):
    set2 = set()
    for arg in args:
        set2.update({arg})
    set1 = set()
    for key, value in COURSES.iteritems():
        if len(set(value)&set2) == len(set2):
            set1.update({key})
    print set1

covers('Ruby','input') 

It looks like you are returning a set rather than a list.

Hi Ryan

Oops, thanks for pointing that out! That for sure was one reason for not passing. I did try to return a list but it still didn't work however. Any idea what other issues could be?

def covers(*args):
    set2 = set()
    set1 = set()
    for arg in args:
        set2.update({arg})
    for key, value in COURSES.iteritems():
        if len(set(value)&set2) == len(set2):
            set1.update({key})
    return list(set1)
Dominik Holter
Dominik Holter
1,388 Points

Hi Michael,

for one I notice that you go through a - to my mind - complicated mechanism of having *args as your prameter and then creating a set with each arg from *args. Since you get a set anyhow passed into covers() by the code challenge, that is redundant. You could simply use:

def covers(set2):
    set1 = set()
    # no need to intialize set2
    # the rest of your code

But maybe you were trying it out. I suppose the task should pass anyway.

As for what is actually not working, I am trying to wrap my head around what you are doing with len(). Since you are supposed to check whether set2 is part of set1, I don't understand what you are doing there.

Hi Dominik

That was very helpful indeed. For some reason I thought I was passing in multiple variables and not a list. Re the len(), I was comparing the length of the intersection of the value with that of the search input, but I realized that I can just simple compare the actual results instead of the lengths (silly me).

The function looks a lot tidier now. But, unfortunately it still doesn't pass, even though it runs fine in my terminal.

def covers(set2):
    set1 = set()
    for key, value in COURSES.items():
        if value&set2 == set2:
            set1.update({key})
    return list(set1)
Dominik Holter
Dominik Holter
1,388 Points

Hi Michael,

glad that was helpful!

Please post your entire current code here. I ran it in workspaces and I get a TypeError: unsupported operand type(s) for &: 'set' and 'tuple'. It refers to the following line of code:

if value&set2 == set2:

Below is the full code. I've tried it in workspaces and it ran smoothly with the right output (when checking with "print").

COURSES = {
    "Python Basics": {"Python", "functions", "variables",
                      "booleans", "integers", "floats",
                      "arrays", "strings", "exceptions",
                      "conditions", "input", "loops"},
    "Java Basics": {"Java", "strings", "variables",
                    "input", "exceptions", "integers",
                    "booleans", "loops"},
    "PHP Basics": {"PHP", "variables", "conditions",
                   "integers", "floats", "strings",
                   "booleans", "HTML"},
    "Ruby Basics": {"Ruby", "strings", "floats",
                    "integers", "conditions",
                    "functions", "input"}
}

def covers(set2):
    set1 = set()
    for key, value in COURSES.items():
        if value&set2 == set2:
            set1.update({key})
    return list(set1)

In case it helps anyone else, my code originally passed in Workspaces but not on the challenge page because I forgot to change the practice input into a set.

I was inadvertently having the covers function accept a string instead, so I kept getting the same TypeError.

I fixed it this way:

user_topic = input("> ") 
user_set = set(user_topic.split()) 

And then I plugged user_set into the covers function to test it.

print("{}".format(covers(user_set)))

I'm sure there's a more Pythonic way to do this, but it got me through Part 1 of the challenge. (Over an hour later, and only with help from this thread.)

This is the code that ended up working for me:

def covers(topic):
    courses_list = []
    for name, topics in COURSES.items():
        if topic & topics:
            courses_list.append(name)
    return courses_list

Just hoping this helps someone the way you've all helped me. :)