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 :class:`dict` where: - the key is the *Student Id* (:class:`int`) - the value is a :class:`list` with the name (:class:`str`) and the grade (:class:`float`) of that student for that exam. For example: .. literalinclude:: search_first_allpassrow.test :language: python :start-after: --ini-D :end-before: --fi-D - 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 :class:`list` of **rows**. Each row in turn is a :class:`list` of :class:`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: .. literalinclude:: search_first_allpassrow.test :language: python :start-after: --ini-cl51 :end-before: --fi-cl51 Please implement the following Python functions in the :mod:`classroom` module (:file:`classroom.py` file): The first function is .. py:function:: search_first_allpassrow(gradesD, classroomL) such that **given** - ``gradesD``, a :class:`dict` of students grades as described above. - ``classroomL``, a :class:`list` representing a students classroom as described above. All *Student Id* in this list are keys in ``gradesD``. **returns** a :class:`tuple` with the row index (:class:`int`) and the row (:class:`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: .. literalinclude:: search_first_allpassrow.test :language: python :start-after: --ini-cl51-out :end-before: --fi-cl51-out whereas it the case of the following, slightly different, classroom .. literalinclude:: search_first_allpassrow.test :language: python :start-after: --ini-cl52 :end-before: --fi-cl52 where in all rows there is at least one student that did not pass, the function should do the following: .. literalinclude:: search_first_allpassrow.test :language: python :start-after: --ini-cl52-out :end-before: --fi-cl52-out .. 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 :download:`search_first_allpassrow.test ` file. .. note:: To implement this function is recommended (but not mandatory) to previosly implement and test the following auxiliar function: .. py:function:: check_allpassrow(gradesD, row) such that **given** - ``gradesD``, a :class:`dict` of students grades as described above. - ``row`` a :class:`list` of :class:`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 .. py:function:: search_first_allpassrow_plus(gradesD, classroomL) such that **given** - ``gradesD``, a :class:`dict` of students grades as described above. - ``classroomL``, a :class:`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 :class:`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: .. literalinclude:: search_first_allpassrow_plus.test :language: python :start-after: --ini-cl51-out :end-before: --fi-cl51-out .. literalinclude:: search_first_allpassrow_plus.test :language: python :start-after: --ini-cl52-out :end-before: --fi-cl52-out Doctests are available at the :download:`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: .. py:function:: get_allpassrow_grades(gradesD, row) such that **given** - ``gradesD``, a :class:`dict` of students grades as described above. - ``row`` a :class:`list` of :class:`int` representing a row as described above. **returns** a :class:`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.