I'm Launching Street-Smart Coding: 30 Lessons to Help You Code Like a Pro (the Roadmap I Wish I Had Starting Out)

Street-Smart Coding cover
Street-Smart Coding: 30 Ways to Get Better at Coding Without Losing Your Mind

I spent five years in college learning to code.

A stupid dissertation delayed my graduation. But that’s another story.

Most of my five-year program didn’t prepare me for real-world coding. My real coding journey began at my first job, with one Google search: “how to get good at coding.”

I found a lot of conflicting advice:

  • “Use comments”
  • “Don’t use comments”
  • “Do this”
  • “Don’t do that”

Arrggg!

It took years of trial and error to learn what worked.

I had to survive on-call shifts, talk to stakeholders, and say “no” politely. More importantly, I had to learn that coding takes more than just syntax.

That’s why I wrote Street-Smart Coding— a roadmap of 30 lessons I wish I had when I started. For every dev who’s ever typed “how to get better at coding” into Google or ChatGPT. (Back in my days, I didn’t have ChatGPT… Wait, I sound like a nostalgic grandpa…)

Scrolling through the first pages of Street-Smart Coding
Preview of the first ~12 pages

Inside “Street-Smart Coding”

This isn’t a textbook. It’s a battle-tested guide for your journey from junior/mid-level to senior.

Some lessons are conventional.

Others were learned the hard way.

And a few are weird.

One lesson comes from a TV show. Nope, not Mr. Robot or Silicon Valley. That’s on Chapter #29. It will teach you about problem-solving.

You’ll learn how to:

  • Google like a pro
  • Debug without banging your head against a wall
  • Communicate clearly with non-tech folks

…and 27 more lessons I learned over ten years of mistakes.

Now they’re yours.

Get your copy of Street-Smart Coding here and skip the years of trial and error. For launch week only: Pay what you want—even $1 or $2.

My 400 Daily Posts Reflection

Writing 400 daily posts gave me momentum as a writer.

The first 100 posts were training to find ideas. The next 100 proved I wouldn’t run out of ideas. The next 100 tested my discipline, I wrote even when tired. This last 100 gave me trust to keep going.

In the last 3 months, I released a book, Street-Smart Coding and I shared the behind-the-scenes:

Promoting my book won me my first hater, a milestone in the writing journey.

But beyond criticism, writing daily gave me something more lasting: “the time capsule” effect.

And after many posts, I can see what I was learning each day years ago. I even started to write some “on this day” posts. Here’s the last one I wrote.

That’s a gift for future generations: reading what grandpa wrote 20 years ago.

My most-read and favorite posts

Here are some of the most-read posts from the last 100 days:

Here are my 100-post, 200-post, and 300-post. Next milestone to celebrate: 500 daily posts.

Friday Links: Confessions, manager pendulum, and the junior hiring crisis

Hey! Here are 3 reads (plus a funny bonus) I found interesting this week.

#1. After being afraid of sharing them, here are the confessions of an uncensored coder (10min). I agree, we don’t have to learn everything about everything. And I have to confess I don’t fully understand Blazor, in spite of working with it for almost a year.

#2. Most companies only offer two tracks for coders. You either stay as an Individual Contributor or join the Management side. Switching between the two is called: “manager pendulum.” But AI might be breaking the pendulum (10min), creating hybrid roles. Or maybe it’s just an excuse to get rid of the role and the compensation?

#3. It’s easier than ever to start coding. But it’s getting harder and harder to break into the market as a junior coder. We’re in a junior hiring crisis (10min). AI seems to have a lot with it…And just in the past few weeks, someone in the same situation reached out on LinkedIn asking for advice. I didn’t have much to say.

Bonus: What if we let AI replace our bosses? Here’s replaceyourboss.ai. The funniest line I got: “Let’s cut the single-use cups but keep the private jet for strategic mobility.”


On my blog, this past week, I shared about 4 AI issues I’ve collected (2min) and 4 lessons I learned while fighting next to my mom with a chronic disease (3min). Feel free to skip that last one if you only want to read about coding. I won’t get mad.


(Bzzz…Radio voice) This email was brought to you by… My latest book, Street-Smart Coding: 30 lessons to help you code like a pro, from Googling to clear communication. It’s the roadmap I wish I had moving from junior to senior and the one I hope helps you too.

See you next time,

Cesar

Advent of Code Day 3: Calculating the Joltage of Batteries

On Day 3 of Advent of Code, we’re finding the joltage of a bank of batteries to power an escalator.

Elevators are out of service and the escalator needs the batteries with the higher joltage.

Finding pairs of batteries

I use brute force to find all battery pairs.

