167 lines
3.3 KiB
Go
167 lines
3.3 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||
|
)
|
||
|
|
||
|
var sleepTime = (time.Second / 5)
|
||
|
|
||
|
var minx, miny, maxx, maxy int
|
||
|
|
||
|
func main() {
|
||
|
inp := h.StdinToStringSlice()
|
||
|
|
||
|
watch := len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "-w")
|
||
|
if watch {
|
||
|
if strings.Contains(os.Args[1], "=") {
|
||
|
pts := strings.Split(os.Args[1], "=")
|
||
|
sleepTime = (time.Second / time.Duration(h.Atoi(pts[1])))
|
||
|
}
|
||
|
}
|
||
|
simulate(inp, 10, watch)
|
||
|
}
|
||
|
|
||
|
func buildInstructions(inp []string) []byte {
|
||
|
var inst []byte
|
||
|
for i := range inp {
|
||
|
dir, count := inp[i][0], h.Atoi(inp[i][2:])
|
||
|
for j := 0; j < count; j++ {
|
||
|
inst = append(inst, dir)
|
||
|
}
|
||
|
}
|
||
|
return inst
|
||
|
}
|
||
|
|
||
|
func simulate(inp []string, knotCount int, watch bool) {
|
||
|
if watch {
|
||
|
fmt.Print(h.CLEAR_SCREEN)
|
||
|
}
|
||
|
visited := make(map[h.Coordinate]bool)
|
||
|
inst := buildInstructions(inp)
|
||
|
var knots []h.Coordinate
|
||
|
for i := 0; i < knotCount; i++ {
|
||
|
knots = append(knots, h.Coordinate{X: 0, Y: 0})
|
||
|
}
|
||
|
if watch {
|
||
|
fmt.Println("# Part 1")
|
||
|
printVisits(visited, knots)
|
||
|
}
|
||
|
for i, dir := range inst {
|
||
|
moveHead(dir, knots)
|
||
|
visited[knots[len(knots)-1]] = true
|
||
|
if watch {
|
||
|
time.Sleep(sleepTime)
|
||
|
fmt.Print(h.CLEAR_SCREEN)
|
||
|
fmt.Printf("# Part 1 (%d/%d)\n", i, len(inst))
|
||
|
printVisits(visited, knots)
|
||
|
}
|
||
|
}
|
||
|
if watch {
|
||
|
time.Sleep(sleepTime)
|
||
|
fmt.Print(h.CLEAR_SCREEN)
|
||
|
}
|
||
|
fmt.Println("# Part 1")
|
||
|
if watch {
|
||
|
printVisits(visited, knots)
|
||
|
}
|
||
|
fmt.Printf("Tail visited %d positions\n", len(visited))
|
||
|
}
|
||
|
|
||
|
func moveHead(dir byte, knots []h.Coordinate) {
|
||
|
prevKnots := make([]h.Coordinate, len(knots))
|
||
|
copy(prevKnots, knots)
|
||
|
switch dir {
|
||
|
case 'U':
|
||
|
knots[0] = knots[0].North()
|
||
|
case 'R':
|
||
|
knots[0] = knots[0].East()
|
||
|
case 'D':
|
||
|
knots[0] = knots[0].South()
|
||
|
case 'L':
|
||
|
knots[0] = knots[0].West()
|
||
|
}
|
||
|
if knots[0].X < minx {
|
||
|
minx = knots[0].X
|
||
|
}
|
||
|
if knots[0].X > maxx {
|
||
|
maxx = knots[0].X
|
||
|
}
|
||
|
if knots[0].Y < miny {
|
||
|
miny = knots[0].Y
|
||
|
}
|
||
|
if knots[0].Y > maxy {
|
||
|
maxy = knots[0].Y
|
||
|
}
|
||
|
for i := 1; i < len(knots); i++ {
|
||
|
// Go through all knots and check if any need to move
|
||
|
if !knots[i].Equals(knots[i-1]) && !knots[i].Adjacent(knots[i-1]) {
|
||
|
if knots[i].X == knots[i-1].X {
|
||
|
// Same column
|
||
|
if knots[i].Y < knots[i-1].Y {
|
||
|
knots[i].Y++
|
||
|
} else {
|
||
|
knots[i].Y--
|
||
|
}
|
||
|
} else if knots[i].Y == knots[i-1].Y {
|
||
|
// Save row
|
||
|
if knots[i].X < knots[i-1].X {
|
||
|
knots[i].X++
|
||
|
} else {
|
||
|
knots[i].X--
|
||
|
}
|
||
|
} else {
|
||
|
// Not in the same row or column
|
||
|
if knots[i].X < knots[i-1].X {
|
||
|
knots[i].X++
|
||
|
} else {
|
||
|
knots[i].X--
|
||
|
}
|
||
|
if knots[i].Y < knots[i-1].Y {
|
||
|
knots[i].Y++
|
||
|
} else {
|
||
|
knots[i].Y--
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
// If one knot didn't need to move, none behind it will
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func printVisits(m map[h.Coordinate]bool, knots []h.Coordinate) {
|
||
|
for y := miny; y <= maxy; y++ {
|
||
|
for x := minx; x <= maxx; x++ {
|
||
|
var isKnot bool
|
||
|
for i := range knots {
|
||
|
if knots[i].X == x && knots[i].Y == y {
|
||
|
isKnot = true
|
||
|
var bt byte
|
||
|
if i == 0 {
|
||
|
bt = 'H'
|
||
|
} else {
|
||
|
bt = '0' + byte(i)
|
||
|
}
|
||
|
fmt.Print(string(bt))
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if !isKnot {
|
||
|
if v, ok := m[h.Coordinate{X: x, Y: y}]; ok && v {
|
||
|
fmt.Print("#")
|
||
|
} else {
|
||
|
fmt.Print(".")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fmt.Println()
|
||
|
}
|
||
|
fmt.Printf("Bridge: %s\n", knots)
|
||
|
fmt.Println()
|
||
|
}
|