Hacker News new | past | comments | ask | show | jobs | submit login
How to do hard things (drmaciver.com)
1189 points by necrodome 30 days ago | hide | past | web | favorite | 116 comments

The most valuable thing I learned at university was how to tackle difficult problems. Taking advanced math and science courses where I had to really study, and still struggled, and having to write essays so frequently that I could no longer procrastinate or wait for the spark to hit me, was more valuable in the long run than any of the actual knowledge I gained.

The advice to break a hard problem down into simpler pieces good, but I feel like that is often difficult without proper domain knowledge. In many cases, knowing how to break apart a problem like that is how you become an expert in the first place. If you want to learn a musical instrument, there are plenty of good simple excercises to start with, but only an expert can tell you what they are, you can’t easily intuit them from scratch. An experienced programmer will know how to break down a difficult project into small and simpler pieces, that ability is part of what makes them an expert. “Find a good teacher” and “put in the work” seem like rather banal pieces of advice, but it’s a system that has consistently worked throughout the ages. If you are truly breaking new ground then you should already have a framework and significant experience to guide your exploration.

Your comment reminds me of the exercise where a class was split into two cohorts, one was tasked with producing just one clay pot (I can't remember the thing now), while the other cohort was tasked with making one per day or something similar.

Put simply, one group put all of its energy into producing just one, and the other group just turned out pot after pot after pot.

At the end, so the story goes, the group that cranked out pots like crazy ended up producing pots of higher quality.

In my own life, I can often find out the thing that I'm afraid of learning because I've set it up like that first cohort: making the one perfect thing, instead of putting it out there and iterating on it or making another based on what I learned. Goes with learning languages (I'd do way better if I simply tried speaking every day, but I wait for perfect opportunities).

> (I can't remember the thing now)

Don’t worry about the details; it was just a made-up story in the book Art & Fear; I have never seen any evidence such a pottery class ever existed. https://kk.org/cooltools/art-fear/

> The ceramics teacher announced on opening day that he was dividing the class into two groups. All those on the left side of the studio, he said, would be graded solely on the quantity of work they produced, all those on the right solely on its quality. His procedure was simple: on the final day of class he would bring in his bathroom scales and weigh the work of the "quantity" group: fifty pound of pots rated an "A", forty pounds a "B", and so on. Those being graded on "quality", however, needed to produce only one pot -albeit a perfect one - to get an "A". Well, came grading time and a curious fact emerged: the works of highest quality were all produced by the group being graded for quantity. It seems that while the "quantity" group was busily churning out piles of work - and learning from their mistakes - the "quality" group had sat theorizing about perfection, and in the end had little more to show for their efforts than grandiose theories and a pile of dead clay.

This story is somewhat true actually if you correct for the literary license taken.

James Clear reached out to the authors of Art& Fear and this is his footnote: (Link:https://jamesclear.com/repetitions)

This story comes from page 29 of Art & Fear by David Bayles and Ted Orland. In an email conversation with Orland on October 18, 2016, he explained the origins of the story. “Yes, the ‘ceramics story’ in ‘Art & Fear’ is indeed true, allowing for some literary license in the retelling. Its real-world origin was as a gambit employed by photographer Jerry Uelsmann to motivate his Beginning Photography students at the University of Florida. As retold in ‘Art & Fear’ it faithfully captures the scene as Jerry told it to me—except I replaced photography with ceramics as the medium being explored. Admittedly, it would’ve been easier to retain photography as the art medium being discussed, but David Bayles (co-author) & I are both photographers ourselves, and at the time we were consciously trying to broaden the range of media being referenced in the text. The intriguing thing to me is that it hardly matters what art form was invoked—the moral of the story appears to hold equally true straight across the whole art spectrum (and even outside the arts, for that matter).” Later in that same email, Orland said, “You have our permission to reprint the any or all of the ‘ceramics’ passage in your forthcoming book.” In the end, I settled on publishing an adapted version, which combines their telling of the ceramics story with facts from the original source of Uelsmann’s photography students. David Bayles and Ted Orland, Art & Fear: Observations on the Perils (and Rewards) of Artmaking (Santa Cruz, CA: Image Continuum Press, 1993), 29.

It's a ironic to me that the original inspiration for the story was not ceramics, but photography. My main pastime is photography, and I took this advice to heart and started being as prolific as possible, which is something that digital photography has made easy and compared to film, inexpensive. It was a great relief to just accept that the first attempts at anything are going to be terrible and that failure was a necessary barrier to entry of getting good. Ten years, and tens of thousands of photos later and I've gained a lot of experience and produced some work that I'm proud to call my own.

I believe it was Henri Cartier-Bresson who quipped (or at least has had it attributed to him) that "Your first ten thousand photos are your worst."

I've found that using digital to gather new skills is terrific, but yet I find some of the work I am most satisfied with is analog; I believe it is mostly down to my own lack of self discipline - when shooting digital, exposures are free and hence I shoot lots and lots.

When out with my Texas Leica (A Fuji G690BL, a 6*9 rangefinder), getting eight exposures to the roll, I take those extra couple of moments to ensure I get it all right.

Looks like I have been pwned; thanks for pointing that out. Guess there was a reason that no good footnote existed in my memory for the origin of the anecdote.

Part of what stuck out to me, though, was that the anecdote aligned with my personal experiences of things that were once difficult until I ended up having to do them everyday for one reason or another.

But you're right, that's still a far way off from there being some actual study or otherwise repeatable exercise to show this in a clinical setting for learning new skills.

The specific anecdote may have been fabricated, but the principle is sound. An example is the marshmallow problem[1], where a group is given some materials and is asked to build, under time pressure, the tallest tower they can with a marshmallow on top. Adults generally fare poorly because they don't experiment enough, building a tall tower and placing a marshmallow on the top as time is running out, only to have the tower collapse under the newly introduced weight. Children often do much better because they start with small, simple structures and iterate quickly.

[1] https://www.ted.com/talks/tom_wujec_build_a_tower?language=e...

I don't know if that is really the same principle as the pottery anecdote however, it's not about experimenting but a narrative enforcing the concept 'practice makes perfect', related I suppose but not the same.

And anyway the pottery principle is not really sound either - I can suppose that the group tasked with producing a pot a day produces a better pot at the end than the group that was given a long time, but let us assume pot-makers both extremely skilled - one is tasked with making a pot a day for 30 days, the other making a pot in 30 days - which pot under those conditions will be better? The pottery principle is only interesting in explaining how to build a skill, but does not have anything to say about what to expect from those who have already mastered a skill.

The pot story is only valid if learning happens.

You can make the same very bad $creative_product every day indefinitely without improving at all.

Which is why there has to be at least some assessment and feedback. That's the big benefit of having a teacher, mentor, and/or the feedback of peers, customers, or an audience.

If you have a mediocre talent they'll steer you towards making the most of it. If you have exceptional talent their feedback may be wrong or misleading, but it should at least make you think more deeply about your relationship with what you're doing.

You can't assess your own work realistically unless you have something to compare it with, and the critical skills to understand which features matter.

And in relation to programming, entrepreneurship, etc. getting basic experience doing "the full pipline" matters. Releasing _anything_ gives you experience in preparing _something_ for release, whereas if you tried making a perfect program you would miss out on what matters early on for an eventual release and be able to coordinate those for your next product.

There have also been discussion about the same thing happening in music and science. That is, the people who produce the best work also produce the most work, and a lot of that work is bad. But some of it is very, very good.

Perhaps related to Sturgeon's law: https://en.wikipedia.org/wiki/Sturgeon%27s_law

Which is much like the Harvard or Yale study (it's usually one or the other) that shows people with specific goals and an action plan do ten times better than those without. Nice to know, except, it's all made up: https://www.peer.ca/Singles/MM255.pdf

There have of course been studies on goal setting and achievement (one of which is mentioned in the above pdf) but while they show an effect, they don't show the spectacular results of the made up study.

I think this rings true for learning. Early on in the learning process people need to focus on just doing a bunch of stuff and failing quick and then looping back to the beginning. Focusing on perfection with no foundation, in my experience is usually a surefire way to create things of lower quality

How hard did you look for that evidence?

I looked for it before and reached the same conclusion -- it is just a made-up story.

These are the same pots they boil the frogs in.


having turned to boiling the stone after exhausting all their methods of drawing blood from it


I think there needs to be a balance. If we want to keep talking about pots at my workplace there are people who produce the same pot quickly but never ever improve. Then there are others who talk about great pots but never make one. And then there are some that produce a little slower but each pot gets better. Depending on the situation probably any of these approaches makes sense sometime.

I've heard a very similar story but with a photo class at UF from James Clear's Atomic Habits. Still, very interesting outcome, although I can't say I was surprised based on the odds. Thanks for the share.


I’ve heard this lil story before but honestly both strategies are really dependent on the situation.

There might be situations where’d you want to continually churn out pots. In other situations, pressure is really high, and you have one shot to get it right.

Both strategies depend on the context. If anything, the best approach is to figure out which strategy is needed for the given situation. I would imagine, strategy of churning out pots is the most common one.

But safety critical systems certainly need that pot to be right the first time otherwise people die.

Yea, sometimes if the stakes are high enough you may have to get it right without multiple attempts.

Depending on your time constraints, the tips given here seem to apply particularly well: find proxy problems that allows you to learn without as much hardship would be a good idea, as well as the other strategies of breaking it down, etc.

Sometimes time is not on your side though, and you have to get it right without time to practice on proxy problems (at least I believe this can occur).

Then you can use what I call it the 'Kitchen sink' approach: grab a bunch of tools, a bunch of approaches and start digesting your problem through as many viewpoints as possible. If your problem has safety implications and you can verify it, then well enough. Otherwise you make an attempt if you are sufficiently confident in your solution; and take some kind of NOP otherwise (if a guaranteed 0-return NOP even exists).

Also, if you're solving something while time constrained, you may need to reflect afterwards if you could have either prevented the time constraint or prepared better somehow.

In general though, there's hope in the sense that if something is verifiable or approximately-verifiable you can approach good solutions with time. At least I have high hopes of always finding a solution given enough time (i.e. "You're not good enough" does not exist).

That's only not applicable if your time is finite or in the same vein you need to improve a skill to apply a series of finite-time decisions. Eh who cares about finite time anyway? :P

(Yes, in reality everything is limited but there are plenty of tasks you can take your time with...)

The pot challenge is one group is they get graded just on number of pots made vs. the other on a single pot they can submit. The group trying to perfect one pot ends up making worse quality pots than the quantity group because the quantity group ends up getting way more practice.

That anecdote gives me lots of hope. I hope it's accurate! :)

One thing to note about the pot challenge - it works because making a pot is a physical skill that improves with repetition in a situation where mistakes are really obvious. If you were to apply the same principle to something else it might not work at all.

If you just write a huge amount of code rather than examining what's good or bad about code you wrote, you'd probably end up writing the same bad code over and over again. Seeing where improvements can be made is sometimes really not obvious and can feel like you're going backwards. For example, learning where functional programming applies instead of writing a class for everything. You need to be able to understand why something is better for simple repetition to work.

Most valuable things I did not learned at university:

* Ignore whole craze toward being cool, participating in random competitions, chasing opposite sex

* Keep detailed notes of your days, who did you meet, what did you learned?

* Don't worry too much about acquiring every possible new skills that you come across

* The most important part of the textbook is exercises and that's not because there would be tests. If you really want to learn something, you need to do exercises!

* Write down import concepts you learned, new insights you developed. The process of writing down to explain to someone or yourself improves learning by an order of magnitude.

* Avoid depth-first search. Not every chapter, every book, every subject must be learned in all its gory details.

* Most textbooks are written by people who have little passion for that subject and they just want to show off their expertise. If you think you are wasting time, dump that textbook sooner than later.

Sounds like you could've used a harder course then, if you picked something that suited you, you wouldn't be able to get through it without most of these.

I _think_ he's saying he learned them, just not at university, or in spite of his time at university...

What did you achieve ? Where are you now in your professional life compared to your early colleges ?

Totally agree. I remember the first days of Algebra at university and you couldn't understand anything what the teacher was saying. Some freaked out as if they didn't know it now, meant they will never understand it (fixed mindset) and some thought "hell, I don't get it but I'll probably understand it once I studied it for a while (growth mindset).

In high school, smart students can often get away with not studying. In university, your attitude and mindset towards failure and learning becomes much more important.

> In high school, smart students can often get away with not studying. In university, your attitude and mindset towards failure and learning becomes much more important.

In high school I rarely opened the textbook and did fine. I ended up on academic probation my first semester in college because I had no idea how to study (or even that I had to study). While it was a rough first year, it was definitely needed.

this was me too. School was easy, I guess the real world is hard. I am still figuring out how to learn.

Sadly my course at university was too easy - most of the times i could easily wing the exams, prepare for a presentation day before, and do the same thing to the project - and get equivalent of B.

Professors were also good at teaching, which reduced the need to study at home even further.

It hurt me in the long run - i am really bad at putting in effort unless something catches my attention(thankfully programming can totally absorb me), and i quite frequently 'wait for the spark'(walking helps with that a lot).

It is unfortunate that many smart people go through their life without being truly challenged to work hard and develop these skills. It is often too easy for us (excuse my pride) to coast by on our ability to grasp material quickly and intuitively, yet ultimately feel dissatisfied as we know we didn’t work that hard at it. The only way I have found to overcome this is to engage in rigorous study with those who are better than you. In some ways I think many of the elite schools in the US do a disservice to their students by coddling them with inflated grades and subjective assessments. Having experienced both, I far prefer the brutal and objective assessments of difficult midterms and finals found at large public universities. If you don’t have access to such an education, then start by reading the original works of great thinkers. Take courses at the best school you can find. Online is ok, but don’t neglect the work. Find professional work with peers that challenge you. Being surrounded by smart people who work hard will change your perspective on what is possible. Procrastination is just one form of self-sabotage which allows us avoid confronting our own limitations. There’s no shame in turning in a crap project because you did it the night before, but it would be a catastrophe to spend weeks pouring your heart and soul into a piece and still have it be garbage! The reality is that many hard things require lots of practice, and you won’t always nail it. Laugh at your mistakes, throw it away, start over, iterate and improve. It’s ok to fail, it’s not an indictment of your potential. Great projects may start with inspiration from a long walk, but they also require lots of editing and refactoring. The important thing is to start the thing and keep working at it, keep chipping away at the small pieces until you get there.

>> Laugh at your mistakes, throw it away, start over, iterate and improve.

Nature plays the same game, I believe.

In addition to mastering the field of study that interests us, mastering our own minds may help us get better results.

> The advice to break a hard problem down into simpler pieces good, but I feel like that is often difficult without proper domain knowledge. In many cases, knowing how to break apart a problem like that is how you become an expert in the first place.

No, you don't always have that choice.

What you do is you break it up, best you can, then try to build each part. If that doesn't work, you break it up differently.

> In many cases, knowing how to break apart a problem like that is how you become an expert in the first place.

Funny, I had this notion that experts are most of the time better at avoiding deadends. Subtlety and patience. Noobs are impatient and depth first and lose hope.

A teacher who recognizes and corrects your subtle misunderstandings is ideal, but in >3 degrees, I've never had one. Though I have played that role with guitar and computer science students, so they do exist. I guess.

Breaking down problems is obvious and known advice, but very helpful, especially when you are lost in the weeds, can't see the forest for the trees, etc. Having it as "a system" helps self-management. Disagree about the importance of touch-typing.

Grammar snark (for an article about writing): "Sometimes it will be obvious what you need to improve, sometimes it won’t. When it doesn’t, ..."

when it doesn't obvious to you

This was my problem at university. It was way too easy for me, and I didn't get challenged until the final thesis project, which then took way too long and essentially failed even though I did get a passing grade. Real-life work does present complex problems though, and I am basically not capable of tackling them, even though I am smart enough to solve them once someone else has divided them into smaller problems.

I agree in the main . Specially about breaking up hard problems often being a retrospective advantage. I think simplifying a problem by removing details, solving that and then wondering about the differences is pretty effective. Helps you understand what you’re confused about.

That's why they say "one learns to learn at university"

totally agree, I think when I confront a new complex system, let's say AWS Cloud, I wish there would be a page or tutorial where all the building blocks would be stated up-front, so I agree with you that identifying those building blocks are crucial, and a good teacher or good documentation should help putting that information up-front then go into details on how those building blocks relate to each other.

My biggest realization about doing hard things is that I needed to let go of my intellectual entitlement. Just because something is (or seems) effortless to others, doesn't mean it will be the same for me.

Part of this entitlement stemmed from a (now eroded by bitter experience) belief that I'm somehow a faster learner than normal, that _I_ don't have to do the work.

For example, about seven years ago I wanted to learn Calc I-III on my own. I went down the usual, lazy, intellectually-entitled route of watching lectures and YouTube videos online without doing a single exercise.

A year later, guess what? I couldn't remember jack-shit. Moreover, I couldn't solve problems, which is basically the reason I was learning math anyway. Any bystander could have predicted this outcome, but I was blinded by my own entitlement.

Now, after being humbled (here and elsewhere, e.g. in learning to play music by ear), I realize that there's honor, even long-term efficiencies in following every step the great teachers of the past have laid out, in moving slowly albeit with rigor and confidence.

I resumed my math study with Geometry 101, the absolute basics, using a book of 5000 (short) exercises. It probably took me three times as long as Calc I-III lectures combined. But I realized something — I found more joy in doing the exercises, in doing things the _right_ way, than I ever had in watching lectures.

>Just because something is (or seems) effortless to others

My favorite part of skate videos growing up was at the end when they showed all the wipeouts and crashes. They hurt to watch, so much, but they always drove home the fact that it took a lot of painful and frustrating failures before the guy landed that really smooth 35 stair grind.

The point it, things often seem effortless to others but that's just cause you're not really seeing the effort being put in.

> Just because something is (or seems) effortless to others, doesn't mean it will be the same for me.

I think it's also important to remember it is rarely effortless to others. You just don't see the effort. I was fortunate enough to hang out with some people in college who were valedictorians at their high schools, and would generally be considered smart. They ended up graduating college with 4.0s. Since I hung out with them all the time, I got to see just how much they worked at it. They took amazing notes, and studied all the time. We didn't have a name for it then, but they essentially did the Pomodoro technique to pull all nighters studying for big exams.

Seeing them definitely helped me realize that getting through hard problems is work, and requires time. Thinking time, studying time, and practicing time. Do some things come easier to some people? Sure, but almost everyone has to put in the work at some point.

As an aside, not understanding how much work goes into something is common in sports. People see Michael Jordan hit the final shot or Tiger Woods hit an amazing shot out of a bunker, but do not realize they have probably practiced that shot hundreds if not thousands of times.

As much as it hurts me to believe as much, I'm confident that there really are people for whom at least certain things are "basically effortless". I've seen this occur around my peers, especially with music, where some (who already play piano but only by notes) learn to play by ear in a summer, but others are still struggling after five years of daily practice.

Absolutely. There are definitely people where certain things just come easier. You mentioned music, which I have seen. Same with athletics. But even those people often spend way more time practicing than they are given credit for.

> long-term efficiencies in following every step the great teachers of the past have laid out, in moving slowly albeit with rigor and confidence.

I always return to this [0] diagram when thinking about learning. Am I taking shortcuts that'll actually stunt my ability to progress further in my development. The "Expert Beginner" is a dead-end development wise - it might be a perfectly reasonable place to end up, but not the right way to expertise.

[0] https://daedtech.com/pics/ExpertBeginner.jpg

>A year later, guess what? I couldn't remember jack-shit. Moreover, I couldn't solve problems, which is basically the reason I was learning math anyway. Any bystander could have predicted this outcome, but I was blinded by my own entitlement.

I'm a third year university student; I did all the exercises set last year to do well in the exam and over the course of the whole year. And now, only one year later, I can't remember how to do some of the most fundamental problems. I can remember the derivative and integral of trig functions, but the method of doing even moderately challenging exercises with them I don't remember well and I'd need to look it up. I don't know what that signifies, but I have the impression that even just doing the exercises doesn't last long unless you use what you have learned semi-regularly at the least.

To add to your point, I think this reinforces the value of spaced repetition learning. It's been show to been one of the best ways to actually retain information. So, as you said, just doing the exercises only gets one so far. You'll need to either use what you learned or at least do refresher exercises to better put what you learned into memory. The benefit is that you may be able to do these refreshers and greater intervals over time, effectively retaining the information longer.

For me personally, there does seem to be a tipping point where what I learned really sticks in my brain and degrades much slower. However, I can't seem to pinpoint where that point happens or if it is even consistent. There are some coding concepts I never forget, and some that seem to leave me within a month.




What was the book of 5000 geometry exercises? I have students who could benefit from such a thing (and I might too!).

Geometry: Seeing, Doing, Understanding by Harold R. Jacobs

Preview: https://books.google.de/books/about/Geometry.html?id=u5o6DwA...

You can purchase a complete solution manual separately, which is very handy.

> My biggest realization about doing hard things is that I needed to let go of my intellectual entitlement. Just because something is (or seems) effortless to others, doesn't mean it will be the same for me.

The movie Goodwill Hunting has a scene that describes this [0].

[0] https://www.youtube.com/watch?v=RKu_QQVHJLA

This more or less matches my own system. Some additional notes:

* When creating great work as an expert, you will be working down the ladder of abstraction (e.g. for writing–coming up with a concise high-level vision and then progressively expanding it down to the level of characters on a page)–this is the most efficient way to make anything, since you can sanity check your work at higher levels to avoid expensive rewrites at lower levels. However, when learning, you should learn subskills in the exact inverse order (start from the lowest level–how to type keys–then work upwards). Mastering subskills in this order maximizes the feedback signal you get while learning–if you can't write a paragraph coherently, it is very difficult to determine how well you're doing at developing your authorial voice (or whatever).

* Time spent practicing a skill only makes you faster / more robust at the method you already know; it doesn't lead you to improve your methods. So spend half your time actually performing the skill, and half the time analyzing your work / comparing to known good examples / planning how to improve (and, really, half of that time should be for improving your tools for analysis and comparison...). If you fail to do this kind of meta-work, 10000 hours of practice or whatever will just get you a fast, robust system for producing garbage.

* Assuming you're following an intelligent process for learning the skill (see previous points), the most likely way in which you will fail to learn it is by getting disinterested or discouraged and giving up. It's essential that you try and structure your learning process in a way that yields intermediate feedback and some satisfaction for improvement, and pay attention to both 1) reducing the parts of the process you dislike and 2) figuring out ways to make it enjoyable (including figuring out how successful other people have managed to derive enjoyment from the activity).

Item #2 relates to reflecting on your work, Reflective Practice. Give Donald Schon's book The Reflective Practitioner a read (or heck, the Wiki page). It deals with being able to rise above work and improve how you work.

“We shall not cease from exploration, and the end of all our exploring will be to arrive where we started and know the place for the first time.”

~ T. S. Eliot

I used to make songs, not so much any more. Creating a song is hard you have to come up with both a good melody and good lyrics.

What seemed to work great is I tape-recorded myself playing and singing the initial version of the song. Then I played it and sang on top of it, even doing multi-tracking sometimes.

I found it was easy to come up with new words and new adjustments to the melody while singing on top of an existing version. Why? Perhaps because I didn't need to spend energy trying to remember both the old version and the new version. The tape-recorder remembered the old version, so I was not afraid of losing it.

I have had similar experiences - I find it easier to edit things than to create them in the first place.

His use of loops just seems like an implementation of breaking a problem down into smaller components. If I wanted to learn to learn a difficult skill, such as writing a decent novel, I'd break it down as follows:

1) Research what skills I'll need to develop. At my current stage of learning I don't know what I don't know.

2) Figure out a path to start developing skills. This might be writing a small story every single day while also reading books/guides on how to develop as a writer. I'm still writing daily.

3) As I'm becoming mor comfortable writing anything I now need to develop skills on writing specific things. How do I flesh out a character, how do I describe settings, etc. I'm still writing daily.

