package main import ( "bufio" "fmt" "log" "os" "strconv" "strings" ) const ( MaxInt = int(^uint(0) >> 1) MinInt = -MaxInt - 1 ClearScreen = "\033[H\033[2J" ) var sky *Sky func main() { inp := StdinToStringSlice() buildSky(inp) part1() } func buildSky(inp []string) { sky = &Sky{ minPos: Pos{x: MaxInt, y: MaxInt}, maxPos: Pos{x: MinInt, y: MinInt}, } for _, v := range inp { sky.addStar(v) } } func part1() { for i := 1; i < 100000; i++ { sky.tick() if sky.maxPos.y-sky.minPos.y <= 10 { sky.printSky() fmt.Println("Seconds:", i) break } } } type Sky struct { stars []*Star minPos, maxPos Pos } func (s *Sky) tick() { s.setMinPosX(MaxInt) s.setMinPosY(MaxInt) s.setMaxPosX(MinInt) s.setMaxPosY(MinInt) for _, v := range s.stars { v.tick() s.considerStar(v) } } func (s *Sky) considerStar(v *Star) { if v.position.x < s.minPos.x { s.setMinPosX(v.position.x) } if v.position.y < s.minPos.y { s.setMinPosY(v.position.y) } if v.position.x > s.maxPos.x { s.setMaxPosX(v.position.x) } if v.position.y > s.maxPos.y { s.setMaxPosY(v.position.y) } } func (s *Sky) starAt(p *Pos) bool { for _, v := range s.stars { if p.equals(v.position) { return true } } return false } func (s *Sky) printSky() { for i := s.minPos.y; i <= s.maxPos.y; i++ { for j := s.minPos.x; j <= s.maxPos.x; j++ { if s.starAt(&Pos{x: j, y: i}) { fmt.Print("*") } else { fmt.Print(" ") } } fmt.Println("") } } func (s *Sky) addStar(inp string) { v := NewStar(inp) s.stars = append(s.stars, v) s.considerStar(v) } func (s *Sky) setMinPosX(x int) { s.minPos.x = x } func (s *Sky) setMinPosY(y int) { s.minPos.y = y } func (s *Sky) setMaxPosX(x int) { s.maxPos.x = x } func (s *Sky) setMaxPosY(y int) { s.maxPos.y = y } type Star struct { position *Pos velocity *Pos } func NewStar(inp string) *Star { inp = inp[10:] pts := strings.Split(inp, ">") posStr := pts[0] velStr := pts[1][11:len(pts[1])] return &Star{ position: NewPos(posStr), velocity: NewPos(velStr), } } func (s *Star) tick() { s.position.x += s.velocity.x s.position.y += s.velocity.y } type Pos struct { x, y int } func NewPos(inp string) *Pos { pts := strings.Split(inp, ", ") return &Pos{ x: Atoi(strings.TrimSpace(pts[0])), y: Atoi(strings.TrimSpace(pts[1])), } } func (p *Pos) equals(o *Pos) bool { return p.x == o.x && p.y == o.y } func StdinToStringSlice() []string { var input []string scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { input = append(input, scanner.Text()) } return input } func Atoi(i string) int { var ret int var err error if ret, err = strconv.Atoi(i); err != nil { fmt.Println(err.Error()) log.Fatal("Invalid Atoi" + i) } return ret }