Hi everyone,
How did I choose the problems that drive each chapter, and the chapter exercises?
I’ve had more than a few readers now email me and ask me this question. I like to reflect on my writing processes, so this question is interesting to me. I didn’t think it would be interesting to anyone else.
But since some readers have asked, I feel like that gives me the excuse I need to write this post! :D
In almost all programming books, the author of the book comes up with the examples, exercises, projects, etc. as part of writing the book. I imagine that those authors decide what topic to exemplify next, then design a learning resource (example, exercise) for that topic. They decide on both the material to be taught and how to teach it, so it meshes well.
My book, Learn to Code by Solving Problems is kinda designed backward compared to those books. I didn’t come up with a single chapter problem or exercise myself. I found them all on programming judge websites.
It seems like this would make my job easier, right? I guess I could have come up with all kinds of problems and exercises myself, fine-tune them, test them – but I can promise that my book wouldn’t be in your hands right now if it were just me. We wouldn’t have this book without the amazing folks who designed all of these materials.
So in that way, it did make my job easier. But in a weird way, it made it harder, too, because now I had to unearth the perfect problems from the thousands of problems out there.
lol, perfect problems. Let me be clear: everything that anyone ever does, if they give it their best, is perfect for some purpose. My first book that I wrote 15 years ago sucked, but it was perfect to help me write future books. So by perfect problems, I mean problems that worked perfectly for my purposes. Now, I don’t think I found too many (my failing, not the failing of the problem authors), but I had to stop somewhere, and “perfect is the enemy of finishing something”.
When going through hundreds or thousands of problems, looking to fill a specific purpose, I was somehow deciding which ones to use and which ones to pass on. I’d often find a problem that I liked and would write it down, but then keep searching because I thought I could do better. Sometimes I could, sometimes I couldn’t. Other times, I’d find a problem and know in my heart that it was the right problem.
I’m trying to reflect on this two years after doing the writing, so it may not be entirely accurate. But an example of a problem where I was happy but not elated was Problem #19: Common Words. It just seemed too tough for the first dictionary problem, and I still think it is. But in the intervening two years I still don’t have a replacement, even if I were afforded the opportunity to do a new edition. An example where I found a problem and knew it was the one is Problem #11: Village Neighborhood. I think that one still holds up for my purposes of motivating why we need lists.
So what was I looking for?
I wanted each problem to have some context. Now, in these small problems, it’s really difficult to have meaningful contexts, but I wanted something. It’s likely easier to think about villages at points along a street rather than numbers on a number line, or cities and states rather than nonsense letter combinations. At the same time, I didn’t want the context to require too much setup or to overwhelm the problem with details. I also did my best to choose accessible contexts. Ugh: in Problem #14: Card Game, I said that the reader didn’t need to know anything about cards (I didn’t want to exclude anyone here), before immediately using the word deck. I can do better than that. :( at least I explained how US states work in Problem #20: Cities and States.
So often I’d find a problem that I really liked, but that used some programming feature that I hadn’t planned to introduce yet. It was a fun challenge to find problems that fit into the curriculum that I was designing for the book. Importantly, when introducing a new programming feature, I didn’t want the problem to be solvable using what the reader already knew. Sometimes that’s impossible because programming features can overlap and be used for the same purpose. For example, for Problem #6: Occupied Spaces, we don’t absolutely need a range for loop, but I think a range for loop is the way that most programmers would solve this problem.
One of my readers told me that they recently solved the High Tide, Low Tide problem. I was totally pumped for them that they not only found a new problem but also had solved it. Then I started thinking: why didn’t I use this problem in Chapter 5? It uses lists. It requires the list to be sorted. We can use the split
method just like we did in Problem #12: School Trip. Did I need to redo Chapter 5 and apologize to the publisher and all readers for the wrong problem? (I know, seriously. Impostor Syndrome never goes away.)
No, we’re good. I remembered why I didn’t use the High Tide, Low Tide problem: I think it’s a little hard to understand the problem statement itself, and there are some fiddly bits to get right in the code having to do with even/odd lengths of the list. I must not have wanted that (seeming) distraction in the chapter. It’s a great problem exercise, though!
To summarize: I was looking for problems where the programming concept I wanted to teach was the focus, not special cases that distracted from teaching the concept. Of course, these special cases are great for practicing the concept once learned.
And again: these problems are perfect for their purpose. The purpose of these problems is not only to teach but to help people test and improve. Some problems seem to me to be more on the teaching side and others on the testing side, and it was my task to orchestrate the problems to teach.
I try to respond individually to all of my readers – keep those emails coming! – but I wanted to also give an overall thank-you to everyone who has supported my work. When you read a book, you are implicitly trusting the author with your time. Thank you for that trust, and I hope that in return the book has helped you be a better programmer.
Written on February 11th, 2023 by Daniel Zingaro