Tuesday, August 10, 2010

The Secret to Learning Anything

SkyHi @ Tuesday, August 10, 2010
Some of the most important lessons I learned in college came from one professor,
Michael Mitzenmacher. Now,
this was a guy with a lot of papers to his name, tenured at Harvard,
working on some pretty darn complicated computer science theory (I took his
algorithms class). So you'd expect that I'd learn something important. But as
it turned out, the biggest lessons I learned from him weren't on the topics he
taught. I learned a secret that helped me learn much more effectively.

At one point when describing the problem sets in the class, he gave some advice
that stuck with me:

Don't suffer from Math Major syndrome

So, what you ask, is Math Major syndrome? Well, think of it this
way--if you are studying a hard problem, what's your first tendency? To get
lost in thought? To start at it, mulling over ideas in your head, waiting for
a flash of insight? If so, that's math major syndrome. It's the idea that you
can (or have to) solve problems entirely through a brilliant flash of insight,
without doing any actual work.

The alternative is quite simple:

Hard problems become easier by working through them with diagrams, effort and patience

In other words, don't just wait for answers to come to you--go out and find
them. Don't just use what's in your head--use paper, or the computer, or a
whiteboard, to draw out the ideas, try experiments, make the patterns
visible rather than waiting for a flash of insight.

I remember really learning this lesson during the first problem set--I'd
started it when it was handed out, but the night before it was due I still had
one problem left. I spent hours on that problem, but I spent it drawing out
equations, working through possiblities. Each one ended in failure, until I
had a flash of insight in the middle of writing out an equation. If I hadn't
worked through (and discarded) all those possibilities, I'd have had no hope of
solving that problem.

So how do you apply this principle in practice?

Program Program Program

If you're learning to program, you should be programming. Work practice problems while you
read tutorials--in fact,
you're probably better off in most cases working practice problems than
you are reading about programming. (You will need to read, but without
practice, that reading means nothing.)

In fact, if you're just learning to program, then I suggest that you stop
reading this article right now and go write some code (or get yourself
set up with a compiler and
then go write some code). But not something you know how to solve--try to
write a program that is just a little bit scary or hard. You should feel just
a bit scared that you won't be able to do it.

Draw it Out

A second corollary to the principle is that you're better off using paper than
trying to imagine everything. In fact, I can't say enough about the importance
of drawing diagrams. A lot of things in programming sound very abstract or
difficult to describe in words, but they can be quickly shown with a picture.
Computer memory, for example, can be thought of as a long block of cells
(almost like in an Excel spreadsheet). Drawing out each piece of memory in
your program (when dealing with pointers or data structures) can really help
visualize what is going on. You can also write out recursion manually by
showing each recursive call with its arguments and return value.

But even simpler concepts become clear when you draw them or work through them
step by step--having trouble understanding a complex piece of code? Write out
the different variables and how they are modified. For example, the boolean

! a || b

(in other words, NOT a OR b)

has a very specific meaning in English: "if a is true, then b must be true";
this could be useful for checking user inputs ("if the user pressed exit, then
the game must be over--otherwise, print out an error"). But it's not
at all obvious what ! a || b means unless you actually work through it. What
do I mean?

The statement "if a is true, then b must be true" requires that:

if a = true, b must be true<br />if a = false, b can be either true or false<br />

How does that work for the expression "! a || b? You can draw out the table by
writing a in one column, b in a second, and whether the condition is satisfied
result in a third:

ab! a || b

Now you can more quickly see that the table expresses the English condition.
The condition is satisfied in all the cases except when a is true and b is
false (clearly, that can't satisfy an expression that says, "if as is true,
then b is true"!)

Being able to look at the data really helps!

Related Articles