JFC, today's puzzle made me feel dumb.
I'm writing my answers in Swift - which is the language I use in my day-job, and have for multiple years. (In my defense, I spend most™ of my time doing UI/UX work, so not a ton of algorithmic lifting or string manipulation in my day-to-day life).
today was... not my most impressive showing, lets say...
--------Part 1--------- --------Part 2---------
Day Time Rank Score Time Rank Score
6 00:56:49 18480 0 02:51:21 31126 0
yup, that sure does say 3 fucking hours to solve the whole thing!
(code under the cut)
Part of my problem was I didn't think generically when I wrote part 1, so part 2 absolutely blind-sided me, and I needed to come up with a more generic way to solve the problem (or brute-force it, but the shame was upon me, and I am stubborn, especially after 10 PM)
So, my first swing at part 1 involved attempting to pull a String.Substring 4 characters long, and check that for redundant chars, before sliding it along. I quickly realized that I could be more efficient than just scooting my substring forward 1 index and re-comparing all the characters. (good job, Rey!), and moved towards a pretty brute-force technique where I manually compared all the situations that would eliminate 3 of the 4 chars, then 2 then 1.
Not brilliant, but effective, woo!
So, when I read part 2 and realized that I needed a more generic solution, I went back to the Substring idea .
Here's where it all went off the rails, for multiple reasons:
- String and Substring will not let you use subscript with int values, only String.Index values, which cannot be swapped back and forth with int values. (there's reasons for this, having to do with how Substring works) At this point, I should have turned back, but see above re: sleepy Rey being a stubborn idiot. Also, the docs have sample code that really seems to imply that Int should work FINE as part of a subscript range!
let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
let streetsSlice = streets[2 ..< streets.endIndex]
print(streetsSlice)
// Prints "["Channing", "Douglas", "Evarts"]"
let index = streetsSlice.firstIndex(of: "Evarts") // 4
print(streets[index!])
// Prints "Evarts"
(see: https://developer.apple.com/documentation/swift/string/subscript(_:)-2so14 )
- I've been doing all the problems so far in an Xcode Playground, which on it's face is really nice and tidy! However... there's no breakpoints in playgrounds, and no backtraces when you crash. Which means debugging is literally just
print()statements. it's like Intro to CS all over again! >.<
So, by now, it's 11 PM, and my husband comes downstairs to chase me off to bed so he can watch Fútbol Americas in peace, and I am Full Of Feels and Stubborns. The good part of all the above wandering is that I had worked out what my algorithm should be, and how to nom chars off the front of my string, and so when I threw in the towel on using the fancy API and moved to just splitting the string into an array of Characters (and don't even GET me started on Character vs String, swift, I do not EVEN.), and used variables to keep track of various relevant indicies. 20 mins later and victory was mine! Heres the final code I wrote, and you can see all the other attempts in my github, here: https://github.com/nothes/AdventOfCode/blob/main/AdventOfCode.playground/Pages/Day%206.xcplaygroundpage/Contents.swift
func parseInput3(_ text: String) {
var startIndex: Int = 0
var endIndex: Int = 13
guard text.count >= 14 else { return } // no possible way to get a 14 letter code with less than 14 chars.
var potentialStartPacket: [Character] = []
var mutableText = text
for _ in 0 ..< 14 {
potentialStartPacket.append(mutableText.removeFirst())
}
var compare1 = 13 // start at the end of my string
var compare2 = 12 // what am I comparing it to?
var newFirstIndex: Int? = nil
while mutableText.count >= 14 {
while compare1 >= 1 {
while compare2 >= 0 {
if potentialStartPacket[compare1] == potentialStartPacket[compare2] {
newFirstIndex = compare2 + 1
break
} else {
compare2 -= 1
}
}
if newFirstIndex != nil {
break
}
compare1 -= 1
compare2 = compare1 - 1
}
if let newFirstIndex = newFirstIndex {
// update start & end indexes, and search array.
let keepLast = 14 - newFirstIndex
for i in 0 ..< keepLast {
potentialStartPacket[i] = potentialStartPacket[14 - keepLast + i]
}
for j in keepLast ..< 14 {
if mutableText.isEmpty == false {
potentialStartPacket[j] = mutableText.removeFirst()
} else {
print("no unique sequence found.")
return
}
}
startIndex += newFirstIndex
endIndex = startIndex + 13
compare1 = 13
compare2 = compare1 - 1
} else {
// we found a clean string!
print("found 14 unique chars: \(potentialStartPacket). first index after that is \(endIndex + 1)")
return
}
newFirstIndex = nil
}
}