Teaching Portfolio
1 Statement of Teaching Philosophy
My teaching philosophy can be summarized as follows.
I create positive learning experiences and lasting impacts on students by bringing out the joy in learning.
I would argue that there are ways in which learning can be profoundly and universally joyful, appealing to our basic desires as human beings. Furthermore, as educators, we can strive to bring out this joy in our students, leading to effective learning and positive long-term outcomes.
In the following, I will focus on three powerful ways learning can be joyful, and how I have tried to incorporate these in my teaching. I’ll then conclude with why I teach. Below are the three joys related to learning that I want to focus on. Rather than explain why each of these feelings is so powerful, I invite you to remember when you experienced each joy. I’m sure you can relate to each of them in some way.
- The joy of empowerment. Think of a time when you learned something that allowed you to create something, solve a problem, or express yourself in a way you couldn’t before.
- The joy of exploration and discovery. Think of a time when you explored something new and discovered something interesting or surprising.
- The joy of curiosity. Think of a time when you were obsessed with some question or puzzle, and finally found the answer.
A hands-on approach to theory. Programming has several advantages when it comes to teaching and learning. Firstly, exploration is extremely straightforward. You can ask “what if …”, and check in seconds by running some code. Secondly, programming is extremely easy to make relevant and high-value – students know that programming is a useful skill and there are many real-world examples to draw upon when creating assignments/exercises. Thus, the joys of empowerment and exploration are relatively straightforward to emphasize when teaching students how to program. I try to bring this sprit to teaching theory by making the concepts in theory tangible and concrete.
For the algorithms class for 3rd year students, CSC373, I created coding notebooks using Google Colab where students can implement, test, and compare the algorithms from class. The notebooks provide an environment where exploration is easy – since all the data and setup are provided, students can focus on implementing the algorithm and trying variations. Aside from being able to explore, implementing the algorithms makes it ‘real’ for the students. They see the algorithms working on real data and can ‘feel’ the difference in efficiency. Understanding \(O(n\log(n))\) vs \(O(n^2)\) is one thing, but seeing one algorithm crash your computer while the other runs in seconds is a completely different experience.
Another example of my hands-on approach is demonstrating how the topics students are learning about can solve real-world problems relevant to their lives. For example, when teaching a unit on modelling problems with graphs, I show students how I solved a very real problem related to the course – assigning homework partners. In the lecture, I show them the data I’m working with – I have more than 100 students, and each pair of students has some compatibility score determined by the times they’re available to work on the problem sets. I tell them that I would like to assign homework partners to maximize the overall compatibility. I have them work through some small examples to get some intuition for the problems (and to convince them that it is indeed a challenging problem). Then, using concepts just learned in class, I model the problem as a max-weight matching problem and show students how to solve the problem in seconds with a single library call. Students are impressed by the simplicity of the solution, and hence the idea sticks: “If I can model a problem as a graph problem, then I can solve it”.
Priming Curiosity. I also like to preview more advanced aspects of my course early on to spark students’ curiosity. For example, in my introduction to theory course, I pose the following question to students in the first week (which will appear on a problem set by the end of week 4).
“Suppose I have a Rubik’s cube in its solved state. Is it true that for any sequence of turns, if I repeat that sequence enough times, the cube will eventually return to the solved state?”
The question is straightforward enough to state and concrete enough to explore. After trying some sequences, students might form a hypothesis, but it’s not clear to them how to prove it. Indeed, they don’t have the techniques yet—it is currently out of reach. For some students, this puzzle is very motivating—they think about how the topics in class will help them answer the Rubik’s cube question, and that’s exactly what I want! By the end of week 4, students can finally answer the question by putting together topics from the first few weeks.
Asking the right questions at the right times is a powerful way to motivate students. Having them use the topics learned in the course to satisfy their curiosity is an empowering feeling.
Why this is so important. Bringing out the joy in learning can be a powerful motivator for students. When students see learning in a course as fun, interesting, and relevant, they continue to show up and stay engaged. More importantly, bringing out the joy creates a lasting impact on students. If I can impart the joy of learning computer science to my students, then they will be more likely to continue to pursue learning computer science and continue to experience that joy. This is what matters to me – I want to inspire students to continue learning long after the course ends.
Why I teach. By now, it should be clear that I find learning a joyous experience. I love the feeling of learning something new and being able to apply it in my life, the feeling of grappling with a complex puzzle (and eventually solving it), and the feeling of exploring – getting my hands dirty to discover or understand something new. There’s another deeply innate source of joy that I’ve discovered in my life, and that’s the joy of sharing. There’s nothing better than sharing something you’re passionate about with others – especially when they find it interesting or it empowers them. I have found this through teaching, and it’s why I want to pursue a career in education.
2 Reflections on Teaching Experiences
In this section, I reflect on my past experiences as a course instructor at U of T.
2.1 CSC236 – Introduction to the Theory of Computation – Summer 2022
Context.
- Summer course
- Sole instructor
- \(\approx 100\) students
- First time as a course instructor
I modelled the course on previous iterations with several modifications. When reviewing previous iterations of the course, I noticed that the first five weeks were spent studying proofs by induction, which I felt was too much time, especially given the fact that students have already seen proofs by induction in a previous course. Furthermore, since induction was the first topic covered in the course, most of the problems that can be asked of the students in these first few weeks are rather dry and uninteresting (for example, proving divisibility properties). To address my concern, I started the course by teaching functions, binary relations, and graphs. Aside from being foundational topics in their own right, teaching these topics first made more interesting induction problems available to students, such as the Rubik’s Cube Problem (See Section 3.3) (using induction on injective functions), and topological sort / extending partial ordering.
Below is some positive feedback I received in my course evaluations related to my efforts to make the course content more interesting and applicable.
“Professor Sha did an excellent job at making CSC236 a really engaging, interesting, and overall enjoyable experience. All of the course materials used and developed by Professor Sha for this course showed a high level of detail, care, and thought, including lecture slides and homework assignments. Lecture content was extremely engaging, and covered a wide variety of CS concepts in good detail.”
“Harry pulled on a lot of application–type presentations to explain new concepts to us, and this helped it stick with me more rather than a pure theoretical take on the concepts. I found the problem sets to further enforce the content that we learned in class in a fair manner as well as being fun to do (like a puzzle). He allowed a lot of opportunity for us to ask questions and brought up some of his own if no one was asking any (I found this helpful since his self–questions were ones I had on my mind).”
“[…] Homework was extremely creative and interesting and allowed a deeper, more conceptual understanding of course material.”
“The instructor designed very thought–invoking homework and tutorials to help understand and apply course concepts”
In this semester, I also gained valuable experience in managing course logistics such as managing TAs, communicating with support staff, computing grades, and running exams.
2.2 CSC236 – Introduction to the Theory of Computation – Fall 2022
Context.
- Immediately after the summer course.
- Co-taught with François Pitt (the course coordinator) and Siphelele Danisa.
- Five sections.
- \(\approx 500\) students.
In this course, the teaching team decided to use a pedagogical approach that was quite different from what I was used to – we had 6 term tests (one every other week), a final, and assignments were graded on (essentially) completion. This was an approach from François Pitt based on the finding that frequent testing leads to better learning. The idea was that if marks were based on tests, then students would be more focused on learning from the problem sets rather than simply submitting a correct solution. Here are the pros and cons of this approach in my experience:
Pros
- Students were less likely to procrastinate and fall behind (since they need to be caught up with the course at least every other week, in time for the term test)
- No concerns about academic integrity on the assignments.
Cons
- Term tests took place during tutorials, which meant fewer tutorials.
- Many test questions need to be generated – 3 different versions of each of the 6 term tests.
- Limited in what kinds of questions can be asked (since each term test was just 50 minutes, and there need to be three roughly equivalent variants of the problem)
- Tests (even if they are low-weight) are stressful for some students.
To keep consistent with the other sections, we all used the original course content (without my additions from the previous summer). This was challenging for me at first because I understand certain topics in slightly different ways, and sometimes it’s unclear what exactly the author of the materials had in mind when creating a slide. In hindsight, I learned that I should have consulted more with the author of the slides.
Later in the course, I also tried using the blackboard instead of the slides to help with pacing, and add flexibility. After this course and receiving feedback, I decided this approach did not work well for me, and I would reconsider my lecturing method in my next semester of teaching.
2.3 CSC236 – Introduction to the Theory of Computation – Summer 2023
Context.
- Summer course
- Sole instructor
- \(\approx 100\) students
This semester, I decided on a different grading scheme. I wanted to capture the pros of the grading scheme from the previous fall (many tests, low-weight assignments), and adapt it for a summer course. I used 5 TA check-ins (15-minute meetings), one midterm, and one final. There are 5 homework assignments (one for each check-in), and I promise that at least one of the problems on the midterm and final is based on one of the homework problems. In the check-ins, the TA asks students to explain one or two problems from the problem set, and then students have a chance to ask the TAs any questions they might have about the course. Each check-in is worth 2% of the overall grade.
Rationale:
- Since most of the points from the course come from the exam, students need to understand the topic.
- Students are still motivated to engage with the homeworks because of the check-ins and the promise that one of the problems from the exams will be heavily inspired by a homework problem. Furthermore, students don’t feel pressure to create a perfect solution to the homework and hence see them more as opportunities to learn.
- This approach does not limit the resources available to students to support their learning (if assignments are graded, then no outside resources are allowed, including the internet).
I have included the guide to check-ins and homework from this semester in Section 7, in which I explain the goal of the homework and describe the rationale behind the grading scheme to my students.
Reflecting on this marking scheme, I felt that it mainly achieved the goals I had for it, but there were also some important drawbacks:
- TA time is spent on repetitive work (checking in with students about the same problems).
- Students don’t get feedback on their written proofs until the midterm. There is only limited feedback on assignments. If a TA does not ask them about a particular problem, students might think they understand it even if they really don’t.
- Heavy-weighted exams can be stressful.
I also include the syllabus for this semester in the appendix (Section 7.3).
Approach to lecturing. This semester, I went back to using slides. However, I used a reduced version of the slides that omitted certain proofs and examples for lectures. I then drew over the slides using my iPad. In the end, there were 3 versions of the slides: the reduced version, the full version, and the version with my in-class writing. Writing on the slides helps me pace and allows me the flexibility to add more examples on the fly to better answer questions. The full version of the slides serves as a reference, while the version with my in-class writing captures a record of the additional examples. I also recorded my lectures this semester to make them more accessible to students who might have to miss several lectures due to work, travel, or illness.
2.4 CSC373 – Algorithms Design and Analysis – Winter 2024
Context.
- Co-taught with Nathan Wiebe (course coordinator)
- Three sections
- \(\approx 300\) students
- First time teaching this course
While reviewing the course materials, I noticed a lack of applications for the algorithms learned in class. In fact, in its current state, students go through CSC373 without running a single line of code. In my opinion, this felt like too theoretical an approach, and a big missed opportunity – one of the best things about computer science is the ability to explore and test things out for yourself! Thus, I introduced several coding notebooks, which we set as optional extra credit problems on assignments. For more about these notebooks, see Section 3.1.
Other than these additions, I mostly stuck to the existing materials to stay coordinated with Nathan.
2.5 CSC373 – Algorithms Design and Analysis – Winter 2025
Context.
- Co-taught with Nathan Wiebe (course coordinator)
- Three sections
- \(\approx 300\) students
This time it went much more smoothly. I developed new slides (largely based on the old slides but with additional modifications to suit my lecturing style)
Since I received positive feedback from students on the coding notebooks, I decided to move them into the lecture (instead of being an optional extra credit problem) to improve their reach.
2.6 CSC236 – Introduction to the Theory of Computation – Summer 2025
Context.
- Summer course
- Sole instructor
- \(\approx 100\) students
I went back to the drawing board again for the grading scheme for this course.
The main points I wanted to address from the last time were the usage of TA time and the fact that students don’t get quality feedback until their midterm (halfway through the course). The grading scheme I ultimately landed on was three-term tests and one exam. Problem sets were assigned, but were ungraded.
Rationale:
- Instead of grading or doing check-ins (repetitive work), TA time was freed up to create resources like explainer videos, host office hours, and answer questions on Piazza.
- One of the term tests happens in Week 3 and is lighter weighted than the other term tests, so students can at least get some feedback on their work, and a diagnostic on our expectations.
Additionally, this time I made significant upgrades to the course website (See Section 3.4).
Here is some of the positive feedback related to these factors on my course evaluations.
“Tutorial videos were very helpful in demonstrating how to solve problems.”
“After a full semester, I see why this course has its own website: the website is superior to Quercus in just about every way.”
“The learning support for this course was excellent. The practice problems, tutorials, and explanations provided ample opportunities to reinforce the material. The instructor and TAs were approachable and provided helpful guidance whenever questions arose.”
“Piazza was also used very effectively, with questions being answered promptly.”
2.7 CSC108 – Introduction to Computer Programming – Fall 2025
Context.
- 10 sections
- Co-taught with several instructors including the course coordinator, Jen Campbell
- \(\approx 2000\) students
- First time teaching programming
This course is currently in progress, and it is my first time teaching a non-theory course. I’m really enjoying it so far, and I love how easy it is to engage students, demonstrate errors, and show the problem-solving process.
This is a flipped class, where lectures are mostly reserved for working through worksheets together with the students rather than lecturing. I really enjoy this style of teaching and have gained practice facilitating active learning activities.
3 Materials
In this section, I showcase some teaching materials I have developed over the years. I have selected a couple here to highlight.
3.1 Coding Notebooks
I create coding notebooks to make algorithms tangible: students implement, visualize, and compare methods so efficiency and correctness are felt, not just stated. This supports empowerment (they can build it) and exploration (they can test hypotheses and try variations).
I used Google Colab for the following reasons.
- Minimal setup required. The notebook runs in the cloud, so no local setup is required (no need to install Python or other libraries).
- Easily shareable. Students can easily make a copy of the notebook to work on their own version.
I’ll highlight one of these notebooks, and the rest can be found in Section 3.1.2.
Huffman Coding and Closest Pair of Points in \(\mathbb{R}^2\)
The notebook I want to highlight (linked here) is one I created for the first two topics of the algorithms course – divide and conquer and greedy algorithms. In this notebook, students implement two algorithms that were discussed in lecture, Huffman Coding and a divide and conquer algorithm for the closest pair of points in \(\mathbb{R}^2\) problem.
Below is a summary of the notebook and some screenshots
Huffman Coding
- Setting up the problem and motivation (data compression)
- Examining provided tools (Binary tree, priority queue, and visualizations)
- Implementing the algorithm and generating an encoding
- Testing the encoding on different texts. Open ended question: does this encoding do better than the naive encoding on all texts?







