adventofcode/2018/day10/day10.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
}