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) start, _ := m.FindFirst('S') m.Put(start, '.') result := []h.Coordinate{start} for i := 0; i < 64; i++ { result = findNext(&m, result) } fmt.Println("# Part 1") fmt.Println(len(result)) } // 253370351984188 is too low func part2(input []string) { m := h.StringSliceToCoordByteMap(input) start, _ := m.FindFirst('S') m.Put(start, '.') steps := 26501365 p := make([]int, 3) size := len(input) half := size / 2 fmt.Println("Getting Plots: p[0]") p[0], _ = getPlots(&m, half, 5) fmt.Println("Getting Plots: p[1]") m = h.StringSliceToCoordByteMap(input) p[1], _ = getPlots(&m, half+size, 5) fmt.Println("Getting Plots: p[2]") m = h.StringSliceToCoordByteMap(input) p[2], _ = getPlots(&m, half+2*size, 5) a := (p[2] + p[0] - 2*p[1]) / 2 b := p[1] - p[0] - a c := p[0] n := steps / size result := a*n*n + b*n + c fmt.Println("# Part 2") fmt.Println(result) } var visited map[string]bool func getPlots(m *h.CoordByteMap, steps int, factor int) (int, error) { sx, sy := m.ColCount(), m.RowCount() l := sy expandMap(m, factor) sx = l * (factor / 2) sy = l * (factor / 2) visited = make(map[string]bool) return len(nextStep(sx, sy, 0, steps, m)), nil } func isPlot(m *h.CoordByteMap, x, y int) bool { return m.Get(h.Coordinate{X: x, Y: y}) == '.' } func nextStep(x, y, step, max int, m *h.CoordByteMap) []h.Coordinate { var acc []h.Coordinate var key = fmt.Sprintf("%d;%d;%d", x, y, step) if _, ok := visited[key]; ok { return []h.Coordinate{} } else { visited[key] = true } if step == max { return []h.Coordinate{{X: x, Y: y}} } if x > 0 && isPlot(m, x-1, y) { acc = append(acc, nextStep(x-1, y, step+1, max, m)...) } if x < m.ColCount() && isPlot(m, x+1, y) { acc = append(acc, nextStep(x, y-1, step+1, max, m)...) } if y > 0 && isPlot(m, x, y-1) { acc = append(acc, nextStep(x, y-1, step+1, max, m)...) } if y < m.RowCount() && isPlot(m, x, y+1) { acc = append(acc, nextStep(x, y+1, step+1, max, m)...) } return acc } func expandMap(m *h.CoordByteMap, factor int) { stx, edx := m.TLX, m.BRX for f := 1; f < factor; f++ { for x := stx; x <= edx; x++ { col := m.GetCol(x) m.AddCol(col) } sty, edy := m.TLY, m.BRY for y := sty; y <= edy; y++ { row := m.GetRow(y) m.AddRow(row) } } } func part2BruteForce(input []string) { // Brute force just isn't going to cut it... m := h.StringSliceToCoordByteMap(input) m.StringEmptyIsSpace = true m.StringEmptyByte = '.' seen := make(map[h.Coordinate]bool) start, _ := m.FindFirst('S') m.Put(start, '.') result := []h.Coordinate{start} steps := 26501365 for i := 0; i < steps; i++ { fmt.Println(h.CLEAR_SCREEN) fmt.Printf("%d/%d (%f)\n", i, steps, float64(i)/float64(steps)) seen, result = findNextInfiniteRepeat(&m, seen, result) if i == 100 { break } } fmt.Println("# Part 2") fmt.Println(len(result)) for i := range result { m.Put(result[i], 'O') } fmt.Println(m) // It's making a diamond shape... } func findNext(m *h.CoordByteMap, curr []h.Coordinate) []h.Coordinate { var result []h.Coordinate for _, c := range curr { for _, tst := range []h.Coordinate{ c.North(), c.East(), c.South(), c.West(), } { if m.ContainsCoord(tst) && m.Get(tst) == '.' { var contains bool for i := range result { if result[i].Equals(tst) { contains = true break } } if !contains { result = append(result, tst) } } } } return result } func findNextInfiniteRepeat(m *h.CoordByteMap, seen map[h.Coordinate]bool, curr []h.Coordinate) (map[h.Coordinate]bool, []h.Coordinate) { var result []h.Coordinate for _, c := range curr { for _, tst := range []h.Coordinate{ c.North(), c.East(), c.South(), c.West(), } { if seen[tst] { continue } wrkX, wrkY := tst.X, tst.Y for wrkX < m.TLX { wrkX += m.BRX } for wrkY < m.TLY { wrkY += m.BRY } wrk := h.Coordinate{X: (wrkX % m.BRX), Y: (wrkY % m.BRY)} if m.Get(wrk) == '.' { var contains bool for i := range result { if result[i].Equals(tst) { contains = true break } } if !contains { result = append(result, tst) seen[tst] = true } } } } return seen, result }