adventofcode/2018/day13/day13.go

150 lines
2.9 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"sort"
)
const (
DIR_N = -1i
DIR_E = 1
DIR_S = 1i
DIR_W = -1
TURN_L = -1i
TURN_S = 1
TURN_R = 1i
)
var width int
var input []byte
var carts []*complex64
var cartMap map[complex64]*Cart
func main() {
stdinToByteSlice()
setupCarts()
//part1()
part2()
}
func part1() {
var crashed bool
for !crashed {
sort.Sort(ByPos(carts))
for _, c := range carts {
if !cartMap[*c].tick() {
return
}
}
}
}
func part2() {
for len(cartMap) > 1 {
sort.Sort(ByPos(carts))
for _, c := range carts {
if *c != 0 {
cartMap[*c].tick()
}
}
}
for pos := range cartMap {
fmt.Printf("🔵: %0.0f,%0.0f\n", real(pos), imag(pos))
}
}
type Cart struct {
pos complex64
dir complex64
nextTurn complex64
}
// Tick the cart, return if it's still alive
func (c *Cart) tick() bool {
// Remove this cart from it's old position
// and figure out it's new one
delete(cartMap, c.pos)
c.pos += c.dir
if cart, ok := cartMap[c.pos]; ok {
fmt.Printf("❌: %0.0f,%0.0f\n", real(c.pos), imag(c.pos))
// Remove the cart we crashed into from the map
delete(cartMap, c.pos)
// And clear the cart's pos, we can ignore them now
cart.pos, c.pos = 0, 0
return false
}
// No crash, figure out the new orientation of the cart
cartMap[c.pos] = c
if getByte(c.pos) == '+' {
c.dir *= c.nextTurn
switch c.nextTurn {
case TURN_L:
c.nextTurn = TURN_S
case TURN_S:
c.nextTurn = TURN_R
case TURN_R:
c.nextTurn = TURN_L
}
} else if getByte(c.pos) == '/' {
// Turn counter-clockwise
c.dir = complex(-imag(c.dir), -real(c.dir))
} else if getByte(c.pos) == '\\' {
// Turn clockwise
c.dir = complex(imag(c.dir), real(c.dir))
}
return true
}
// We have to sort the carts on each tick by y,x position
// y is the imaginary part, x is the real part
type ByPos []*complex64
func (c ByPos) Len() int { return len(c) }
func (c ByPos) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c ByPos) Less(i, j int) bool {
return imag(*c[i]) < imag(*c[j]) ||
(imag(*c[i]) == imag(*c[j]) && real(*c[i]) < real(*c[j]))
}
// getByte pulls a byte from the given position in the input
func getByte(pos complex64) byte {
return input[int(real(pos))+int(imag(pos))*width]
}
/**
* Initialization Functions
*/
func setupCarts() {
cartMap = make(map[complex64]*Cart)
for i := 0; i < len(input); i++ {
pos := complex(float32(i%width), float32(i/width))
switch getByte(pos) {
case '^':
cartMap[pos] = &Cart{pos, DIR_N, TURN_L}
case '>':
cartMap[pos] = &Cart{pos, DIR_E, TURN_L}
case 'v':
cartMap[pos] = &Cart{pos, DIR_S, TURN_L}
case '<':
cartMap[pos] = &Cart{pos, DIR_W, TURN_L}
default:
continue // Not a cart
}
carts = append(carts, &cartMap[pos].pos)
}
}
func stdinToByteSlice() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
data := scanner.Bytes()
if width == 0 {
width = len(data)
}
input = append(input, data...)
}
}