Skip to content

Instantly share code, notes, and snippets.

@ResidentMario
Created September 5, 2019 21:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ResidentMario/e597a96bfacc78c42717701eafa3ea7a to your computer and use it in GitHub Desktop.
Save ResidentMario/e597a96bfacc78c42717701eafa3ea7a to your computer and use it in GitHub Desktop.
Some philosophy

Some thoughts on a part of coding challenges that I find difficult

...and what it means for my life more broadly.

After a couple of days of struggling with introductory Leetcode exercises, it's pretty clear that there is something fundamental to coding challenges that doesn't come to me naturally.

Doing well on a coding challenge means implementing a method that solves for all possible cases of the given problem with the given constraints as written. This means that all "normal cases" and all "edge cases" must be discovered and considered simultaneously—in advance of the actual algorithm design.

This differs from my typical workflow when implementing a new algorithm. My typical workflow is iterative. I define a narrowly scoped "normal case" version of the problem, and write an algorithm that solves that narrow problem. I then relax the constraints of the problem one step at a time, modifying the algorithm as needed to account for the additional cases.

This iterative workflow has the following advantages:

  • It has less mental overhead. It doesn't require understanding the entire system beforehand. This lets me go from thinking to coding in the minimum possible time. I like coding, and don't like thinking. =)
  • It is easier. It makes edge cases easier to tackle. I can address edge case correctness one-a-time, instead of all at once. Furthermore, writing a solution for a simpler case builds further understanding of the problem, leaving me better placed to solve the edge cases when I do get to them.

The direct workflow encouraged in interviewing has the following advantages:

  • It is cleaner and faster. Oftentimes when implementing a solution iteratively I end up with an architecture for the algorithm that doesn't extend to the edge cases easily, requiring refactor or even sometimes a rewrite to get an elegant solution.

Why have I historically worked in an iterative manner?

  • Cleanly algorithmic problems are rare in practice. Unless you are a bona-fida expert in a space, and the system in question is small, most real-life systems are too complex to able to confidentally address every possible case beforehand. The iterative workflow, or a "chunked workflow" that addresses the solution space in batches, is the only one that makes sense.
  • The domains I have worked in historically—data analytics, machine learning, muddling about with things in which I am totally uninformed—encourage development by way of experimentation.

Why is direct workflow preferable in coding challenges?

  • Coding challenges are concerned with "toy systems" with simple boundaries that can be mentally processed all at once.
  • Interviews are a 100% mental effort. Directly solving an algorithm, if you can handle the overhead, is strictly better in terms of speed. Of course, 100% isn't sustainable long-term once you're actually on the job...
  • The more experienced a programmer, the larger the systems they are able to hold in their head. It's an attractive albeit flawed analogy for how experienced engineers can more quickly build real-life systems based on real-life subcomponents that they've spent more significant times working with than more junior engineers.

There's something else going on, which has to do with who I am: my Freudian id fingerprint. I am fundamentally a "top down" thinker. I am good at fuzzy problems with inconcrete boundaries, I am good at understanding and building "natural" products and APIs, I am good at translating broad prioritization into specific tasks, and I am good at collaborating on asks. Hi.

Coding challenges are "bottom up". They are concrete, well-specified problems. The only conversation is one of specifying problem parameters. They require understanding subsystems in isolation, then building up from these basic building blocks. An example of someone that embodies this is Calvin. Or Ciara.

Top-down tasks that I enjoy include designing APIs, experimenting with user workflows, product feature design, and experimental implementations of whole systems. Bottom-up tasks that I don't enjoy include studying component specifications and/or tutorial documents, thinking about edge cases, and yes, coding challenges.

Of course good engineers can do both. My model of a 10x engineer, Dima, does both. But he's definitely a bottom-up kind of person, fundamentally.


The university system involves (and strongly encourages) bottom-up thinking, which helps explain why coding challenges are such a good HR fit. Whereas I am effectively 100% self-taught and have always approached problems in a top-down manner. Bottom-up design, neither comes naturally to me, nor is it something I have a lot of experience with.

At least I can elucidate why that is. :)


As I continue to solve coding challenges, I need to continue to emphasize this first bottom-up "system understanding" step of the approach. This will provide the largest immediate gain in my outcomes.

In a broader sense, following the sudden twist in the arc of my career of this chapter of my life. It's pretty clear that I understand the top-down part of the software engineering well (although there is always room for improvement!), and the next couple of years are going to be about becoming better at the bottom-up aspects of it, because if I want to actually get to engineer more complex systems, that's what I need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment