One year ago, I started writing here on the topic of deliberate practice techniques for software developers. This is my 52nd weekly post for 2015. With the year coming to an end, let’s review the story so far.
Algorithmic Problem Solving
Improving programming ability requires a combination of theory and practice. You need to learn new things, and then write code that requires you to use that knowledge. What you want to learn and practice is up to you. You could focus on a programming language like C++, a web development framework like ASP.NET, a specialty like content management systems, or one of an almost limitless number of other areas that programmers work in.
But there’s one topic area that’s a special case: algorithmic problem solving — i.e., using algorithms to solve problems. This area is known to all programmers, regardless of their areas of specialty. It comes up throughout a programmer’s career: After Computer Science students learn programming basics, they learn algorithms. When companies want to evaluate a candidate’s programming skills, they often present them with algorithmic problems. The most popular programming contests also focus on these types of problems. While you can’t be sure that a programmer knows a specific technology, it’s reasonable to ask them to solve a programming puzzle in their favorite language.
So rather than picking a specific topic area that I know about, and mining it for examples of how to get better, I’m focusing mainly on algorithmic problem solving. In practice, that means competitive programming, with or without competition.
When I come across interesting algorithmic programming problems during my learning project, I often use them as topics for blog posts. Last week, I wrote about UVa 927: Integer Sequences from Addition of Terms. I know these types of posts are useful because I use them myself when I’m stuck on a hard puzzle and I’m no longer making progress on it. Reading an editorial for a problem that you have worked hard on is a good way to get better at problem solving.
Writing an editorial is also a good way to solidify the lessons that you learned in solving the problem. And in my experience, it’s an easy type of blog post to write once I have an accepted solution. The hard part is solving the problem, and then it’s just a matter of translating my thought process into an understandable form. Others may find that the opposite is true. (Solving the problem is easier for them than writing an editorial).
Despite the benefits of problem editorials to both writer and readers, it’s not enough just to explain the solution. It’s great to have a clear explanation of how to solve a particular problem. But what readers really wants to know is how they can solve problems on their own. In other words, what is the thought process that an experienced algorithmic problem solver would go through when they encountered the problem. I try to include some of that when I write up a solution.
Early in the year, I published a process for getting the most learning benefit out of programming puzzles. Although I believe that using this process will result in faster learning than an ad hoc approach to problem solving, my process does not explain how to find the solution to an algorithmic problem. Processes like that do exist, and it’s something I’ll write about in the future.
Blogging experts sometimes advise writers to “niche down” — focus on a specific aspect of a general topic. This is a technique for standing out in a crowded field. There are a number of bloggers who focus on learning in general (see Cal and Scott), or on learning specific technical subjects (e.g., BetterExplained for math). But I haven’t seen a blog that publishes regular posts specifically on improving algorithmic problem solving skills. My goal is to fill that niche.
At the beginning of August, I published a review of my posts so far, categorized according to nine themes. Those themes are still appropriate for the posts I have written since then. Here’s a review of my August-December posts, categorized by seven of the nine themes:
Theme: Deliberate Practice
Unit Testing your Competitive Programming Solutions: Part of the deliberate practice approach is using continuous feedback (see element #3) to improve a skill. Unit tests are also intended to provide feedback continuously, rather than only at fixed intervals, as with traditional software testing. Writing unit tests for your programming puzzle solutions can help identify areas of weakness that might be hidden if you’re relying only on running your whole program to find bugs. I don’t use unit tests on every problem, or even on most problems. But they can be helpful when splitting up the solution to harder problems.
The Role of Questions and Answers in Learning: Another source of deliberate practice feedback is active recall learning techniques, in the form of questions and answers. Q&A learning techniques ensure that you’re really learning. You can also think of unit tests as a type of Q&A. The question is “What code will make this test pass?” The answer is the code, and you know it’s correct if the test passes.
Theme: Productivity Systems
Productivity systems are a way to make your work results more predictable. I came up with a system called Time Bank that I have been using for almost a year now.
Software methodologies are productivity systems that are normally used for groups of programmers, but you can use them to make your individual work more effective as well.
Measuring your productivity is key to making your system work, and measuring yourself is less error-prone than trying to measure someone who works for you.
While getting advice about productivity is better than building your system from scratch, you ultimately need to build your own system and experiment to find out what works best for you. The Top Performer online course takes that approach by combining advice with exercises that prompt students to develop systems appropriate for their field.
Theme: Coding Education
Working on coding fundamentals is rarely wasted effort. Sometimes I dig into topics like using integers and longs in Java. There are always language details to learn better.
Theme: Programming Puzzles
Although I write about programming puzzles all the time, I sometimes like to consider them at a higher level. For example:
- Why competitive programming is a tricky topic to bring up on Stack Overflow, and how to get answers about it there.
- A definition of competitive programming that applies to everyone who wants to try it, not just famous people.
- The ongoing debate about the pros and cons of competitive programming.
I also wrote an editorial for UVa 100: The 3n+1 problem, a puzzle that many people use as their introduction to UVa Online Judge.
Theme: Math and Algorithms
It’s hard to get very far in competitive programming without a certain amount of math experience. Even relatively easy problems like UVa 927: Integer Sequences from Addition of Terms requires reading math notation and understanding some basic discrete math concepts. For some people, the math in most programming puzzles is invisible. They just read it as they would read any other technical description, and what it means is fairly obvious. For those people, a problem only “requires math” when it requires knowledge of a more unusual (for computer science students) math topic, like topology.
Theme: Learning Projects
My learning project continues to supply me with interesting material.
Theme: Publishing Results
The last step in learning something is teaching it to others. Here are the uHunt starred problems that I wrote about since August:
- UVa 11572 – Unique Snowflakes: The key concept is segments.
- UVa 978 – Lemmings Battle!: I used this one for my unit test experiment.
- UVa 100 – The 3n+1 problem: The most popular problem on UVa Online Judge.
- UVa 11402 – Ahoy, Pirates!: The key concept is segment trees. I spent more time solving this problem than any other uHunt problem so far.
- UVa 927 – Integer Sequences from Addition of Terms: The description for this problem has a bit of math notation.
I’m also writing the longest review ever of Competitive Programming 3 by Steven and Felix Halim. In November, I wrote three posts related to Chapter 2 of that book:
- Lessons from uHunt Chapter Two: On the programming problems.
- Lessons from Competitive Programming 3, Chapter Two: On the book chapter itself.
- Java Lessons from uHunt Chapter 2: On the Java language concepts required to solve the problems.
That’s it for this year. See you all in January!
(Image credit: A winter scene from the farm where I used to live)