Nim
Runtime: 30-40 ms
I’m not very experienced with recursion and memoization, so this took me quite a while.
Edit: slightly better version
template splitNum(numStr: string): seq[int] =
@[parseInt(numStr[0..<numStr.len div 2]), parseInt(numStr[numStr.len div 2..^1])]
template applyRule(stone: int): seq[int] =
if stone == 0: @[1]
else:
let numStr = $stone
if numStr.len mod 2 == 0: splitNum(numStr)
else: @[stone * 2024]
proc memRule(st: int): seq[int] =
var memo {.global.}: Table[int, seq[int]]
if st in memo: return memo[st]
result = st.applyRule
memo[st] = result
proc countAfter(stone: int, targetBlinks: int): int =
var memo {.global.}: Table[(int, int), int]
if (stone,targetBlinks) in memo: return memo[(stone,targetBlinks)]
if targetBlinks == 0: return 1
for st in memRule(stone):
result += st.countAfter(targetBlinks - 1)
memo[(stone,targetBlinks)] = result
proc solve(input: string): AOCSolution[int, int] =
for stone in input.split.map(parseInt):
result.part1 += stone.countAfter(25)
result.part2 += stone.countAfter(75)
Nim
Runtime:
7ms3.18 msPart 1: I use flood fill to count all grouped plants and keep track of each border I see.
Part 2: I use an algorithm
similar to “merge overlapping ranges”to count spans of borders (border orientation matters) in each row and column, for each group. Resulting code (hidden under spoiler) is a little messy and not very DRY (it’s completely soaked).Edit: refactored solution, removed some very stupid code.
proc groupSpans()
Codeberg repo