174 lines
2.7 KiB
Go
174 lines
2.7 KiB
Go
|
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
|
||
|
}
|