package main const CYCLES = 1000000000 // cycleOnce transposes and rolls a single image four times (N,W,S,E) 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 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 func cycleMany(image img, iterations int) { cachedIndexes := make(map[string]int) cachedImages := make(map[int][]string) i, start := 0, 0 for ; i < iterations; i++ { cycleOnce(image) if idx, ok := cachedIndexes[image.String()]; ok { // we found first repeated image start = idx i++ break } cachedIndexes[image.String()] = i + 1 cachedImages[i+1] = make([]string, len(image.raw)) copy(cachedImages[i+1], image.raw) } period := i - start // length of a full period copy(image.raw, cachedImages[start+((iterations-i-1)%period)+1]) // copy cachedImage into image.raw } // 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()) }