Closest pair in \(\mathbb{R}^2\)
- Examining provided tools (Point class, visualization, brute force algorithm)
- Implementing the divide and conquer algorithm
- Comparing runtimes of brute force vs divide and conquer
- Testing on large inputs (to see the efficiency difference)
The next problem is to implement the closest pair of points in \(\mathbb{R}^2\) algorithm using divide and conquer. Again, I start by setting up the problem and giving them several tools to work with in their implementation, including a function to visualize points.





List of Notebooks
For CSC373
- Huffman Coding + Closest Pair of Points in \(\mathbb{R}^2\)
- Dynamic Programming algorithms for the knapsack problem and the TSP problem
- Flow and Linear Programming on weighted bipartite matching

For CSC236
- Matching (Also see Section 3.2.1).
- TSP vs. MST


For CSC448 (as a TA)

3.2 Lectures
In this section, I highlight parts of two lectures I developed for CSC236 (Introduction to the Theory of Computation). I chose these two lectures because they illustrate my approach to making theory tangible and relevant to students, as well as my approach to learning theory through exploration and discovery.
Matching
This example is from a lecture on graphs and modelling in CSC236 (Introduction to the Theory of Computation). The main goal of the unit was for students to model real-world problems as well as studied problems on graphs. I introduced this unit because it squarely belongs in theory (the idea of reductions is central to theoretical computer science), yet also has clear applications to the real world. Throughout the lecture, I define several graph problems and give examples of how real-world problems can be made instances of these graph problems.
After defining the matching problem, I tell students that I’ve actually been working on a problem that can be modelled as a matching problem – assigning homework partners from this course! At this point, I open up a coding notebook I prepared earlier and show them the data I have collected earlier in the week on their availability and working preferences. It looks like this.

