Hiking for Advent of Code 2024 - Day 10

Date

Day 10 of Advent of Code is a simple hike up a mountain. This visualization is just a representation of the searching algorithm, so a few more spaces are filled in that what represents a hiking trail.

Hiking

Lessons Learned

For the past couple of years, I always used SIMD4<Float> to represent a color, since that is what is directly used by Metal. That’s always tricky because it’s hard to eyeball what color something is when looking at SIMD4<Float>(0.25, 0.75, 0.01, 1.0).

I added an extension for using native colors directly, so I can instead ask for NativeColor.systemGreen.simd. Under the hood, NativeColor is just and alias for UIColor or NSColor.


Word Search for Advent of Code 2024 - Day 4

Date

Day 4 of Advent of Code had us do a word search for “XMAS”. My solution was to just look for the letter “X” and then spin around that point looking for the string. I though the spinning would look interesting, so I put together a simple 2D visualization.

Word Search

Lessons Learned

Rendering a grid of text is slow. I added a new offscreenImage function to my visualization library that lets you generate a CGImage using the same drawing tools you use for the main visualization.

let image = offscreenImage { offscreenContext in
    let rect = CGRect(origin: .zero, size: CGSize(width: 20, height: 20))
    let color = CGColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
    fill(rect: rect, color: red, in: offscreenContext)
}

context.draw(image, in: screenRect)

Since rendering the found words would also be slow, I ended up recreating the text grid any time new highlights were found, allowing the main rendering loop to only render cursors and search vectors.



Score Card 4.0 Released

Date

Score Card 4.0 brings a whole new set of features to the app. Not only should the app be a great utility, but also should be more fun.

Target scores! Setting a target score provides a nice celebration for the winner of a game.

Tally mode! A new way to capture scores by simply adding or subtracting points from a player.

Saved settings! Settings from past games can be used when creating new score cards.

Check out the app on the App Store.


Restructure 2.1.3 Released

Date

A bug was found where if a statement was reused and one of the bindings went from a non-nil value to a nil value, the binding would not update. For example:

try restructure.execute(query: "CREATE TABLE foo (name TEXT NULL)")
let statement = try restructure.prepare(query: "INSERT INTO foo (name) VALUES (:name)")
let encoder = StatementEncoder()

struct Foo {
    name: String?
}

statement.reset()
try enconder.encode(Foo(name: "Bar"), to: statement)
statement.step()

statement.reset()
try enconder.encode(Foo(name: nil), to: statement)
statement.step()

In this case, both records would have a name of “Bar”.

This bug comes from the use of KeyedEncodingContainerProtocol. I assumed that implementing encodeNil would be enough for handling nil values, but the code needs to also implement the encodeIfPresent methods.

Also, along with being on Github, I’ve also added Restructure to the Swift Package Index.