package main import ( "fmt" "os" "strings" "time" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) var sleepTime = (time.Second / 5) var minx, miny, maxx, maxy int func main() { inp := h.StdinToStringSlice() watch := len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "-w") if watch { if strings.Contains(os.Args[1], "=") { pts := strings.Split(os.Args[1], "=") sleepTime = (time.Second / time.Duration(h.Atoi(pts[1]))) } } simulate(inp, 10, watch) } func buildInstructions(inp []string) []byte { var inst []byte for i := range inp { dir, count := inp[i][0], h.Atoi(inp[i][2:]) for j := 0; j < count; j++ { inst = append(inst, dir) } } return inst } func simulate(inp []string, knotCount int, watch bool) { if watch { fmt.Print(h.CLEAR_SCREEN) } visited := make(map[h.Coordinate]bool) inst := buildInstructions(inp) var knots []h.Coordinate for i := 0; i < knotCount; i++ { knots = append(knots, h.Coordinate{X: 0, Y: 0}) } if watch { fmt.Println("# Part 1") printVisits(visited, knots) } for i, dir := range inst { moveHead(dir, knots) visited[knots[len(knots)-1]] = true if watch { time.Sleep(sleepTime) fmt.Print(h.CLEAR_SCREEN) fmt.Printf("# Part 1 (%d/%d)\n", i, len(inst)) printVisits(visited, knots) } } if watch { time.Sleep(sleepTime) fmt.Print(h.CLEAR_SCREEN) } fmt.Println("# Part 1") if watch { printVisits(visited, knots) } fmt.Printf("Tail visited %d positions\n", len(visited)) } func moveHead(dir byte, knots []h.Coordinate) { prevKnots := make([]h.Coordinate, len(knots)) copy(prevKnots, knots) switch dir { case 'U': knots[0] = knots[0].North() case 'R': knots[0] = knots[0].East() case 'D': knots[0] = knots[0].South() case 'L': knots[0] = knots[0].West() } if knots[0].X < minx { minx = knots[0].X } if knots[0].X > maxx { maxx = knots[0].X } if knots[0].Y < miny { miny = knots[0].Y } if knots[0].Y > maxy { maxy = knots[0].Y } for i := 1; i < len(knots); i++ { // Go through all knots and check if any need to move if !knots[i].Equals(knots[i-1]) && !knots[i].Adjacent(knots[i-1]) { if knots[i].X == knots[i-1].X { // Same column if knots[i].Y < knots[i-1].Y { knots[i].Y++ } else { knots[i].Y-- } } else if knots[i].Y == knots[i-1].Y { // Save row if knots[i].X < knots[i-1].X { knots[i].X++ } else { knots[i].X-- } } else { // Not in the same row or column if knots[i].X < knots[i-1].X { knots[i].X++ } else { knots[i].X-- } if knots[i].Y < knots[i-1].Y { knots[i].Y++ } else { knots[i].Y-- } } } else { // If one knot didn't need to move, none behind it will break } } } func printVisits(m map[h.Coordinate]bool, knots []h.Coordinate) { for y := miny; y <= maxy; y++ { for x := minx; x <= maxx; x++ { var isKnot bool for i := range knots { if knots[i].X == x && knots[i].Y == y { isKnot = true var bt byte if i == 0 { bt = 'H' } else { bt = '0' + byte(i) } fmt.Print(string(bt)) break } } if !isKnot { if v, ok := m[h.Coordinate{X: x, Y: y}]; ok && v { fmt.Print("#") } else { fmt.Print(".") } } } fmt.Println() } fmt.Printf("Bridge: %s\n", knots) fmt.Println() }