I then get students to model the problem of assigning homework partners as a matching problem. Once we have agreed on how to do it, I show them some code to turn the table into the graph that they defined. Next, I help students develop intuition for the problem and appreciate how non-trivial it is. I start by plotting the graph for just 6 students, and ask for an optimal assignment.

This is still easy enough to compute by hand. Then I plot the graph for 8 students, and it already becomes difficult. Next, I try to plot the graph for 20 students, and it becomes a complicated mess. Now that the students have some appreciation for the complexity of the problem, I then show them how to solve the problem using a single library call.
matching = nx.max_weight_matching(g, maxcardinality=True)Finally, I show them the documentation for networkx, which implements several graph algorithms. I emphasise to them that I did not need to know how to solve the matching problem to do all of this. All I needed to do was to know how to model my problem as a problem on a graph. This drives home the importance of modelling, which was the topic of this lecture.
Fibonacci
This example is from lecture 5 from CSC236 (Introduction to the Theory of Computation). The main goal of this lecture is to introduce students to the idea of recurrence relations and how to solve them using induction. This part of the lecture comes after defining recurrence relations and reviewing asymptotics. To introduce Fibonacci numbers, I use the classic domino tiling problem. I pose the following question.
How many ways are there to tile a \(2 \times n\) board using \(2 \times 1\) dominoes?
I define \(T(n)\) to be the number of tilings of a \(2 \times n\) board, and we work through some small examples together: I show them the following empty boards for \(T(4)\) and take suggestions from them on how to place the dominoes.

