2023-12-14 22:22:41 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
const CYCLES = 1000000000
|
|
|
|
|
2023-12-15 01:04:22 +00:00
|
|
|
// cycleOnce transposes and rolls a single image four times (N,W,S,E)
|
2023-12-14 22:22:41 +00:00
|
|
|
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
|
2023-12-15 00:53:14 +00:00
|
|
|
// it caches seen images as well as their location in the period
|
|
|
|
// finally it copies the cached image with idx matching the interval to image.raw
|
2023-12-14 22:22:41 +00:00
|
|
|
func cycleMany(image img, iterations int) {
|
2023-12-15 00:53:14 +00:00
|
|
|
cachedIndexes := make(map[string]int)
|
|
|
|
cachedImages := make(map[int][]string)
|
2023-12-14 22:22:41 +00:00
|
|
|
i, start := 0, 0
|
|
|
|
for ; i < iterations; i++ {
|
|
|
|
cycleOnce(image)
|
|
|
|
|
2023-12-15 00:53:14 +00:00
|
|
|
if idx, ok := cachedIndexes[image.String()]; ok { // we found first repeated image
|
2023-12-14 22:22:41 +00:00
|
|
|
start = idx
|
|
|
|
i++
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2023-12-15 00:53:14 +00:00
|
|
|
cachedIndexes[image.String()] = i + 1
|
|
|
|
cachedImages[i+1] = make([]string, len(image.raw))
|
|
|
|
copy(cachedImages[i+1], image.raw)
|
2023-12-14 22:22:41 +00:00
|
|
|
}
|
2023-12-15 00:53:14 +00:00
|
|
|
|
2023-12-15 01:37:15 +00:00
|
|
|
period := i - start // length of a full period
|
|
|
|
copy(image.raw, cachedImages[start+((iterations-i-1)%period)+1]) // copy cachedImage into image.raw
|
2023-12-14 22:22:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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())
|
|
|
|
}
|