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 the index of the interation for each image 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()) }