package day14 import ( "fmt" "strconv" "strings" ) type Robot struct { px, py int // position vx, vy int // velocity } func Part1(input string) int { // Parse the input lines := strings.Split(input, "\n") var robots []Robot for _, line := range lines { robot := ParseRobot(line) robots = append(robots, robot) } // Define grid size gridWidth := 101 gridHeight := 103 // Update robot positions for 100 seconds for i := 0; i < 100; i++ { for j := range robots { robots[j].UpdatePosition(gridWidth, gridHeight) } } // Count the robots in each quadrant q1, q2, q3, q4 := CountRobotsInQuadrants(robots, gridWidth, gridHeight) fmt.Printf("Quadrant counts: Q1=%d, Q2=%d, Q3=%d, Q4=%d\n", q1, q2, q3, q4) // Calculate the safety factor safetyFactor := CalculateSafetyFactor(q1, q2, q3, q4) fmt.Printf("Safety Factor: %d\n", safetyFactor) return safetyFactor } func Part2(input string) int { // Parse the input lines := strings.Split(input, "\n") var robots []Robot for _, line := range lines { robot := ParseRobot(line) robots = append(robots, robot) } // Define grid size gridWidth := 101 gridHeight := 103 // Update robot positions for 100 seconds for i := 0; i < 6285; i++ { for j := range robots { robots[j].UpdatePosition(gridWidth, gridHeight) } } DisplayGrid(robots, gridWidth, gridHeight) return 2 } // ParseRobot takes a line of input and converts it to a Robot struct func ParseRobot(line string) Robot { parts := strings.Split(line, " ") posParts := strings.Split(parts[0][2:], ",") // Extract p=x,y and split velParts := strings.Split(parts[1][2:], ",") // Extract v=x,y and split px, _ := strconv.Atoi(posParts[0]) py, _ := strconv.Atoi(posParts[1]) vx, _ := strconv.Atoi(velParts[0]) vy, _ := strconv.Atoi(velParts[1]) return Robot{px, py, vx, vy} } // UpdatePosition updates the position of a robot, considering the wrap-around func (r *Robot) UpdatePosition(gridWidth, gridHeight int) { r.px = (r.px + r.vx + gridWidth) % gridWidth r.py = (r.py + r.vy + gridHeight) % gridHeight } // CountRobotsInQuadrants counts the number of robots in each of the four quadrants func CountRobotsInQuadrants(robots []Robot, width, height int) (int, int, int, int) { midX := width / 2 midY := height / 2 q1, q2, q3, q4 := 0, 0, 0, 0 for _, r := range robots { if r.px == midX || r.py == midY { // Skip robots on the middle line continue } if r.px < midX && r.py < midY { q1++ // Top-left quadrant } else if r.px > midX && r.py < midY { q2++ // Top-right quadrant } else if r.px < midX && r.py > midY { q3++ // Bottom-left quadrant } else if r.px > midX && r.py > midY { q4++ // Bottom-right quadrant } } return q1, q2, q3, q4 } // CalculateSafetyFactor multiplies the number of robots in each quadrant func CalculateSafetyFactor(q1, q2, q3, q4 int) int { return q1 * q2 * q3 * q4 } // DisplayGrid displays the current state of the grid func DisplayGrid(robots []Robot, width, height int) { grid := make([][]rune, height) for i := range grid { grid[i] = make([]rune, width) for j := range grid[i] { grid[i][j] = '.' } } for _, r := range robots { grid[r.py][r.px] = '#' } for _, row := range grid { fmt.Println(string(row)) } } // FindEasterEgg determines the fewest number of seconds that must elapse for the robots to display the Easter egg func FindEasterEgg(robots []Robot, width, height int) int { smallestArea := width * height bestTime := 0 for t := 6285; t < 6286; t++ { // Large upper limit to search // Update robot positions for i := range robots { robots[i].UpdatePosition(width, height) } // Calculate the bounding box of all robot positions minX, minY := width, height maxX, maxY := 0, 0 for _, r := range robots { if r.px < minX { minX = r.px } if r.px > maxX { maxX = r.px } if r.py < minY { minY = r.py } if r.py > maxY { maxY = r.py } } area := (maxX - minX + 1) * (maxY - minY + 1) if area < smallestArea { smallestArea = area bestTime = t + 1 fmt.Printf("Time: %d\n", bestTime) DisplayGrid(robots, width, height) } } return bestTime }