Eventually, we end up with the following tilings.
We then do the same for \(T(5)\).

Then, I ask students to find a recurrence relation for \(T(n)\). Usually, someone notices the key insight: the first domino placed can be either vertical or horizontal, leading us to the following conclusion.

I note that this recurrence might be familiar to them, and it’s the famous Fibonnaci sequence (shifted by 1).
\[ F(n) = \begin{cases} 0 & n = 0\\ 1 & n = 1\\ F(n-1) + F(n-2) & n \geq 2 \end{cases} \]
I then prove a simple upper bound on \(F(n)\).
Claim. \(\forall n \in \mathbb{N}. F(n) \leq 2^n\).
I then ask if there was slack in this argument, and students usually notice that the inequality \(2^k + 2^{k-1} \leq 2^k + 2^k\) is quite loose. We then try the prove \(\forall n \in \mathbb{N}. F(n) \leq 1.8^n,\) and the proof still works. I then get ambitious and try with \(1.5\) instead of \(2\), but now the key inequality fails. In particular, we have
\[ (1.5)^k + (1.5)^{k-1} = (1.5)^k(1 + 1/1.5) = (1.5)^k \cdot 1.666 \]
But this is not less than \(1.5^{k+1}\) since \(1.666 > 1.5\).
So the true answer must be somewhere in between \(1.5\) and \(1.8\). This setup naturally begs the questions: what is the true answer? How can we find it? At this point, students who don’t know about the golden ratio are curious, while those who do know the right answer are wondering how to arrive at it.
Before arriving at the true answer, I have students explore to find the right exponent ‘graphically’ using the following interactive Desmos graph.
I have populated the graph with Fibonacci numbers and some sliders to adjust the exponent and scale. Students can then visually see how close they are to the true exponent by adjusting the sliders. This activity usually happens during a break in the lecture. After the break, I project a copy of the plot on the screen and ask students for the best values that they found, and show the graph with those values plugged in. Usually, we get something very, very close (usually, the exponent is correct up to 2 decimal points).
Now that the students have an idea of the correct answer, I show them how to arrive at it by modifying the inductive proof to use \(x\) as the base of the exponent, and then solving for \(x\) so that the key inequality becomes an equality.
I like this activity because it engages students in a discovery process. Instead of defining the golden ratio and proving outright that \(\forall n \in \mathbb{N}. F(n) \leq \varphi^n\), I show how one might arrive at the golden ratio. This hands-on approach gives students a deeper understanding of the why the golden ratio is the right answer, rather than just accepting it as a fact.
3.3 Assignment Problem – Rubik’s Inevitability
This problem shows up in an introduction to theory course after students have learned about functions, graphs, and induction.
I see this problem as a milestone for students, as it combines several concepts learned in the first few weeks and requires creative thinking to solve. The problem centers around the following strange phenomenon.
Fix a sequence of turns of a Rubik’s cube, and suppose the Rubik’s cube starts in the solved state. If we repeat this sequence of turns enough times, the Rubik’s Cube will eventually return to the solved state. Crucially, this is true regardless of what sequence of turns we choose!
For simple sequences, this is easy to verify – for example, if the sequence is “turn the front face clockwise”, then it’s not hard to see that after 4 repetitions, the cube returns to the solved state. However, for more complex sequences, the cube becomes quite scrambled, and it’s not clear why repeating the same sequence would eventually return it to the solved state. However, inevitably, almost like magic, the colors begin to match up again, and the cube returns to the solved state. Here’s one example .
I like this problem for two main reasons.
- It is a surprising and counterintuitive fact that piques students’ curiosity.
- The problem is challenging and integrates several concepts learned in the first few weeks of the course, which makes students feel accomplished when they finally solve it.
I have asked several versions of this problem (with varying levels of scaffolding). Below is the most recent version of the problem I have used. Note that in the web version, solutions and hints are collapsible.
A Rubik’s cube is a fun puzzle/toy. If you don’t have a Rubik’s Cube, check out this simulator.
Assume the blue face of the cube is always facing you. A state of the cube describes the current position of all the stickers. For example, the solved state of the cube is the one where every face has just one color (namely, the one matching the center square of the face).
The cube has \(6\) faces. Let \(f_i\) be the operation of turning the \(i\)th face of the cube a quarter turn clockwise. Let \(\mathrm{Turns}= \{f_1,...,f_6\}\) be the set of turns one can perform on the Rubik’s cube.
a.) Let \(s\) be the solved state of the Rubik’s cube. Define the set of possible Rubiks cube states, \(\mathrm{Rubiks}\), recursively or inductively.
b.) Model the task of solving a Rubik’s cube in the minimum number of moves as a graph problem. Fully specify the vertex set, edge set, and edge weights (if any), and explain why a solution to the graph problem corresponds to solving the cube.
Start with a solved Rubik’s cube and consider any fixed sequence of turns. Now repeat that sequence of turns many times. Eventually, somewhat magically, the Rubik’s Cube will return to the solved configuration! In this problem, we will prove this fact.
c.) Let \(g\) be an arbitrary sequence of turns. Show \(g : \mathrm{Rubiks} \to \mathrm{Rubiks}\) is an injective function.
d.) Give an upper bound on \(|\mathrm{Rubiks}|\) i.e. find some \(k\) such that \(|\mathrm{Rubiks}| \leq k\)
Let \(g\) be an arbitrary sequence of turns. Denote \[g^m = g\underbrace{\circ ... \circ}_{m \text{ times}}g\] to be the function that applies \(g\) \(m\) times. Also, let \(s \in \mathrm{Rubiks}\) be the solved state of the cube.
e.) Show that for some \(m \in \mathbb{N}\) with \(m \geq 1\), \(g^m(s) = s\). That is, after \(m\) applications of the sequence of moves defined by \(g\), we return to the solved state!
Hint. Consider the sequence \(s_0, s_1, s_2,...\) where \(s_0 = s\), and \(s_i = g^i(s)\).
3.4 Course Website
When I teach CSC236 in summer terms, I develop my own course website. Here is the website for the most recent iteration of the course.
The main benefit of this approach is that all course content is in one place, including lectures, tutorials, and problem sets. This enables the following:
- Search functionality. There’s a search bar that lets students find what they are looking for quickly. In my experience, this drastically reduces the number of clicks required to find something.