4) Once I've figured out individual building blocks I'd then teach myself how to construct them together. What elements do stories contain? How do I flow between small sections to weave a larger tale? I'm still writing daily.

I'm sure as I become a more knowledgeable and skilled writer I'd identify other areas I need to work on, skills to develop, etc. It all comes down to identify small blocks and build from there.

For a long time I've had this idea about creating a website where this type of idea is expressed. I envision it to be some large hierarchical tree like structure (not unlike the ones you see in games like FInal Fantasy) where you pick a topic you want to learn and it gives you the basics to learn and then once mastered allows you to goes deeper by diverging into specialised categories.

I've prototyped this mentally too. If I were going to do it, I think I'd write myself a modification to a Wiki engine that can detect when links only go to simpler things, and highlight those. (You don't want to "ban" links going up to harder things, but you may want to isolate them in a dedicated section or something.)

You might be able to bootstrap off of wikipedia content.

The thought that provoked this in my own head was the observation that Wikipedia is virtually useless for learning anything mathematical because so many of the links on any given article head "up", rather than "down", and a casual user can't figure out which is which.

Sounds great! Something I found lacking in school was that nobody could take "I want to do X" and turn it into "You should learn A, B, D, and R", nor the reverse.

then you should work on that website a little every day, while researching how to make it even better :)

