Files
advent-of-code-go/2018/day10/main.go
T

159 lines
2.9 KiB
Go

package main
import (
"flag"
"fmt"
"math"
"strings"
"time"
"github.com/alexchao26/advent-of-code-go/cast"
"github.com/alexchao26/advent-of-code-go/util"
)
func main() {
var part int
flag.IntVar(&part, "part", 1, "part 1 or 2")
flag.Parse()
fmt.Println("Running part", part)
if part == 1 {
part1(util.ReadFile("./input.txt"))
} else {
part2(util.ReadFile("./input.txt"))
}
}
func part1(input string) {
postions, velocities := parseInputs(input)
steps := 0
prints := 0
hasPrinted := false
for hasLoneIsland(postions) {
move(postions, velocities)
steps++
fmt.Println("\nsteps run", steps)
printable := printGrid(postions)
if printable != "" {
fmt.Println("Steps: ", steps)
fmt.Println(printable)
time.Sleep(time.Millisecond * 500)
hasPrinted = true
}
// stop printing after things have collided
if printable == "" && hasPrinted {
return
}
fmt.Println(prints)
}
}
func part2(input string) {
// Note, reused part 1 with a print for the number of steps
part1(input)
}
func parseInputs(input string) (positions [][2]int, velocities [][2]int) {
lines := strings.Split(input, "\n")
for _, l := range lines {
posX := strings.TrimSpace(l[10:16])
posY := strings.TrimSpace(l[18:24])
velX := strings.TrimSpace(l[36:38])
velY := strings.TrimSpace(l[40:42])
positions = append(positions, [2]int{cast.ToInt(posX), cast.ToInt(posY)})
velocities = append(velocities, [2]int{cast.ToInt(velX), cast.ToInt(velY)})
}
return positions, velocities
}
// this didn't work unfortunately, letters like K do have "lone islands" along
// the diagonals
func hasLoneIsland(grid [][2]int) bool {
coords := map[[2]int]bool{}
// generate map
for _, pos := range grid {
coords[pos] = true
}
// iterate through coords again and check if each has a neighbor in the map
delta := [][2]int{
{-1, 0},
{1, 0},
{0, -1},
{0, 1},
}
for _, pos := range grid {
hasNeighbor := false
for _, d := range delta {
pos[0] += d[0]
pos[1] += d[1]
if coords[pos] {
hasNeighbor = true
}
pos[0] -= d[0]
pos[1] -= d[1]
}
if !hasNeighbor {
return true // there is a lone island
}
}
return false
}
func move(positions [][2]int, velocities [][2]int) {
for i := range positions {
positions[i][0] += velocities[i][0]
positions[i][1] += velocities[i][1]
}
}
func printGrid(positions [][2]int) string {
// get bounds
left := math.MaxInt16
right := -math.MaxInt16
top := math.MaxInt16
bottom := -math.MaxInt16
coords := map[[2]int]bool{}
for _, p := range positions {
coords[p] = true
if p[0] < top {
top = p[0]
}
if p[0] > bottom {
bottom = p[0]
}
if p[1] < left {
left = p[1]
}
if p[1] > right {
right = p[1]
}
}
if right-left > 20 && bottom-top > 20 {
return ""
}
ans := ""
for row := top; row <= bottom; row++ {
for col := left; col <= right; col++ {
if coords[[2]int{row, col}] {
ans += "0"
} else {
ans += " "
}
}
ans += "\n"
}
return ans
}