- Everything is linkable. Not only does each lecture/assignment/tutorial have links, each heading and subheading in each webpage also have links. This allows me to precisely direct students to relevant material. For example – here is The Master Theorem.
It’s also faster than the course management system that the university provides.
While creating a website seems overkill when other course management systems like Quercus / Canvas are available, the website actually made things easier for me to manage.
- Since I create the website, I can automate much of the updating.
- It’s easier to deal with students enrolling late – I can just link them to the course website instead of looking them up on the CMS and manually adding them as an observer.
3.5 CSC236 Concept Map
I made this concept map as a present to my students in CSC236 at the end of the course.
I showed it to them in the last lecture for them to celebrate how much they have learned over the semester. I wanted students to appreciate the breadth of topics we covered and how they all fit together. Seeing all the topics laid out like this seems very impressive and hopefully makes the students feel accomplished.
Next time I teach, I will keep a running version of this map throughout the course, updating it as we cover new topics. This may help students see how new topics fit into the big picture as we go along. I also imagine a cool animation of the graph growing as we cover new topics, starting as a few nodes and gradually expanding into the full map by the end of the course – that could be awesome!
3.6 Tutorials Slides
I have TA’ed for CSC448 (Formal Languages and Automata) and CSC463 (Computational Complexity and Computability) several times, and I have developed tutorial slides for both courses that cover some additional topics. These tutorial slides I developed are still being used in current iterations of the course.
I would like to highlight tutorial 9 on the time hierarchy theorem from CSC463, which I include in the appendix (Section 8).
Here are dropbox links to the full set of tutorial slides for CSC463, and tutorial slides for CSC448.
3.7 Inspirit AI
Before starting my PhD, I developed several AI projects for high school and middle school students for Inspirit AI. A big part of this work involved making AI concepts accessible and fun for younger students. Here are some of the projects I developed.
- Self-driving cars: 1, 2, 3
- In this project, students gradually build models to drive cars in one of the OpenAI Gym environments.
- The project starts with basic models to decide whether the road turns left or right and gradually builds to models based on behavioral cloning and deep Q-learning.