It sounds like great advice, I just wish I had some properly hard things I needed to apply it to, rather than the multitude of what ought to be simple things of which a few unexpectedly and inexplicably turn out to be grossly disproportionately difficult to do for no very good reason.

I have also experienced this phenomenon. Why do you suppose we come to these surprises, and why do you suppose we experience them?

Is it because we are confident? Or because we lack sedulity? Or because our analysis was incomplete?

Is the surprise time consuming because we want/expect it to be easy? Or because we are focused on a different problem really. Or because our focus was interrupted.

sedulity: diligence, dedication

good word!

Basically this is Descartes’s Discourse on the Method

(2) The second ·was· to divide each of the difficulties I examined into as many parts as possible and as might be required in order to resolve them better. (3) The third ·was· to direct my thoughts in an orderly manner, by •starting with the simplest and most easily known objects in order to move up gradually to knowledge of the most complex, and •by stipulating some order even among objects that have no natural order of precedence. (4) And the last ·was· to make all my enumerations so complete, and my reviews so comprehensive, that I could be sure that I hadn’t overlooked anything.


I conquered my own process by eventually realizing I could approach it exactly like a computer program. I architect how I am about to work. Now instead of just nebulously working I always know exactly what I'm working on. This frees my mind to focus on the task at hand and if I get sidetracked I can just look at my current goal and process list I setup before I started working, that I thought out rather well, and it gets me right back on track.

