Intermediate Python3 - New Teacher in Town

Looking for some help with task 4. I completed the first part.
I defined a Python class method to take a list of students and create a list of tuples of two students each of the ten total students, all possible combinations.
I am unable to convert that list of tuples into a list of tuples of tables of five combinations of the list of tuples of the two students.

I have not done this course (but I’ve been using Python for many years so) I will take a stab at this issue:

I think the issue is probably on this line: tables_five = itertools.combinations(two_students, 5) - if you run the code following that line more than once it will only print the contents in tables_five the first time (because on the second run the iterable would’ve exhausted.

Try this and see if it works:

import itertools
twos=list(itertools.combinations(list('abcd') , 2))

#twos:  [('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]


tables_five = itertools.combinations(twos , 5)
for table in tables_five:
     print(list(table))
 
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd')]
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('c', 'd')]
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'd'), ('c', 'd')]
[('a', 'b'), ('a', 'c'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
[('a', 'b'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
[('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd’)]

# print the second time and it wouldn’t print anything
for table in tables_five:
     print(list(table))

# fix tables_five = itertools.combinations(twos , 5) by wrapping it in a list - like so:
tables_five = list(itertools.combinations(twos , 5))

Just to keep things straight… Iterables are not consumed (exhausted); iterators are consumed. There is a distinction.

Hi Roy (mtf)
Could you help me with this problem? I seem to be missing the logic here. I had already attempted to do what system8489050653 suggested as I don’t fully understand what I am doing wrong or not grasping. I rarely post on the forum and try to solve issues myself, because that tells me I gained knowledge. This topic is completely new to me and I’m stumped. I am trying to learn this topic. My goal is LEARNING and understanding.
I provided a link to my gist for this New Teacher in Town project, for this Intermediate Python3 course.

As I understand it I’m supposed to take this list of tuples below and convert it into 5 tables of the possible combinations of 2 student tuples. So the end result would be a list of tuples of five tables, containing tuples of two students combinations, right?
It is similar to task 5. The difference is task 5 uses a class for loop method to iterate through the student roster (dictionary) and return a list of tuples of the students whose favorite subject is either Math of Science. Then in script.py when the method is called a combinatoric iterator is implemented to take that list of tuples and convert it into a list of tuples of tables, representing all the tables of 4 (seating arrangement) of those tuples of math/science students, possible combinations.
But in task 4, the distinction between this and task 5, (classroom_organizer.py) the class method begins with a combinatoric iterator method. When this method is called in script.py when I create a new instance object (new_student) of the class, the result is a list containing the possible two student (tuple) combinations of all 10 students, (similar to task 5). And this is where I’m stuck. How to take this list of tuples of 2 students and return all the possible 5 tables of 2 students tuples of tuples.,

task 4 - (classroom_organizer.py) class method:
def two_students_combos(self):
two_combos =
twos = itertools.combinations(self.sorted_names, 2)
for two in twos:
two_combos.append(two)
return two_combos

task 4 - (script.py) calling the class method and OUTPUT:
print(“task 4 - Two students combos possible”)
two_students = new_student.two_students_combos()
print(two_students)

task 4 - Two students combos possible (script.py) OUTPUT: A list if tuples
[(‘Alex C’, ‘Benny D’), (‘Alex C’, ‘Esmeralda R’), (‘Alex C’, ‘Helena L’), (‘Alex C’, ‘Karina M’), (‘Alex C’, ‘Marisol R’), (‘Alex C’, ‘Matthew Q’), (‘Alex C’, ‘Sandy P’), (‘Alex C’, ‘Trudy B’), (‘Alex C’, ‘Yori K’), (‘Benny D’, ‘Esmeralda R’), (‘Benny D’, ‘Helena L’), (‘Benny D’, ‘Karina M’), (‘Benny D’, ‘Marisol R’), (‘Benny D’, ‘Matthew Q’), (‘Benny D’, ‘Sandy P’), (‘Benny D’, ‘Trudy B’), (‘Benny D’, ‘Yori K’), (‘Esmeralda R’, ‘Helena L’), (‘Esmeralda R’, ‘Karina M’), (‘Esmeralda R’, ‘Marisol R’), (‘Esmeralda R’, ‘Matthew Q’), (‘Esmeralda R’, ‘Sandy P’), (‘Esmeralda R’, ‘Trudy B’), (‘Esmeralda R’, ‘Yori K’), (‘Helena L’, ‘Karina M’), (‘Helena L’, ‘Marisol R’), (‘Helena L’, ‘Matthew Q’), (‘Helena L’, ‘Sandy P’), (‘Helena L’, ‘Trudy B’), (‘Helena L’, ‘Yori K’), (‘Karina M’, ‘Marisol R’), (‘Karina M’, ‘Matthew Q’), (‘Karina M’, ‘Sandy P’), (‘Karina M’, ‘Trudy B’), (‘Karina M’, ‘Yori K’), (‘Marisol R’, ‘Matthew Q’), (‘Marisol R’, ‘Sandy P’), (‘Marisol R’, ‘Trudy B’), (‘Marisol R’, ‘Yori K’), (‘Matthew Q’, ‘Sandy P’), (‘Matthew Q’, ‘Trudy B’), (‘Matthew Q’, ‘Yori K’), (‘Sandy P’, ‘Trudy B’), (‘Sandy P’, ‘Yori K’), (‘Trudy B’, ‘Yori K’)]

task 5
classroom_organizer.py) class method
def get_students_with_subject(self, subject):
selected_students =
for student in student_roster:
if student[‘favorite_subject’] == subject:
selected_students.append((student[‘name’], subject))
return selected_students

task 5 - (script.py) calling the class method and OUTPUT:
print(“task 5: favorite subject is Math or Science”)

math_science_list = list(itertools.chain(new_student.get_students_with_subject(“Math”), new_student.get_students_with_subject(“Science”)))
print(math_science_list)
print()
print(“task 5: combos of tables of four.”)
math_science_fours = list(itertools.combinations(math_science_list, 4))
print(math_science_fours)

task 5: favorite subject is Math or Science
[(‘Karina M’, ‘Math’), (‘Benny D’, ‘Math’), (‘Marisol R’, ‘Math’), (‘Alex C’, ‘Science’), (‘Trudy B’, ‘Science’)]

task 5: combos of tables of four.
[((‘Karina M’, ‘Math’), (‘Benny D’, ‘Math’), (‘Marisol R’, ‘Math’), (‘Alex C’, ‘Science’)), ((‘Karina M’, ‘Math’), (‘Benny D’, ‘Math’), (‘Marisol R’, ‘Math’), (‘Trudy B’, ‘Science’)), ((‘Karina M’, ‘Math’), (‘Benny D’, ‘Math’), (‘Alex C’, ‘Science’), (‘Trudy B’, ‘Science’)), ((‘Karina M’, ‘Math’), (‘Marisol R’, ‘Math’), (‘Alex C’, ‘Science’), (‘Trudy B’, ‘Science’)), ((‘Benny D’, ‘Math’), (‘Marisol R’, ‘Math’), (‘Alex C’, ‘Science’), (‘Trudy B’, ‘Science’))]

Task 5 seems straightforward to me (if I’m understanding it correctly) and produces the expected output using a for loop, the itertools chaining() and then combinations() methods.

Task 4 I’m missing the logic. I attempted to provide a parameter to the class method of 5 so when it was called later it would accomplish tuples of 2 student combinations in the tables of 5 tuples but i was not successful. I feel the solution is staring at me and I’m not seeing it.
I apologize for the length of this post. Can you provide some clarification please?

Please post a link to the landing page for this project.

Until I read the instructions it’s only guessing but this is what I’ve cooked up as a method to randomly select five pairs from 10 individuals…

from itertools import combinations as nCr
from random import choice
s = [*'abcdefghij']
pairs = []
while len(s) > 0:
  a, b = choice([*nCr(s, 2)])
  pairs.append((a, b))
  s.remove(a)
  s.remove(b)
print (pairs)
[('e', 'h'), ('b', 'c'), ('d', 'g'), ('f', 'j'), ('a', 'i')]

https://www.codecademy.com/courses/learn-intermediate-python-3/projects/new-teacher-in-town-project

I assume by ‘landing page’ you are referring to the URL for the course.

1 Like

I’ve got some catching up to do (haven’t reached this point in the course, yet) but I’ll try to stumble my way through this project, docs in hand.

Here’s how I approached the first task…

from roster import student_roster
import itertools
s = iter(student_roster)
while True:
  try:
    print (next(s))
  except StopIteration:
    break

It prints out each of the ten dictionaries. On to task 2. Well, that one was easy. Let’s try task 3, Roll Call!

For this I added a method to the ClassroomOrganizer class definition:

  def roll_call(self):
    r = iter(self.sorted_names)
    while True:
      try:
        print (next(r))
      except StopIteration:
        break
Alex C
Benny D
Esmeralda R
Helena L
Karina M
Marisol R
Matthew Q
Sandy P
Trudy B
Yori K

Task 4 is rather moot. There are 45 possible pairings, from which we only need five. The method above computes the pairings, then randomly chooses one of them. The two names chosen (the pair) are both removed from the list and a new iterator generated on the remaining names. We do this until the list is empty.

  def pairing(self):
    s = self.sorted_names[:]
    pairs = []
    while len(s) > 0:
      a, b = choice([*itertools.combinations(s, 2)])
      pairs.append((a, b))
      s.remove(a)
      s.remove(b)
    self.pairs = pairs

Over in script.py I have an instance I called s.

s.pairing()
print (s.pairs)
[('Benny D', 'Helena L'), ('Marisol R', 'Matthew Q'), ('Alex C', 'Sandy P'), ('Trudy B', 'Yori K'), ('Esmeralda R', 'Karina M')]

On to task 5…

Yes, this is a very new course.
As I started at the beginning, codecademy provided a lesson so I used a ‘raise StopIteration’ for task 1. Thank you for taking the time. I look forward to
seeing what methods you employ for task 2-5.
I have completed the lesson (tasks 1-5), and did the extra credit (task 6) as it helps me to reinforce my learning and perhaps point out my weak areas.
But I am still stuck on task 4. And I sense I am overlooking or missing something.

1 Like

See above how I handled it (task 4), using my own intuition, as it were.

Not sure what the point of task 5 is. There are only five individuals. Why not just sit the maths at one table and the science at the other rather than one sitting alone?

I’ll revisit this project when I get through the earlier units of the Intermediate course, perhaps with more insight to replace my intuition.

Am I misunderstanding task 4?
Part 1 -I thought the task was to implement a class method to return the ten students in all possible combinations of two. The result is a list of tuples of students names as strings.
Part 2 - Take the list of tuples of students. Then return all possible combinations of the students tuples arranged at five tables (seating arrangements of two students at five tables?

This is what I did for task 5
Part 1 - Created a list of tuples of the students whose favorite subject was either Math or Science. The tuples consisted of student name and either “Math” or “Science”.
Part 2 - Combine the name/subject tuples list into all possible combinations of seating at 4 tables.
My result/output was a list of tuples (4 tables) of tuples of students/subject (nested tuples)

Which is fine, if we really want to see all the possible combinations. I found this rather moot, although for demonstration purposes, it has a place. Didn’t see the need to write a full blown method to do this, and refactored my method to generate five random pairings, which seems practical enough.

Thanks for your help.
More often than not, these lessons/courses include a walk-through video if a student is stuck or confused, or to compare ‘your’ code to ‘their’ code. I find it very helpful as a number of the instructors include helpful hints, etc as they explain each task solution. This one just points a student to the forum.

1 Like

Still playing around in this project. Nothing spectacular to report, but just for demonstration…

def get_column(key, label, iterable):
  return label, [*map(lambda x: x[key], iterable)]

columns = {'name': 'Name', 'age': 'Age', 'height': 'Height', 'favorite_subject': 'Favorite Subject', 'favorite_animal': 'Favorite Animal'}
for key, label in columns.items():
  print (get_column(key, label, student_roster))

True to the nature of iterators, map() exhausts itself when the unpack tool is put to work. The return is a label and list in a tuple.


Later…

We would be remiss if the code didn’t get another look. Chop, chop, chop. That’s always on the menu. The payback for our time is the cleaner code.

def key_to_label(key):
  return ' '.join(map(lambda x: x.capitalize(), key.split('_')))

def get_column(key, iterable):
  return key_to_label(key), [*map(lambda x: x[key], iterable)]

keys = 'name', 'age', 'height', 'favorite_subject', 'favorite_animal'
for key in keys:
  print (get_column(key, student_roster))

Still later…

def keys(iterable):
  return iterable[0].keys()
def key_to_label(key):
  return ' '.join(map(lambda x: x.capitalize(), key.split('_')))
def get_column(key, iterable):
  return key_to_label(key), [*map(lambda x: x[key], iterable)]
def col_dump(iterable):
  for key in keys(iterable):
    print (get_column(key, iterable))
col_dump(student_roster)

We’re working within the confines of the ‘student_roster’, so this is very much ‘scenario based software’.

thanks, I’ll play around with this. I need more practice with lambdas.

I looked at task 4 again and now realize although they allude to tables of four, the output is supposed to be
all combinations of two students.

Still only a minor variation on the previous with nothing really added to the experience pool. We should have some idea of how combinatorics work, by now, at least in this limited sense.

>>> from itertools import combinations as nCr
>>> [*nCr('abcde', 2)]
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('a', 'e'), ('b', 'c'), ('b', 'd'), ('b', 'e'), ('c', 'd'), ('c', 'e'), ('d', 'e')]
>>> 

The topic comes up in senior maths, where we learn the formula for computing the binomial coefficient which just happens to be the number of combinations, N choose R.

         n!
nCr = --------
      r!(n-r)!

         5!
nCr = --------
       2!(3!)

       5*4*3!
nCr = --------  # 3!/3! = 1
       2 * 3!

== 20 / 2 => 10

It stems from the Binomial theorem for which we credit Isaac Newton.

It’s obvious that the itertools combinations method produces every combination. This does not come about with maths, but with algorithms. Back in the day, when I was smarter and more energetic and determined, I sussed out Pascal’s Triangle on a TS-1000 by some miracle or another. It was not the math that I knew, which I had none of, but the process that I envisioned that led to the algorithm. Don’t ask me to reproduce that now. Remember, it was back in the day. All I saw was the pattern, and set out to reproduce it.

Maths is like that. Not at first, obviously, but eventually we see things in three or more dimensions (me not so much past the third dimension). When I was embarking on this stuff with my trusty Timex Sinclair I was a high school drop out with a 55 in first HS year math. It was not a good year considering I was runner up valedictorian the previous grade. My life took a turn.

That little machine opened up possibilities simply because we could tell it what to do and it made a promise to deliver on all its command responses. There was every level of access given to the user. Write assembler and execute it from within a higher level program with USR calls. Back then it was common among hobbyists because it was the only way to achieve any speed.

If you were not motivated to write an assembler version of a lengthy math process, there was still the MATH statement that would shut everything down in terms of I/O so the system could be dedicated to running the program. Don’t even ask for examples; that was forty years ago. But the above is one.

Computing factorials is a recursive function since we need the computation of the first two to carry on with the next one, and then the next one, &c. It’s not a good example, but one all the same. Of course we can use an iterative approach as well, which in the case of factorials works very efficiently, at the human readable level. Recursion is what works at the machine level. Once you get into assembler it will become evident why. But, that’s not our lesson plan for today. Just something to bookmark. To really get to the bottom of iterators, we need to get to the very bottom. Python modules such as itertools give us that ability. It’s not a jump I’ve made with steam, but I can see what’s up. Refresh you maths as you go through this course so it syncs up with the concepts. Don’t try to learn maths through programming. Use your math prowess to dictate code.

I think it is helpful to have a good foundation in math when learning programming. And it is apparent that math occupies a strong presence ‘under the hood’. My approach
to learning from the codecademy courses is to fully embrace the course instruction and rely heavily on the code base skillset. I try to understand the relationship of new subjects to what courses I have completed. My overall thrust is more leaning to programming applications and what code I can implement, code for the sake of coding. Since programming is a far newer discipline than math, I am enjoying its many facets on their own merit, while still cognizant of the significance of math.

When we were learning maths we used to quip, “there must be a computer that can do this.” Only a handful ever sat down at a computer and tried to do it. The key is that we saw it on the blackboard, first, and had textbook and worksheet assignments to work on with pencil and paper.

I am not a mathematician, but in the day it was one of my loves. Give me a chalk or white board it was sheer joy. So many years later, I’m struggling to retrieve that. Clearly, the love is still there, but the acuteness maybe less so. Physics has always been a love. It is probably why maths are so leveled upon, here. It is the language of physics, and a lot of science, in general.

With such evidence of the reasons to possess the language, it falls upon us which order to learn the respective languages. That’s all I’m really saying in this lengthy diatribe.