package main import ( "fmt" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := h.StdinToStringSlice() part1(inp) fmt.Println() part2(inp) } func part1(input []string) { m := h.StringSliceToCoordByteMap(input) fmt.Println("# Part 1") tiltNorth(&m) fmt.Println(calcLoad(&m)) } func part2(input []string) { target := 1_000_000_000 mapCache := make(map[string]int) m := h.StringSliceToCoordByteMap(input) var i = 0 var ignoreCache bool for ; i <= target; i++ { tiltNorth(&m) tiltWest(&m) tiltSouth(&m) tiltEast(&m) if !ignoreCache { if v, ok := mapCache[m.String()]; ok && i > 200 { target = i + (target-v)%(i-v) - 1 ignoreCache = true } mapCache[m.String()] = i } } fmt.Println("# Part 2") fmt.Println(calcLoad(&m)) } func c(x, y int) h.Coordinate { return h.Coordinate{X: x, Y: y} } // m.FindAll returns a slice sorted Left->Right, Top->Bottom func tiltNorth(m *h.CoordByteMap) { rocks := m.FindAll('O') for i := range rocks { if rocks[i].Y == m.TLY { continue } mv := h.Coordinate{X: rocks[i].X, Y: rocks[i].Y} for m.Get(mv.North()) == '.' { mv.MoveNorth() } if !mv.Equals(rocks[i]) { m.Put(rocks[i], '.') m.Put(mv, 'O') } } } func tiltEast(m *h.CoordByteMap) { rocks := m.FindAll('O') for i, j := 0, len(rocks)-1; i < j; i, j = i+1, j-1 { rocks[i], rocks[j] = rocks[j], rocks[i] } for i := range rocks { if rocks[i].X == m.BRX { continue } mv := h.Coordinate{X: rocks[i].X, Y: rocks[i].Y} for m.Get(mv.East()) == '.' { mv.MoveEast() } if !mv.Equals(rocks[i]) { m.Put(rocks[i], '.') m.Put(mv, 'O') } } } func tiltSouth(m *h.CoordByteMap) { rocks := m.FindAll('O') for i, j := 0, len(rocks)-1; i < j; i, j = i+1, j-1 { rocks[i], rocks[j] = rocks[j], rocks[i] } for i := range rocks { if rocks[i].Y == m.BRY { continue } mv := h.Coordinate{X: rocks[i].X, Y: rocks[i].Y} for m.Get(mv.South()) == '.' { mv.MoveSouth() } if !mv.Equals(rocks[i]) { m.Put(rocks[i], '.') m.Put(mv, 'O') } } } func tiltWest(m *h.CoordByteMap) { rocks := m.FindAll('O') for i := range rocks { if rocks[i].X == m.TLX { continue } mv := h.Coordinate{X: rocks[i].X, Y: rocks[i].Y} for m.Get(mv.West()) == '.' { mv.MoveWest() } if !mv.Equals(rocks[i]) { m.Put(rocks[i], '.') m.Put(mv, 'O') } } } func calcLoad(m *h.CoordByteMap) int { var res int bot := m.BRY rocks := m.FindAll('O') for i := range rocks { res += (bot - rocks[i].Y) + 1 } return res }