Students Classroom

Let’s consider the hypothetical scenario of a group of students who have taken a programming exam. The professor responsible of that exam is interested in knowing the pairs of students who got similar grades and were seating next to each other. The information available is the following:

  • A grades dictionary: A dict where:

    • the key is the Student Id (int)

    • the value is a list with the name (str) and the grade (float) of that student for that exam.

    For example:

    
    >>> gradesD = {
    ... 107: ['JBB', 0.0],
    ... 155: ['GWV', 5.5],
    ... 227: ['JJJ', 6.5],
    ... 275: ['AWV', 3.5],
    ... 321: ['MMP', 5.5],
    ... 325: ['BWV', 4.5],
    ... 423: ['SCC', 7.5],
    ... 490: ['BWV', 9.0],
    ... 555: ['FCC', 5.0],
    ... 727: ['ABC', 7.0],
    ... 811: ['GMM', 8.0],
    ... 923: ['MRP', 10.0],
    ... 999: ['ARG', 10.0],
    ... }
    
    
  • A classroom list: This is a 2-dimension list representing the locations where the students were seating during the exam. More precisely it is a list of rows. Each row in turn is a list of int which is either a Student Id or -1 is nobody is seating in that location. Rows are counted top-down starting at 1 and locations are counted from left to right starting at 1. For example:

    
    >>> cl51 = [
    ... [227, -1, 423, 811,  -1, 107,  -1],
    ... [155, -1, 275,  -1,  -1, 325, 490],
    ... [ -1, -1,  -1,  -1, -1,  -1, -1],
    ... [923, -1, 727,  -1, 321, 555, 999],
    ... ]
    
    

Please implement the following Python functions in the classroom module (classroom.py file):

The first function is

search_first_allpassrow(gradesD, classroomL)

such that

given

  • gradesD, a dict of students grades as described above.

  • classroomL, a list representing a students classroom as described above. All Student Id in this list are keys in gradesD.

returns a tuple with the row index (int) and the row (list) of the first row whose students all pass.

Whether there is no row in the classroom in which all the students pass then it returns (-1, []).

For example, in case of the classroom above, the function should do the following:


>>> sol = search_first_allpassrow(gradesD, cl51)
>>> sol
(4, [923, -1, 727, -1, 321, 555, 999])

whereas it the case of the following, slightly different, classroom


>>> cl52 = [
... [227, -1, 423, 811, -1, 107, -1],
... [ -1, -1,  -1,  -1, -1,  -1, -1],
... [155, -1, 727,  -1,  -1, 325, 490],
... [923, -1, 275,  -1, 321, 555, 999],
... ]

where in all rows there is at least one student that did not pass, the function should do the following:


>>> sol = search_first_allpassrow(gradesD, cl52)
>>> sol
(-1, [])

Note

Bear in mind that if a row is empty (no students are seating there (in other words al Students Ids are -1) that is not an all pass row.

Doctests are available at the search_first_allpassrow.test file.

Note

To implement this function is recommended (but not mandatory) to previosly implement and test the following auxiliar function:

check_allpassrow(gradesD, row)

such that

given

  • gradesD, a dict of students grades as described above.

  • row a list of int representing a row as described above.

returns True if all students in that row have a grade greater or equal than 5.0 or False otherwise.

Implementing first this auxiliar function is useful to implement the main function but also to reuse the main function code to implement the next function.


The second function is

search_first_allpassrow_plus(gradesD, classroomL)

such that

given

  • gradesD, a dict of students grades as described above.

  • classroomL, a list representing a students classroom as described above. All Student Id in this list are keys in gradesD.

returns the first row where all the students pass. Specificly a tuple with two components:

  • the row index (remember that the row numbertig starts at 1).

  • the list of grades of the students in that row.

Whether there is no row in the classroom in which all the students pass then it returns (-1, []).

For instance, in case of the two classrooms above the function should behave as follows:


>>> sol = search_first_allpassrow_plus(gradesD, cl51)
>>> sol
(4, [10.0, 7.0, 5.5, 5.0, 10.0])


>>> sol = search_first_allpassrow_plus(gradesD, cl52)
>>> sol 
(-1, [])

Doctests are available at the search_first_allpassrow_plus.test file.

Note

To implement this function is recommended (but not mandatory) to reuse the main code for the previous function and replace the auxiliar function check_allpassrow by the following auxiliar function to be implemented and tested:

get_allpassrow_grades(gradesD, row)

such that

given

  • gradesD, a dict of students grades as described above.

  • row a list of int representing a row as described above.

returns a list` with either the grades of all students in row if all of them pass, or [] otherwise.

Warning

Both functions have the same grade weight.