package main import ("os"; "strings"; "fmt"; "strconv"; "regexp") type Board struct { width uint8 height uint8 } type Robot struct { x uint8 y uint8 vx int8 vy int8 } func (r Robot) Step(b Board, n uint) Robot { pos_vx := int(r.vx) pos_vy := int(r.vy) if pos_vx < 0 { pos_vx = int(b.width) + pos_vx } if pos_vy < 0 { pos_vy = int(b.height) + pos_vy } new_x := uint( uint(r.x) + uint(pos_vx) * n ) % uint(b.width) new_y := uint( uint(r.y) + uint(pos_vy) * n ) % uint(b.height) return Robot{uint8(new_x), uint8(new_y), r.vx, r.vy} } func check(e error) { if e != nil { panic(e) } } func abs(n int) uint { if n < 0 { return uint(-n) } return uint(n) } func NewRobot(line string) Robot { pattern := regexp.MustCompile(`-?\d+`) matches := pattern.FindAllString(line, -1) numbers := [4]int{} for i, match := range matches { num, err := strconv.Atoi(match) check(err) numbers[i] = num } return Robot{uint8(numbers[0]), uint8(numbers[1]), int8(numbers[2]), int8(numbers[3])} } func print_board(rs []Robot, b Board) { num_fields := int(b.width) * int(b.height) str := make([]byte, 0, num_fields + int(b.height) + 1) for i := range num_fields + int(b.height) { switch { case (i + 1) % (int(b.width) + 1) == 0: str = append(str, '\n') default: str = append(str, '.') } } str = append(str, 0) for _, r := range rs { offset := int(r.y) * int(b.width + 1) + int(r.x) str[offset] = '#' } fmt.Println(string(str)) } func main() { dat, err := os.ReadFile("data.txt") check(err) lines := strings.Split(strings.TrimSpace(string(dat)), "\n") board := Board{width: 101, height: 103} robots := make([]Robot, 0, 100) for _, line := range lines { robots = append(robots, NewRobot(line)) } // run simulation for i := range 10000 { for j := range robots { robots[j] = robots[j].Step(board, 1) } fmt.Println("------------\nafter", i, "seconds") print_board(robots, board) } }