Two for loops didn’t feel old-schoool. So I borrow a LINQ query from this StackOverflow answer.

static class Extensions
{
    public static IEnumerable<(T First, T Second)> Pairs<T>(this IEnumerable<T> self)
    {
        return self.SelectMany((fst, i) => self.Skip(i + 1).Select(snd => (fst, snd)));
    }
}

Calculating the joltage

Once we have the pairs, I need two methods to calculate joltage: for a pair and for a bank.

static int FindJoltage(Bank bank)
    => bank.Batteries.Pairs().Select(FindJoltageOfPair).Max();

static int FindJoltageOfPair((int Battery1, int Battery2) pair)
    => pair.Battery1 * 10 + pair.Battery2;

Here’s my full solution:


var allBanks = new List<Bank>
{
    new Bank([ 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1 ]),
    new Bank([ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9 ]),
    new Bank([ 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 7, 8 ]),
    new Bank([ 8, 1, 8, 1, 8, 1, 9, 1, 1, 1, 1, 2, 1, 1, 1 ])
};
var totalJoltage = allBanks.Select(FindJoltage).Sum();
Console.WriteLine(totalJoltage);
Console.ReadLine();

static int FindJoltage(Bank bank)
    => bank.Batteries.Pairs().Select(FindJoltageOfPair).Max();

static int FindJoltageOfPair((int Battery1, int Battery2) pair)
    => pair.Battery1 * 10 + pair.Battery2;

record Bank(IEnumerable<int> Batteries);

static class Extensions
{
    public static IEnumerable<(T First, T Second)> Pairs<T>(this IEnumerable<T> self)
    {
        return self.SelectMany((fst, i) => self.Skip(i + 1).Select(snd => (fst, snd)));
    }
}

Et voilà!

Advent of Code sharpens your coding skills. But coding is more than typing symbols fast. It’s also about teamwork, collaboration, and many skills I share in my book, Street-Smart Coding: 30 Ways to Get Better at Coding. That’s the roadmap I wish I’d known from day one.

Get your copy of Street-Smart Coding here

Advent of Code Day 2: Finding Invalid Product IDs

On Day 2 of Advent of Code, we’re helping the Elves find invalid IDs.

I considered a string-based solution, but that felt like cheating. So I tried a “numeric” one instead.

Let’s start with a bottom-up approach.

Finding if a product ID is invalid

First, I count the digits of a number, then split the number in half using powers of 10.

I borrowed this StackOverflow answer to count digits.

And since a product ID is invalid if it has a sequence repeated twice, product IDs with an odd number of digits are valid.

static bool IsAnInvalidId(int n)
    => HasSequenceRepeatedTwice(n);

static bool HasSequenceRepeatedTwice(int n)
{
    var digitCount = (int)(Math.Log10(n) + 1);
    if (digitCount % 2 != 0)
    {
        return false;
    }

    var firstHalf = n / (int)Math.Pow(10, digitCount / 2);
    var secondHalf = n % (int)Math.Pow(10, digitCount / 2);

    return firstHalf == secondHalf;
}

Once we check for repeated sequences, the only task left is counting IDs in each range.

Counting invalid product IDs

I’m creating a function to enumerate a range, Enumerate(), and a LINQ query to find and count invalid IDs.

Here’s my full solution:

var ranges = new[]
{
    new Range(11, 22),
    new Range(95, 115),
    new Range(998, 1012),
    new Range(1188511880, 1188511890),
    new Range(222220, 222224),
    new Range(1698522, 1698528),
    new Range(446443, 446449),
    new Range(38593856, 38593862),
    new Range(565653, 565659),
    new Range(824824821, 824824827),
    new Range(2121212118, 2121212124),
};

var sum = ranges.SelectMany(Enumerate)
                .Where(IsAnInvalidId)
                .Sum();
Console.WriteLine(sum);
Console.ReadLine();

static IEnumerable<int> Enumerate(Range r)
    => Enumerable.Range(r.Left, r.Right - r.Left + 1);

static bool IsAnInvalidId(int n)
    => HasSequenceRepeatedTwice(n);

static bool HasSequenceRepeatedTwice(int n)
{
    var digitCount = (int)(Math.Log10(n) + 1);
    if (digitCount % 2 != 0)
    {
        return false;
    }

    var firstHalf = n / (int)Math.Pow(10, digitCount / 2);
    var secondHalf = n % (int)Math.Pow(10, digitCount / 2);

    return firstHalf == secondHalf;
}

record Range(int Left, int Right);

Et voilà!