How often do you get interrupted at work?

It used to be just awful, at least 2-3 major focus shifts per day which I got used to. Now rarely, as I realized I am at least 2-3x more effective if I work on the same task for at least a few days at a time. I can ramp up to an amazing level of momentum if I am not being randomized.

One way I accomplish this in programming is to write down what I wish I had. Like ok if I had a magical function that did xyz or if my data just happened to be in this easy to consume format, etc. works pretty well when stuck on a difficult problem.

That's like TDD.


I am a 4th semester CS student from Germany and still don't grasp recursion, even though I already took the data structures & algorithms courses. If you did have something like a magic moment where it made sense to you, please enlighten me as I would really like to truly gain an intuition (and implement a parallelized msd-radixsort for learning-purposes because I failed to do this assignment yesterday).

I had problems with recursion too, I think because the mind at first tries to follow in an abstract way and gets lost. You need to switch to concrete thinking, so you need specific things that you can rely on, these 3 things are solid, and you can rely on them if you get lost in recursion :

1) There is always an exit condition ( or it would run forever , we never want that)

2) There is always a value that changes and it is passed to the next execution, or otherwise it wouldn't make sense it would be always the same execution and the exit condition would never trigger.

3) Think like frames of a movie, in paper o whiteboard, write a table with a column for every variable and a row for every step, my first programming teacher taught me this, and 19 years later it save me in a white board interview, it helps to calm down and just go step by step seeing how values evolve.

