Moved Blog Back to Jekyll

In February, I moved this blog from Jekyll (hosted on Netlify) to micro.blog.

I made the switch because the app I use to write blog posts (iA Writer) can publish directly to micro.blog. This was the idea. But whenever I tried publishing that way, I’d still need to tweak the post in the micro.blog editor to get everything just right.

It ended up being a bit of a pain.

I even tried using Ulysses instead, but ran into the same issues.

To be clear: micro.blog is excellent. It’s a fantastic service. I was just having issues getting my workflow to feel seamless.

So, I decided to move back to Jekyll. It gives me more control over everything. Since I need to tweak the Markdown anyway, I’d rather do it locally before publishing.

I’ve posted the source for this blog on GitHub. The repo is here: rwgrier/blog.ryangrier.com.

This is the last migration for a while. Hopefully. 🤞

Project Euler - Problem 2

This is the second post in my new Project Euler series. I recently wrote about Problem 1. Shockingly, I’m still at it.

The GitHub repo is here: rwgrier/swift-project-euler

Let’s dive in.

The second problem states:

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

So, it’s a Fibonacci problem. That’s familiar territory. I’ve written about the Fibonacci Sequence in 2014 and again in 2016. Those posts covered a variety of ways to calculate Fibonacci numbers at a given index, from brute force to memoization to using my Jedi-math tricks.

For this one, I’m going with Binet’s Formula. It’s elegant and good enough for what we need here. (If I were doing this in a coding interview, I’d reach for memoization like I showed in the 2016 post.)

To reuse later, I wrapped it all in a FibonacciGenerator:

struct FibonacciGenerator {
    private let sqrt_5: Double
    private let phi: Double

    init() {
        sqrt_5 = sqrt(Double(5))
        phi = ((1 + sqrt_5) / 2)
    }

    func fibonacci(at index: Int) -> Int {
        guard index >= 2 else {
            return index
        }

        let doubleIndex = Double(index)

        // x(n) = (Phi^n - (-Phi)^-n) / √5
        let numerator = pow(phi, doubleIndex) - pow((-1.0 * phi), (-1.0 * doubleIndex))
        return Int(numerator / sqrt_5)
    }
}

It should be noted here that Binet’s Formula can produce inaccurate Fibonacci numbers at larger indices (over 71) because of rounding issues (source). But we shouldn’t encounter that issue for this problem. If we do in the future, I’ll adjust the algorithm.

Now that we can generate Fibonacci numbers, solving the problem is three simple steps:

  1. Generating numbers up to the limit (4 million)
  2. Filtering for even values
  3. Summing the result

Here’s the function to generate the Fibonacci sequence up to a max:

private func generateFibonacciNumbersUpTo(_ max: Int) -> [Int] {
    let generator = FibonacciGenerator()
    var numbers: [Int] = []
    var index: Int = 0
    var fibonacci = 1

    while fibonacci <= max {
        defer { index += 1 }
        fibonacci = generator.fibonacci(at: index)

        guard fibonacci <= max else { break }
        numbers.append(fibonacci)
    }

    return numbers
}

This method loops through calculating Fibonacci numbers until it reaches the maximum. Then, it returns an array of Fibonacci numbers.

Then, summing the even-valued terms is easy:

func sumEvenFibonacci(_ max: Int) -> Int {
    generateFibonacciNumbersUpTo(max)
        .filter { $0.isMultiple(of: 2) }
        .reduce(0, +)
}

Done and done.

Next up, Problem 3. Maybe.

Project Euler - Problem 1

I recently started a new blog series where I solve Project Euler problems and write about how I did it. This post addresses Problem 1.

So far, I’m sticking with the plan. Go me.

The GitHub repo is available here.

Anyway, let’s dive in.

The first problem states:

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

The problem provides an example to start with. It shows how to find every number below 10 that’s a multiple of 3 or 5. Those are 3, 5, 6, and 9. Their sum is 23.

To solve the actual problem, we need to find every number below 1000 that is a multiple of 3 or 5. We can do 0 - 10 on paper (or in our heads). But calculating these numbers between 0 - 1000 is a little more time-consuming.

Luckily, we can solve this with a bit of programming.

My first solution

Here was my first solution.