- COVID-19 mask detection: 1, 2, 3
- In this project, students build models to detect whether or not someone is wearing a mask.
- The models start very simple (using the color distribution of the input image) and gradually get more complex, building up to a convolutional neural network with a facial recognition preprocessing step.
- Students then get a chance to test the model on their images.
- Game-playing AI – the minimax algorithm and variants
- Students implement the minimax algorithm and use it to play tic-tac-toe and Connect 4.
- Students tune a heuristic evaluation function and then get to play against their algorithm, which is always fun :)

4 Course Evaluations
In this section, I summarize some information from my course evaluations.
- Section 4.1 picks out some comments from students grouped by theme,
- Section 4.2 summarizes the quantitative rating data from my course evaluations.
- My raw course evaluations can be found in the appendix (Section 6).
Scope: 6 courses between 2022 and 2025 (see Section 2).
4.1 Comments
Creating a positive learning environment
“The overall quality of the instruction of the course was very positive and strong. It was very well organized, each lecture signified a different section of the course and all material supported each other which really help create a learning atmosphere for me.”
“Clear instruction, good atmosphere, gives opportunity to discuss, always leave room for student to express confusion, overall incredible.”
“Harry is a good instructor who explains concepts clearly. In–class examples were well–chosen to illuminate the subject matter. He brings a good sense of energy to the class and keeps things moving at a good pace. The class at times had a wonderful informal vibe, where people seemed to feel empowered to ask questions. I would encourage taking more moments for class participation and/or for students to work on problems on their own, as this was engaging when it happened.”
“Harry was very engaging in lectures and created a great teaching atmosphere. He also responded quickly to my questions.”
Relevant examples and applications
“Great! I really enjoyed the course a lot! I find that the material on its own is not easy but Harry made it a lot more interesting and engaging in the lectures/homework questions so I actually felt more inclined to learn more about it.”
“One of the best instructors I’ve had at UofT so far. Mr. Sha comes in to his lectures with a lot of enthusiasm. Additionally, when creating / providing examples for his slides or homework problems, he comes up with things that”relate” in a way to people who grew up in my generation. I also love the doodles he created for his lecture examples. The format of the course is conducive to learning: ie. when you show your effort in your homework solutions, you are not punished for the mistakes you made, synonymous to my belief that problem sets / homework are tools to learn from your mistakes, whereas midterms/finals are to show what you have learnt.”
“Professor Sha did an excellent job at making CSC236 a really engaging, interesting, and overall enjoyable experience. All of the course materials used and developed by Professor Sha for this course showed a high level of detail, care, and thought, including lecture slides and homework assignments. Lecture content was extremely engaging, and covered a wide variety of CS concepts in good detail.”
“The instructor was very enthusiastic and presented information well. He was very approachable and answered questions in an encouraging manner. I liked the commentary tying the material to future endeavors and related fields in computer science and STEM applications. Problem sets and tutorial questions were critical in solidifying understanding of lecture content. Tutorial videos solving problems were a great add.”
“Harry pulled on a lot of application–type presentations to explain new concepts to us, and this helped it stick with me more rather than a pure theoretical take on the concepts. I found the problem sets to further enforce the content that we learned in class in a fair manner as well as being fun to do (like a puzzle). He allowed a lot of opportunity for us to ask questions and brought up some of his own if no one was asking any (I found this helpful since his self–questions were ones I had on my mind).”
Effective lecturing and class participation
“Extremely well planned and executed lectures and tutorials. Professor was an absolute pleasure to listen to and I would highly recommend any class he teaches. He really knows his material and has a deep passion for the subject.”
“Harry has a deep grasp of the lecture material and explains it quite well. Unfortunately the course material does get quite repetitive but Harry’s charm allows for this reengagement to still be a little intellectually satisfying.”
“I have previously taken an equivalent course at another campus, but I had a more pleasant and motivating learning experience with Harry. The level of assignments and midterms are adequately adjusted to show my understanding of the course materials and challenge me sometimes. Harry really takes his time to answer any questions, introduces techniques to tackle problems, and creates an enjoyable atmosphere during lectures. Although I find the nature of the subject material to be difficult, it was his teaching that made me like solving problems in this class.”
“Harry is a superb lecturer. It is clear that he cares a lot about the material and wants his students to succeed. He explained the material in a very clear and understandable way, which allowed me to spend most of my revision time approaching practice problems/assignments rather than retroactively trying to decipher lecture material (as I did for 236 and 263). I also really appreciated that Harry did a good job of summarizing concepts so I could intuitively understand them and not memorize as much.”
“Lectures were engaging and relatively easy to follow”
Generating enthusiasm and creativity for the course
“One of the best quality instruction I’ve ever received in any course at UofT. The prof generates a great deal of enthusiasm towards the course content. Furthermore, every now and then, he pauses to ask the class if they have any questions which I think is a great thing.”
“The instructor designed very thought–invoking homework and tutorials to help understand and apply course concepts”
“Quality was amazing, Harry is a phenomenal instructor who describes topics clearly and is very approachable. He makes learning fun!”
“Professor Sha is an extremely enthusiastic teacher, and his knowledge and excitement about course content was obvious during every lecture. I’m a physics major but I looked forward to this class’ lectures more than my physics class’ lectures!”
“The quality of instructions was very impressive. Harry made the class very accessible and fun. Really enjoyed learning in his class.”
Course organization
“Excellent course and great delivery. Loved the fact that the homework was not graded for correctness but for effort and this allowed to study so much better for exam.”
“Overall the course is clear. I really like the fact that professor helped us to find an assignment partner. This really motivated me to learn more and be more and submit assignment in time.”
“Very straightforward slides / website. The professor (Harry Sha) was also very organized and attentive”
Overall quality of the course
“Harry was an excellent instructor. Truly a super nice person, and actually wants all of his students to succeed. Harry taught the material really well, and communicated difficult concepts really well.”
“The instructor did an excellent job of teaching this course. He made the course enjoyable while keeping it intellectually challenging and did administration tasks well.”
“Harry is an excellent instructor and very approchable and enthusiastic excellent”
“Harry Sha is one of my favorite course creators in my time at uoft. everything in the course was immaculate. from the amazing asignments, to the crystal clear slides. He took a extremelly difficult topic and made it accessible and understandable to everyone”
“Excellent. The best course I have taken in the university so far!”
4.2 Ratings
| Question Number | Question |
|---|---|
| 1 | I found the course intellectually stimulating. |
| 2 | The course provided me with a deeper understanding of the subject matter. |
| 3 | The instructor (Harry Sha) created an atmosphere that was conducive to my learning. |
| 4 | Course projects, assignments, tests, and/or exams improved my understanding of the course material. |
| 5 | Course projects, assignments, tests and/or exams provided opportunity for me to demonstrate an understanding of the course material. |
| 6 | Overall, the quality of my learning experience in this course was: |
| 7 | The instructor generated enthusiasm for learning in the course. |
| 8 | Compared to other courses, the workload for this course was: |
| 9 | I would recommend this course to other students. |
- Instead of scrolling up to see the mapping between question numbers and questions, you can also hover over the bars to see the question text.
- You can click on the legend to deactivate different groups.
The following charts summarize the quantitative ratings from my all of my course evaluations, they are plotted against departmental and divisional averages for comparison. Ratings are on a scale of 1 to 5.
The total number of responders is 197
Key takeaways
- Scores exceed departmental and divisional benchmarks on all questions.
- The largest margins are on questions 3 and 7, which are about creating a positive learning environment and generating enthusiasm for the course. The margins are 0.35 and 0.34 respectively.
Here are the average ratings for courses in which I was the course coordinator / sole instructor. The total number of responders in this subset is 121.
Key takeaways
- Scores exceed departmental and divisional benchmarks on all questions except question 8 (workload).
- The largest margins are again on questions 3 and 7, with even larger margins (0.52, and 0.48 respectively).
Here is the same information as a radar chart.