So these 3 together, allow you to think in how the values change in every step, and how to get to the point that the exit condition is meet.

Hope it helps! good luck!

Just my two cents, I really grasped it when I read through Structure and Interpretation of Computer Programs and followed the online course from MIT. It's meant to be a first year course but it's done in Scheme (a kind of lisp) and it's very enlightening to see such a different way to program.

It forces you to learn recursion since for most of the book it only uses pure functional programming with no mutation, so the only way to do loops is with recursion. Overall I would say it gave me a strong base to understand not just recursion but functional programming which has helped me pick up new languages more easily during my career.

Also I used Clojure instead of scheme to do the exercises. It's a wonderful modern lisp that works on JVM and can land you a job. The examples usually work with minor modifications and I would say it's worth it to learn.

I'll pitch in with my own intuition; the easiest way to understand it is to view it as a call stack. Using this example function:

  function RecFunc(n, max) {
    let result; // intialize the return variable
    if (n < max) {
      result = RecFunc(n + 1, max) // the recursion
    } else {
      result = n; // the exit condition
    return result;
  RecFunc(0, 3);
When you call the function, we descend down the stack until it hits the exit condition. Notice that `result` is undefined in the upper levels of the stack; when `n` is equal to `max`, the function is finally able to assign a value to `result` and exit:

  | RecFunc
  v   n: 0, max: 3, result: undefined
  |   RecFunc
  v     n: 1, max: 3, result: undefined
  |     RecFunc
  v       n: 2, max: 3, result: undefined
  |       RecFunc
  v         n: 3, max: 3, result: 3
Now that the exit condition has been met, we go back up the stack, returning the result at each step:

  ^ RecFunc
  |   n: 0, max: 3, result: 3
  ^   RecFunc
  |     n: 1, max: 3, result: 3
  ^     RecFunc
  |       n: 2, max: 3, result: 3
  ^       RecFunc
  |         n: 3, max: 3, result: 3
Notice how the call stack resembles stepping through a for-loop:

  var result = 0;
  for (var i=0; i++; i<=3) {
    result += 1;
If you really want to see a mind-blowing example of recursion, step through an implementation of the `compose`[0] function some time. :)

[0] https://github.com/reduxjs/redux/blob/master/src/compose.js

I remember what made me click was using a bit of assembly.

If you imagine your code as a sequence of instructions, recursion is basically a `JMP` to the start of the stack again, normally with different values.

Once a condition is met, instead of jumping back to the start, it returns something. That condition then repeats itself inside all the repetitions eventually returning the value to the original caller.

  # imagine we're recursing to subtract to zero

  1. call function subtract with 10 (set x = 10)
  2. subtract x by 1
  3. if zero, return 0
  4. else return the result of calling the function with x-1 (jump to 2)
Once I realized deep down at the CPU level it's all a sequence of instructions, recursion is nothing but moving the pointer. With higher level languages there's a bit more involved, but the gist is the same.

The best way I've found is to imagine a physical tree, and perhaps go outside and stand in front of a big one...

Notice there are 2 types of parts:

  - A leaf, which is the end (has no children)
  - A branch, which may have leaves or more branches (has children)... and because a branch can have more branches, this is recursion, so we abstract to a 3rd type of part:
  - A node, which could be a branch or a leaf...
Imagine if you were blind and had to feel your hand up the stem, and when you reach a node, you'd move your hand up the node to check 'is this a leaf, or a branch' If it's a leaf, you mark it; but if it's a branch, you move your hand along the branch and do the same check for the next nodes 'is this a leaf, or a branch'...

  function int getNumLeaves(Node node):
    foreach childNode in node:
      if childNode.IsLeaf(): leafCount++
      else: return getNumLeaves(childNode) // NOT a leaf -> check this branch's children

  print getNumLeaves(tree.stem); // (start with the outermost 'node')
The pseudocode above could have errors, but it's simple enough to get started for understanding;)

Have you seen the movie 'Inception' [0] ? This is the idea behind recursion: you are in some context, then dive into another (similar although not identical) context, then dive into another (similar although not identical) context, etc.

The 'reality' is the top level context.

You dive down to level 2 context by falling asleep; that would be the recursive function call.

In that dream, fall asleep and enter level 3 context. You are now recusrsively falling asleep.

In the movie, the characters wait for a signal to wake up and going one level up. This is the 'stopping condition' of a recursive call.

You can also see that as Matryoshka dolls.

Regarding the 'Inception' movie that's funny, because it popularized the '-ception' suffix to describe a recursive phenomenon [1]

[0] https://www.imdb.com/title/tt1375666/ [1] https://en.wikipedia.org/wiki/Inception#In_popular_culture

Sometimes the best way to grasp an abstract concept is to translate it to a real life example (usually a stupid example). So I'll try to explain recursion to you with an <stupid> example, let's say that you want to take a shower, but you have your pijamas and your underwear on. What you must do is take all your clothes, one by one, and then get into the shower and take the bath. You first take off your pijama shirt (you have 2 pieces left), you then remove your pijama pants (1 piece left) and finally you remove your underwear. Notice that this is a repetitive pattern that must be repeated a couple of times in this case (in other case, you might have more clothe pieces, so you will do this process more). Finally when you're naked, you ask yourself: do I need to remove another piece? NO!, you reply, and you proceed to go and take the bath.

In recursion, you have 3 main components: -A function that performs the same action a repeated number of times, except for when you meet a base case (end of the recursion) -A value that must be tracked and modified in order to perform the said action n times, and know when to stop doing it -A base case that stops the repeating action, and usually performs another 1 time action.

In our example, our components are: - Function <undress to take a shower> that performs the repeated action of taking a piece of cloth off. - Value tracked, which is the <number of pieces of cloth you have left to get naked>, and on each iteration or call of the function will be reduced by 1 (asuming you're taking 1 piece at a time). - Base case, which would be <when you have no pieces of cloth left to remove = you're naked> and you can perform the last 1 time executed action which is <take the bath>.}

Notice the importance of the base case, otherwise your program will keep iterating and the program will get stucked.

Hope that this helps.

I think they easiest way to grasp it is by writing simple examples, eg write a function that prints the last item in a list and returns the rest and then call it recursively to print the whole list. You can do it in about 5 lines in python or js and thinking it through often helps to grok stuff. I just did that myself and on the 5th attempt it worked(!).

I had two A-level maths teachers at school. One always started by getting the class to do a simple as possible example like the above before launching into more complicated stuff, the other started off explaining complex stuff. The first approach worked far better, with the second our minds just kind of glazed over.

There's something a little counter intuitive about it like your neurones have to wire up on the simple example before getting the more complex. Doing the simple stuff then sleeping on it and doing the complex the next day works better still I think.

My first time doing recursion was implementing an indentation level calculation for showing threaded/nested child comments in a mailing list display UI, one of my first web apps. The mysql table I had populated had an id and a parent and I just repeatedly queried the db for any objects that had the current item as parent, depth-first.

I didn’t realize that it was a threshold moment, and I didn’t even know if it was syntactically legal or allowed for a function to call itself (I had no formal CS training) but I remember struggling with the “how much should these child elements be indented” problem and eventually trying it and it worked; it was quite a rush for 14-year-old me.

Maybe try implementing something simple and straightforward that uses it, like a web front end that displays a directed graph of nested comments/message replies?

Recursion works when you can break solving a big problem down to solving a smaller version of the same problem. So, like, if you want to balance a heap, you can start at the root node, and call "balance" on the left heap and right heap.

So, each step needs to get you closer to the goal, working on a smaller problem, until you reach a base case, a really small problem that you don't solve in terms of recursion. You check for the base case, a really small problem you actually solve directly instead of handing it off to another recursive call, and you actually return your solution to the caller.

Recursion is simple: It is just a function calling itself. The difficult part is that it is not getting out of control (e.g. never stops).

To make sure your function will stop calling itself you need an exit-condition. So whenever you want to write a recursive function, simply start with a template like this:

  function myFunc(list) {
    // exit condition
    if (list.length == 0) {
      // What should the function do if the exit condition is true
    } else {
      // before recursion
      // recursion
      // after recursion
So basically you have to think about when your function aborts the recursion, what it does before the recursion (e.g. extract an element from a list), how the recursive call is different from the original call (e.g. the list got reduced by one element) and after what it does after the recursive call (e.g. push a modified element to a stack). By answering those questions you should be able to solve a whole bunch of recursive problems.

Before I learned this pattern, my recursive functions were a mess. Now, they all adhere to that very template and I find it actually fun to write recursive functions as there are some problems which are a lot easier to solve with them.

I suggest studying "A Regular Expression Matcher" by Rob Pike:


You just always start with the base case. It could be recursion is just so simple that your mistake is thinking there must be something complicated.

Also, if the algorithm is not tail recursive, you may be missing that there is an implicit call stack where intermediary results are pushed to.

Try the "Recurrence Relation" chapter of https://larc.unt.edu/ian/books/free/poa.pdf

Read "The Little Schemer"

If you enjoyed this then you'll likely find Claude Shannon's approach useful.


This is a very interesting philosophy. A few years ago, a former coworker and good friend of mine introduced me to an algorithm for solving problems. This is a slightly different purpose than doing something hard, but there are some interesting similarities. In my experience as an engineer in software and operations, this algorithm has never come in reach of failing me, and until I was introduced to it, my own system was seriously lacking even though I didn’t know it! You can be successful without it. But you can be so confident and efficient with it! The algorithm and it’s philosophy are described in none other than Zen and the Art of Motorcyle maintenance. I think there’s also an XKCD of it, Flowchart maybe is the name.

I'm partial to the Feynman Algorithm:

1. Write down the problem.

2. Think real hard.

3. Write down the solution.

Ha, I like this one! Actually these algorithms may approximate one another when generalized. Pirsig explores the philosophy more deeply, though; for example, generating a hypothesis: where does it come from, and is it possible to run out of hypotheses? Pirsig argues no, you practically can’t.

I concur.

Although personally, I use a somewhat modified version:

1. Find the closest person who knows more about what you are doing than you do. Then, for everything you can say about the problem, do so, out loud. (It is very important that you say it out loud and not just in your head.)

There is a very good chance that you are the person who knows the most about the problem, at least in the way you are presently thinking about it. This implies that you need to speak out loud about the problem, to yourself, and nobody else if necessary. Therefore, in order to make yourself take this step seriously, record your dictated thoughts (even if you never plan to play them back). This is a very important 'hack', because it simultaneously tricks your brain into thinking somebody is listening, causing you to take what you say with utmost seriousness (even though it might start out as non-sense), while at the same time giving you the freedom to say whatever you want (which is almost never the case when somebody is actually listening, since mutual intelligibility is a prerequisite for all conversation).

2a. Draw what you see in your "mind's eye" when inspiration strikes (when with a colleague, at the board; alone, on a blank, unruled sheet of paper). Do this for months, until you become fluent in a private 'diagram language' for describing your thoughts.

Similarly, utilize a private 'jargon language' to name things that don't exist yet.

2b. Start typing it all into org-mode, until...

3. ...you realize what the actual solution is. Then go do that.

N.b.: If you squint, everything I just said is nothing more than a generalization of what professional mathematicians do at the blackboard. I learned to think this way in undergrad in the math program, but it's equally applicable to any field IMO.

Disclaimer: This technique risks making you hopeless impractical and obsessive until it starts to pay off. And I have to admit, this is not really an algorithm for solving problems, so much as coming up with creative insights about problems. I think that most problems don't need some massive insight so much as dogged persistence and organization (in which case you should completely disregard this post).

Does this strategy apply to programming? Consider the xkcd cartoon[0] that Bonooru posted upthread. One possible realization of what the the "?" step in that cartoon could be: utilize my "conceptual" strategy to shrink the amount of time spent doing actual coding to a minimum. Doing this with abandon is surely dangerous and risks getting stuck in the first, trivial loop, but if you can find a way to iterate on paper...

Mathematics is the part of physics where experiments are cheap. -Vladimir Arnold

...then perhaps, by analogy: the kind of conceptual work I'm promoting here is the part of programming where the "inner loops" (that is, actual coding, like in the xkcd cartoon) are empty. Take this too seriously, though, and you may one day wake up in academia[1]... :-)

[0] https://www.xkcd.com/844/

[1] For example, AFAIK, Edsger Dijkstra prided himself on writing programs only with paper and pencil rather than at a computer.

I couldn’t agree more. That book changed the way I do my work and live my life.

This was the one, a facetious version of Pirsig’s algorithm: https://xkcd.com/627/

This is what I have concluded for learning: 1) Figure out a way to have feedback on what you are doing and improve on that. Basically training the neural networks in the brain. Of course the feedback you choose matters like "inner game of tennis" or "drawing from the right side of the brain" talks about using non-judgemental feedback and trusting your capability. 2)Choosing the difficulty of the task to train yourself. If too hard you will give up, if too easy no good or get bored, so always keep it at a point where it is somewhat hard.

Also thought people may find this article from andrew ng interesting: https://www.linkedin.com/pulse/20140320175655-176238488-lear...

Yes!! I got introduced to the concept of Double loop learning in a management class in College - and was able to apply it successfully after not being able to get the grade I wanted in some courses - then I realized that the issue was with what I was doing - not with how tight or efficient I was at doing it!

Couldn't recommend this more

Nice. I never explicitly realized this but this is how I always succeeded in doing hard proof-of-concept projects in a complex software product.

Single loop when I know the domain fairly well. And double loop in a complete new domain.

So, the question is: Are there other methods to approach problem-solving which gives positive success?

I changed recently the way I look at problems, instead of thinking I don't know, or I don't understand. I think that is more useful to think that I have a wrong model of reality, that way it helps to

a) Acknowledge that I might have already assumptions that need be questioned

b) Forces me to re-visit what I think I know

