package main import ( "bufio" "fmt" "image" "image/color" "image/png" "os" "strconv" "time" ) const FILE_PATH = "./input.txt" const WIDTH = 101 const HEIGHT = 103 //const FILE_PATH = "./sample.txt" //const WIDTH = 11 //const HEIGHT = 7 func LoadInput(filename string) ([]string, error) { file, err := os.Open(filename) if err != nil { return nil, err } defer file.Close() var lines []string scanner := bufio.NewScanner(file) for scanner.Scan() { lines = append(lines, scanner.Text()) } if err := scanner.Err(); err != nil { return nil, err } return lines, nil } type Vector2 struct { x int y int } type Robot struct { p Vector2 v Vector2 } type structuredInput = []Robot func TransformInput(lines []string) structuredInput { var result = make([]Robot, 0) var j int var m int var numbX int var numbY int var position Vector2 var temp Robot for i := 0; i < len(lines); i++ { j = 2 for ; j < len(lines[i]); j++ { if lines[i][j] == ',' { break } } numbX, _ = strconv.Atoi(lines[i][2:j]) m = j + 1 for ; j < len(lines[i]); j++ { if lines[i][j] == ' ' { break } } numbY, _ = strconv.Atoi(lines[i][m:j]) position = Vector2{numbX, numbY} m = j + 3 for ; j < len(lines[i]); j++ { if lines[i][j] == ',' { break } } numbX, _ = strconv.Atoi(lines[i][m:j]) numbY, _ = strconv.Atoi(lines[i][j+1:]) temp = Robot{position, Vector2{numbX, numbY}} result = append(result, temp) } return result } func Part1(input structuredInput) int { var result = 0 var robots = make([]Robot, 0) var temp Robot for _, robot := range input { temp = Robot{Vector2{robot.p.x, robot.p.y}, Vector2{robot.v.x, robot.v.y}} robots = append(robots, temp) } for i := 0; i < len(input); i++ { robots[i].p.x += 100 * robots[i].v.x robots[i].p.y += 100 * robots[i].v.y for robots[i].p.x < 0 { robots[i].p.x += WIDTH } for robots[i].p.y < 0 { robots[i].p.y += HEIGHT } for robots[i].p.x >= WIDTH { robots[i].p.x -= WIDTH } for robots[i].p.y >= HEIGHT { robots[i].p.y -= HEIGHT } } var count = 0 var quads = make([]int, 0) for offsetY := 0; offsetY < 2; offsetY++ { for offsetX := 0; offsetX < 2; offsetX++ { count = 0 for y := 0 + (offsetY * (HEIGHT/2 + 1)); y < (HEIGHT/2)+(offsetY*(HEIGHT/2+1)); y++ { for x := 0 + (offsetX * (WIDTH/2 + 1)); x < (WIDTH/2)+(offsetX*(WIDTH/2+1)); x++ { for _, robot := range robots { if robot.p.x == x && robot.p.y == y { count++ } } } } quads = append(quads, count) } } result = 1 for _, quadCount := range quads { result *= quadCount } return result } func simulateSecond(robots []Robot) []Robot { for i := 0; i < len(robots); i++ { robots[i].p.x += robots[i].v.x robots[i].p.y += robots[i].v.y for robots[i].p.x < 0 { robots[i].p.x += WIDTH } for robots[i].p.y < 0 { robots[i].p.y += HEIGHT } for robots[i].p.x >= WIDTH { robots[i].p.x -= WIDTH } for robots[i].p.y >= HEIGHT { robots[i].p.y -= HEIGHT } } return robots } func Part2(input structuredInput) int { var result = 0 var robots = make([]Robot, 0) var temp Robot var count int for _, robot := range input { temp = Robot{Vector2{robot.p.x, robot.p.y}, Vector2{robot.v.x, robot.v.y}} robots = append(robots, temp) } var img *image.Gray for i := 0; i < 10000; i++ { img = image.NewGray(image.Rect(0, 0, WIDTH, HEIGHT)) robots = simulateSecond(robots) count = 0 for y := 0; y < HEIGHT; y++ { for x := 0; x < WIDTH; x++ { count = 0 for _, robot := range robots { if robot.p.x == x && robot.p.y == y { count++ } } if count == 0 { img.Set(x, y, color.White) } else { img.Set(x, y, color.Black) } } } f, _ := os.Create("./images/" + strconv.Itoa(i+1) + ".png") defer f.Close() png.Encode(f, img) } // Find result manualy result = 6876 return result } func main() { var start time.Time var elapsed time.Duration = 0 input, err := LoadInput(FILE_PATH) if err != nil { fmt.Println("Error loading input:", err) return } structuredInput := TransformInput(input) fmt.Println("Structured Input:", structuredInput) start = time.Now() fmt.Println("Solution Part 1: ", Part1(structuredInput)) elapsed = time.Since(start) fmt.Printf("Part 1 took %s\n", elapsed) start = time.Now() fmt.Println("Solution Part 2: ", Part2(structuredInput)) elapsed = time.Since(start) fmt.Printf("Part 2 took %s\n", elapsed) }