Open andreiz opened 11 months ago
Part 1 is pretty simple. Loop through games, then for each try in the game check if any red/green/blue exceeds the max.
Didn't have Copilot working yet, so started with GPT prompting again.
After a bit of back and forth about passing the data and structuring the counts it produced this function that checks each game's validity:
let CUBE_LIMITS: [String: Int] = ["red": 12, "green": 13, "blue": 14]
func isGamePossible(gameData: String) -> (isPossible: Bool, violatingCube: String?, count: Int?) {
let tries = gameData.split(separator: ";")
for tryData in tries {
// Initialize cube counts for each try.
var cubeCounts = ["red": 0, "green": 0, "blue": 0]
let colorDataArray = tryData.split(separator: ",")
for colorData in colorDataArray {
let parts = colorData.split(separator: " ")
let count = Int(parts[0].trimmingCharacters(in: .whitespaces)) ?? 0
let color = String(parts[1].trimmingCharacters(in: .whitespaces))
cubeCounts[color, default: 0] += count
if let limit = CUBE_LIMITS[color], cubeCounts[color, default: 0] > limit {
return (false, color, cubeCounts[color]) // Return false, violating cube color, and count
}
}
}
return (true, nil, nil) // Return true with no violations
}
I pointed out that it's trying to sum the per-color counts for all the tries, instead of treating them independently. That, and that the cubeCounts
is unnecessary if we check against the limits directly. Updated result:
func isGamePossible(gameData: String) -> (isPossible: Bool, violatingCube: String?, count: Int?) {
let tries = gameData.split(separator: ";")
for tryData in tries {
let colorDataArray = tryData.split(separator: ",")
for colorData in colorDataArray {
let parts = colorData.split(separator: " ")
let count = Int(parts[0].trimmingCharacters(in: .whitespaces)) ?? 0
let color = String(parts[1].trimmingCharacters(in: .whitespaces))
// Check if the count exceeds the limit for each color.
if let limit = CUBE_LIMITS[color], count > limit {
return (false, color, count) // Return false, violating cube color, and count
}
}
}
return (true, nil, nil) // Return true with no violations
}
I wasn't sure what ??
was, so I asked.
In Swift, the ?? operator is known as the "nil coalescing operator." It is used to provide a default value for an optional in case the optional is nil.
Now we just need to read in a file, iterate over the lines, and sum the game IDs that don't violate the constraints.
I do like how you can return multiple (and optional) values from a func and then unwrap them.
Ran this on the test input and the result was:
Game 1 [3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green]: possible
Game 2 [1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue]: possible
Game 3 [8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red]: impossible due to red cube count 20 exceeding limit
Game 4 [1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red]: impossible due to blue cube count 15 exceeding limit
Game 5 [6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green]: possible
Sum of possible game numbers: 8
Which is correct.
Ok, part 2. Need to keep track of max count of each try and return it along with the game result (whether it's possible or impossible).
I wondered how to easily multiply the values of an array and ChatGPT suggested:
let (isPossible, fewestCubes) = analyzeGame(gameData: gameData)
let cubeProduct = fewestCubes.values.reduce(1, *)
cubeProductSum += cubeProduct
Neat. I like that operators are first-class entities.
Printing out cubeProductSum
now and... it's passed.
https://adventofcode.com/2023/day/2
Puzzle input: https://adventofcode.com/2023/day/2/input