Advent of Code sharpens your coding skills. But coding is more than typing symbols fast. It’s also about teamwork, collaboration, and many skills I share in my book, Street-Smart Coding: 30 Ways to Get Better at Coding. That’s the roadmap I wish I’d known from day one.

Get your copy of Street-Smart Coding here

Advent of Code Day 1: Unlocking the North Pole

Back in 2022, I challenged myself with a different kind of Advent project.

Instead of running an Advent of Code, I ran an Advent of Posts. I wrote 22 posts in the days before Christmas. I missed two days but I declared the mission complete.

This year, I’m following the Advent of Code. I’d like to challenge myself to write “functionalish” solutions.

Here are the instructions for Day 1 and my solution:

Opening the secret entrance to the North Pole

Since there are only two rotations: left and right, I’m creating a discriminated union-like hierarchy. And I’m writing a separate class for the dial itself.

abstract record Rotation
{
    public record Left(int Distance) : Rotation;
    public record Right(int Distance) : Rotation;
}

record Dial(int Position)
{
    public Dial Turn(Rotation rotation)
    {
        return rotation switch
        {
            Rotation.Left f => this with { Position = (Position - f.Distance)%100 },
            Rotation.Right r => this with { Position = (Position + r.Distance)%100 },
            _ => throw new NotImplementedException(),
        };
    }
}

So far, I could do:

var d = new Dial(11);
d.Turn(new Rotation.Right(8)).Turn(new Rotation.Left(19))
// [Dial { Position = 0 }]

I have to confess, figuring out the modulus operation to move the dial took me a while.

With the dial rotating, the only missing piece is applying rotations and counting zeros,

static class Password
{
    public static int Find(Dial d, IEnumerable<Rotation> rotations)
    {
        var state = rotations.Aggregate((Dial: d, Password: 0), (state, rotation) =>
        {
            var dial = state.Dial.Turn(rotation);
            var pwd = dial.Position == 0 ? state.Password + 1: state.Password;
            return (dial, pwd);
        });
        return state.Password;
    }
}

I’m using LINQ Aggregate method to turn the dial and count the zeros.

That works, but Copilot and others’ solutions showed me a cleaner approach: separating moving the dial and counting with Scan(),

static class Password
{
    public static int Find(Dial d, IEnumerable<Rotation> rotations)
    {
        return rotations.Scan(d, (dial, rotation) => dial.Turn(rotation))
                        .Count(d => d.Position == 0);
    }

    public static IEnumerable<TAccumulate> Scan<TSource, TAccumulate>(
        this IEnumerable<TSource> source,
        TAccumulate seed,
        Func<TAccumulate, TSource, TAccumulate> func)
    {
        var acc = seed;
        yield return acc;
        foreach (var item in source)
        {
            acc = func(acc, item);
            yield return acc;
        }
    }
}

And here’s the full solution:

var dial = new Dial(50);
var rotations = new Rotation[]
{
    new Rotation.Left(68),
    new Rotation.Left(30),
    new Rotation.Right(48),
    new Rotation.Left(5),
    new Rotation.Right(60),
    new Rotation.Left(55),
    new Rotation.Left(1),
    new Rotation.Left(99),
    new Rotation.Right(14),
    new Rotation.Left(82)
};
var pwd = Password.Find(dial, rotations);
Console.WriteLine(pwd);
Console.ReadLine();

abstract record Rotation
{
    public record Left(int Distance) : Rotation;
    public record Right(int Distance) : Rotation;
}

record Dial(int Position)
{
    public Dial Turn(Rotation rotation)
    {
        return rotation switch
        {
            Rotation.Left f => this with { Position = (Position - f.Distance)%100 },
            Rotation.Right r => this with { Position = (Position + r.Distance)%100 },
            _ => throw new NotImplementedException(),
        };
    }
}

static class Password
{
    public static int Find(Dial d, IEnumerable<Rotation> rotations)
    {
        return rotations.Scan(d, (dial, rotation) => dial.Turn(rotation))
                        .Count(d => d.Position == 0);
    }

    public static IEnumerable<TAccumulate> Scan<TSource, TAccumulate>(
        this IEnumerable<TSource> source,
        TAccumulate seed,
        Func<TAccumulate, TSource, TAccumulate> func)
    {
        var acc = seed;
        yield return acc;
        foreach (var item in source)
        {
            acc = func(acc, item);
            yield return acc;
        }
    }
}

Et voilà!

Advent of Code sharpens your coding skills. But coding is more than typing symbols fast. It’s also about teamwork, collaboration, and many skills I share in my book, Street-Smart Coding: 30 Ways to Get Better at Coding. That’s the roadmap I wish I’d known from day one.

Get your copy of Street-Smart Coding here