func sumOfMultiples3And5(max: Int) -> Int {
    var sum: Int = 0

    for count in 1..<max {
        guard count % 3 == 0 || count % 5 == 0 else { continue }
        sum += count
    }

    return sum
}

This is a brute-force solution. It loops through every number from 1 to max, and if a number is divisible by 3 or 5, it adds it to a running sum.

My second solution

I then slightly rewrote the function. It’s still a brute-force approach. But it’s a little more concise.

func sumOfMultiples3And5(max: Int) -> Int {
    (1..<max)
        .filter { $0 % 3 == 0 || $0 % 5 == 0 }
        .reduce(0, +)
}

This approach does the same thing but in a more concise way.

It builds a range from 1 to max, filters out numbers that aren’t divisible by 3 or 5, and then adds the rest using reduce.

This approach is very concise but not as readable as my first approach.

My third solution

While I was writing this blog post, I discovered another approach. This is a purely mathematical approach.

This approach uses an Arithmetic Progression. Honestly, I won’t do a great job describing how this works. Instead, read through these two posts:

Here’s the code:

func sumOfMultiples3And5(max: Int) -> Int {
    let three = sumOfMultiplesUsingAP(multiple: 3, max: max)
    let five = sumOfMultiplesUsingAP(multiple: 5, max: max)
    let fifteen = sumOfMultiplesUsingAP(multiple: 15, max: max)

    return (three + five) - fifteen
}

// Using Arithmetic Progression
private func sumOfMultiplesUsingAP(multiple: Int, max: Int) -> Int {
    let numberOfMultiples = (max - 1) / multiple
    return multiple * numberOfMultiples * (numberOfMultiples + 1) / 2
}

This approach doesn’t use any looping. It’s much more efficient than the brute-force methods. But you need to know about Arithmetic Progressions and how to apply them.

If this were given to me in an interview, I would be satisfied with the brute-force solutions I came up with here. However, if the max number were larger than 1000, I would need to look for a more performant solution. The mathematical version would work well here.

Next up is problem two from the Project Euler website.

Project Euler Series

I have an on-again, off-again relationship with working on Project Euler problems. Over the years, I’ve created (and deleted or archived) several Project Euler GitHub repos.

I know what you’re thinking. What is Project Euler?

Project Euler is a site that offers a collection of mathematical problems that can be solved using programming. The problems start out easy but grow more complex as you go. They’re great for sharpening your coding skills and often appear in technical interviews.

As of today, I’ve solved a total of five problems. I gave up quickly.

Maybe “on-again, off-again” is too generous. It’s more like I keep redoing the same five problems repeatedly.

This time, I’m trying something different. I recently unarchived my most recent Project Euler GitHub repo. I created it eight years ago… and almost immediately abandoned it. When I brought it back, I solved one problem (in Swift) and stopped. Ouch.

This time, I plan to stick with it. At least long enough to get past five problems. I hope.

Here’s the plan: when I solve a problem, I’ll write a blog post about it. Each post will walk through the problem, my approach, the code, and anything interesting I discovered along the way. I hope this turns into a long-running series.

In the next post, I’ll discuss the first problem. I went through several iterations of the solution. I’ll go through each of those iterations. Stay tuned.

Blogging Hiatus

I’ve been terrible about blogging lately. I’ve also been bad about working on my side projects.

Working on a side project often gets me thinking about a blog post idea, and writing about something technical gets me in the mood to work on a side project. This process is very cyclical. For me, it’s just a matter of kick-starting it. I’ve had trouble with that lately.

I keep telling myself, “I’ll get back to it next week.” I hope to improve on both of those soon.

I’ve moved to Micro.blog for my blogging platform. I am also using Micro.blog to post the release notes for Beer Style Guidelines.

I’ve included a handful of technical posts to get me started. I have others, but most were outdated.

I don’t know how much personal stuff I’ll be posting. I plan to post technical (programming) posts more frequently and hope to get into a regular posting cadence. I have some blog posts in mind that I hope to get to soon.

Lofty ambitions, right?

So here I am. Stating publicly that I’m going to get back to it soon™. I hope I don’t turn into Homer backing into the bushes when I fail at this. 🤣

OlderNewer