package main import ( "flag" "fmt" "math" "strings" "time" "github.com/alexchao26/advent-of-code-go/cast" "github.com/alexchao26/advent-of-code-go/util" ) func main() { var part int flag.IntVar(&part, "part", 1, "part 1 or 2") flag.Parse() fmt.Println("Running part", part) if part == 1 { part1(util.ReadFile("./input.txt")) } else { part2(util.ReadFile("./input.txt")) } } func part1(input string) { postions, velocities := parseInputs(input) steps := 0 prints := 0 hasPrinted := false for hasLoneIsland(postions) { move(postions, velocities) steps++ fmt.Println("\nsteps run", steps) printable := printGrid(postions) if printable != "" { fmt.Println("Steps: ", steps) fmt.Println(printable) time.Sleep(time.Millisecond * 500) hasPrinted = true } // stop printing after things have collided if printable == "" && hasPrinted { return } fmt.Println(prints) } } func part2(input string) { // Note, reused part 1 with a print for the number of steps part1(input) } func parseInputs(input string) (positions [][2]int, velocities [][2]int) { lines := strings.Split(input, "\n") for _, l := range lines { posX := strings.TrimSpace(l[10:16]) posY := strings.TrimSpace(l[18:24]) velX := strings.TrimSpace(l[36:38]) velY := strings.TrimSpace(l[40:42]) positions = append(positions, [2]int{cast.ToInt(posX), cast.ToInt(posY)}) velocities = append(velocities, [2]int{cast.ToInt(velX), cast.ToInt(velY)}) } return positions, velocities } // this didn't work unfortunately, letters like K do have "lone islands" along // the diagonals func hasLoneIsland(grid [][2]int) bool { coords := map[[2]int]bool{} // generate map for _, pos := range grid { coords[pos] = true } // iterate through coords again and check if each has a neighbor in the map delta := [][2]int{ {-1, 0}, {1, 0}, {0, -1}, {0, 1}, } for _, pos := range grid { hasNeighbor := false for _, d := range delta { pos[0] += d[0] pos[1] += d[1] if coords[pos] { hasNeighbor = true } pos[0] -= d[0] pos[1] -= d[1] } if !hasNeighbor { return true // there is a lone island } } return false } func move(positions [][2]int, velocities [][2]int) { for i := range positions { positions[i][0] += velocities[i][0] positions[i][1] += velocities[i][1] } } func printGrid(positions [][2]int) string { // get bounds left := math.MaxInt16 right := -math.MaxInt16 top := math.MaxInt16 bottom := -math.MaxInt16 coords := map[[2]int]bool{} for _, p := range positions { coords[p] = true if p[0] < top { top = p[0] } if p[0] > bottom { bottom = p[0] } if p[1] < left { left = p[1] } if p[1] > right { right = p[1] } } if right-left > 20 && bottom-top > 20 { return "" } ans := "" for row := top; row <= bottom; row++ { for col := left; col <= right; col++ { if coords[[2]int{row, col}] { ans += "0" } else { ans += " " } } ans += "\n" } return ans }