Advent of Code 2025

Interesting that you say "it's not fast"... I'm using slices in my solution as well, and part 2 takes 0.036 milliseconds on my M4 mini

    func joltage(_ bank: [Int], batteries: Int) -> Int {
        var jolts = 0
        var startIndex = bank.startIndex
        for cutoff in (0..<batteries).reversed() {
            let endIndex = bank.endIndex - cutoff
            let (max, maxIndex) = maxAndIndex(in: bank[startIndex ..< endIndex])
            startIndex += maxIndex + 1
            jolts = jolts * 10 + max
        }
        return jolts
    }

    func maxAndIndex(in array: Array<Int>.SubSequence) -> (Int, Int) {
        var maxValue = Int.min
        var maxIndex = 0
        for (index, element) in array.enumerated() {
            if element > maxValue {
                maxValue = element
                maxIndex = index
            }
        }
        return (maxValue, maxIndex)
    }
3 Likes

I meant my solution as a whole, not Slices specifically, given that my solution is pretty casual about multiple passes on the original String using built in functions instead of the custom function you wrote.

It'd be better to set up some speed tests instead of just assuming though, for sure!

What an interesting greedy solution of you guys. I thought it supposed to use DP

1 Like

Interesting time and solution. I thought it was a recursion + memoization problem and solved it in a much more convoluted way (basically, trying every possible combination of picking or not picking a certain battery, and then caching the results for the subsection of the bank that was in that recursion scope).

I'm somewhat surprised that I I still managed to get a fairly quick execution time despite using a way less efficient approach: ~0.04 s on a M1 Pro MacBook.

1 Like

:sweat_smile: TIL Davis–Putnam algorithm, save that for later...

A little easier than the wikipedia page: Numberphile on Topic (doesn't mention DP explicitly, but combinatorial geometry in general)

EDIT: Oooooh... you might have also meant DP == Dynamic Programing! Ha. My bad... but it's been an interesting distraction.

1 Like

Yeah! I mean Dynamic Programming :joy:

1 Like

Doing this again this year. A little late to the party as I just now got time to sit down and set up an environment and do Day 1. Haven’t used Swift as much as I would like this year, so it’s good to knock the rust off.

For now I’ve got my code in a local repository so I can put my inputs in without worrying about it too much. I’ll make a GH mirror at some point if I need to discuss some of my code.

1 Like

My initial solution for day 8 used an array to store all precomputed distances. Switching to a Heap shaved off ~50% of the runtime - it does pay off not having to sort 500k entries when you only need 1k or so...

3 Likes

I've been wondering what people did.

I used a dictionary of <Edge, Int> where edge was defined as below. It takes over a second at least to run the calculate and sort loops, so I'm sure your heap suggestion will be better.

I was wondering if there was a better way to store the two points so that the order didn't matter for the key value hash. InlineSet<Vector, 2> :sweat_smile:

I saw a suggestion of a an OctTree like structure to not bother with the farthest flung, too.

struct Edge:Hashable {
    let points: Set<Vector>
    
    init?(_ p1:Vector, _ p2:Vector) {
        guard p1 != p2 else {
            return nil
        }
        self.points = [p1, p2]
    }

   func contains(_ point:Vector) -> Bool {
        points.contains(point)
    }
    
    func touches(_ other:Self) -> Vector? {
        //TODO: throw
        guard self != other else {
            print("they are the same edge.")
            return nil
        }
        let inter = points.intersection(other.points).sorted()
        guard !inter.isEmpty else {
            return nil
        }
        return inter.first
    }
}
1 Like

It’s a classic Union Find problem, and I’m using built-in SIMD3 instead of custom Vector. Here is my solution. The only thing I missed to do was use Heap.

2 Likes

Hi people,

Day 10 part 2 question:

I'm curious to learn how you solved part 2 of day 10. The common consensus on the inter webs seems to be to use a solver such as Z3. But that is not available on Swift.

As per CoPilots suggestion I went the "just call a Python script that uses Z3" from my Swift code. Though pragmatic (it works), it feels really dirty. I would like to learn from a pure Swift solution.

Were you able to solve this one using Swift only?

I've caved in and decided to try to learn at least a little Z3 for this once I have time (probably not this year).

There is a Swift wrapper at GitHub - LuizZak/swift-z3: A Swift wrapper over Microsoft's Z3 Theorem Prover that I plan to use.

1 Like

(Day 11 spoilers)

After two days (9 & 10) of trying —and failing— to solve Part 2 by attempting to cut the execution time down through either low-level optimizations or memoization, that approach finally worked today.

Got it running in ~5ms on a M1 Pro even.

Also, total side note but I love how easy it is now to profile a function in Xcode using a test (through the right click → 'Profile [test name]'). Really helpful in quickly hunting down what was slowing down my code, even when it was not the right approach.