c) Realising that accessing the right model is "just" a matter of finding what building blocks are misunderstood or missing in my model.

I think the article suggestion fits this philosophy and it is a valid angle to attack a problem, in "model" terms "Find something that is like the hard thing but is easy" for me easy means, that is familiar to you meaning that is a model that you understand, meaning it is a model that you play and gives you the expected results.

Call me a hedonist, but I usually start with the most fun stuff that gets me some result soon (usually the part I already am good at). Then ideas come for the rest, the dark days I certainly procrastinate until I feel guilty enough to go on again. Works for me.

It helps a lot if you have an employer that gives you the time. There is no substitute for getting paid 8hrs a day to learn new difficult tasks.

It's actually the reason why some of my self-employed friends got a regular job again.

TLDR; The core idea described in article is to identify components that makes things "hard" and then apply each component in isolation to "easy" version and master that easy+one hard thing problem. After you do that for each component, you likely find thing isn't hard anymore. This is "single loop system". The "double loop system" applies to thing that you don't know what the "good" final state looks like. So you basically consider that as problem and apply single loop system to first find out the good final state. Then again apply single loop system to achieve that good final state.

This is insightful but claims are rather over-inflated. More formally thinking, if this system works then my first instinct would be to apply on np-hard problems or build machine with human level intelligence. The issue is that hard things are often hard because solution search space is extremely vast and achieving any level of predictability is difficult because there is almost always new information lurking in space you haven't explored yet.

To be fair, the article does explicitly call out that the system won't work for arbitrarily hard or impossible problems. That's addressed in the opening paragraphs, and again called out in step 4.4 of the single-loop.

Taking notes for my RL research..

First principle thinking comes to my mind after reading the whole article.

When writing, start from the conclusion and work forwards.

I think it is a habit to want to tackle difficult things that is learned through discipline likely fostered by parents that disciplined you. This is anecdotal though.

Writes article on how to do hard things : article is super hard to understand. F M L

great post.

Doing hard things 'isn't impossible'.

Doing hard things is time consuming and/or expensive.

As a side note, I find it interesting how non-engineers describe the reverse engineering process. I thought this was hard to understand.

did you just describe the OP as a non-engineer? https://www.drmaciver.com/

This guy is rambling. The key - just do it.

Change title to how to do "complex" and "complicated". Just stop saying that, and I don't like the algorithmic approach to this and the vaque-ness of the word hard

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact