aoc2023/day-14/two.go

46 lines
1.1 KiB
Go
Raw Normal View History

2023-12-14 22:22:41 +00:00
package main
const CYCLES = 1000000000
// cycleOnce transposes and rolls a single image once
func cycleOnce(image img) {
for i := 0; i < 4; i++ {
for i, line := range image.transposed() {
image.raw[i] = rollRight(line)
}
}
}
// cycleMany cycles a single image for a given number of iterations
// it also caches each image and measures the period of repetition
func cycleMany(image img, iterations int) {
cache := make(map[string]int)
i, start := 0, 0
for ; i < iterations; i++ {
cycleOnce(image)
if idx, ok := cache[image.String()]; ok { // we found first repeated image
start = idx
i++
break
}
cache[image.String()] = i + 1
}
period := i - start // length of a full period
remaining := (iterations - i - 1) % period // number of cycles left in current period
for j := 0; j < remaining; j++ {
cycleOnce(image) // rotate to the final image in the period
}
}
// two returns the load of all boulders after 1000000000 cycles
func two(lines []string) int {
image := newImg(len(lines))
copy(image.raw, lines)
cycleMany(image, CYCLES)
return getload(image.transposed())
}