2018 day 13 complete!
This commit is contained in:
parent
c94dfb5958
commit
52629a7b9c
@ -5,311 +5,145 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DIR_N = iota
|
DIR_N = -1i
|
||||||
DIR_E
|
DIR_E = 1
|
||||||
DIR_S
|
DIR_S = 1i
|
||||||
DIR_W
|
DIR_W = -1
|
||||||
DIR_ERR
|
|
||||||
|
|
||||||
TURN_L = iota
|
TURN_L = -1i
|
||||||
TURN_S
|
TURN_S = 1
|
||||||
TURN_R
|
TURN_R = 1i
|
||||||
TURN_ERR
|
|
||||||
|
|
||||||
ClearScreen = "\033[H\033[2J"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var course [][]Track
|
var width int
|
||||||
var carts []*Pos
|
var input []byte
|
||||||
|
var carts []*complex64
|
||||||
|
var cartMap map[complex64]*Cart
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
inp := StdinToStringSlice()
|
stdinToByteSlice()
|
||||||
part1(inp)
|
setupCarts()
|
||||||
|
//part1()
|
||||||
|
part2()
|
||||||
}
|
}
|
||||||
|
|
||||||
func part1(inp []string) {
|
func part1() {
|
||||||
course, carts = initScrubTrack(inp)
|
var crashed bool
|
||||||
var done bool
|
for !crashed {
|
||||||
for i := 0; ; i++ {
|
sort.Sort(ByPos(carts))
|
||||||
printState()
|
|
||||||
tick()
|
|
||||||
for _, c := range carts {
|
for _, c := range carts {
|
||||||
if c.dir == DIR_ERR {
|
if !cartMap[*c].tick() {
|
||||||
fmt.Println("= Part 1 =")
|
return
|
||||||
fmt.Println(c.string())
|
|
||||||
fmt.Println(i, "ticks")
|
|
||||||
done = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if done {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if i%1000000 == 0 {
|
|
||||||
fmt.Print(".")
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 250)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func tick() {
|
|
||||||
// sort the carts list by y/x
|
|
||||||
sort.Sort(ByPos(carts))
|
|
||||||
for _, c := range carts {
|
|
||||||
switch c.dir {
|
|
||||||
case DIR_N:
|
|
||||||
t := getTrackAt(c.x, c.y-1)
|
|
||||||
if t.goesDown() {
|
|
||||||
c.y--
|
|
||||||
if byte(t) == '+' {
|
|
||||||
c.chooseTurn()
|
|
||||||
} else if byte(t) == '\\' {
|
|
||||||
c.dir = DIR_W
|
|
||||||
} else if byte(t) == '/' {
|
|
||||||
c.dir = DIR_E
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case DIR_E:
|
|
||||||
t := getTrackAt(c.x+1, c.y)
|
|
||||||
if t.goesLeft() {
|
|
||||||
c.x++
|
|
||||||
if byte(t) == '+' {
|
|
||||||
c.chooseTurn()
|
|
||||||
} else if byte(t) == '/' {
|
|
||||||
c.dir = DIR_N
|
|
||||||
} else if byte(t) == '\\' {
|
|
||||||
c.dir = DIR_S
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case DIR_S:
|
|
||||||
t := getTrackAt(c.x, c.y+1)
|
|
||||||
if t.goesUp() {
|
|
||||||
c.y++
|
|
||||||
if byte(t) == '+' {
|
|
||||||
c.chooseTurn()
|
|
||||||
} else if byte(t) == '\\' {
|
|
||||||
c.dir = DIR_E
|
|
||||||
} else if byte(t) == '/' {
|
|
||||||
c.dir = DIR_W
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case DIR_W:
|
|
||||||
t := getTrackAt(c.x-1, c.y)
|
|
||||||
if t.goesRight() {
|
|
||||||
c.x--
|
|
||||||
if byte(t) == '+' {
|
|
||||||
c.chooseTurn()
|
|
||||||
} else if byte(t) == '/' {
|
|
||||||
c.dir = DIR_S
|
|
||||||
} else if byte(t) == '\\' {
|
|
||||||
c.dir = DIR_N
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTrackAt(x, y int) Track {
|
func part2() {
|
||||||
if x < 0 || y < 0 || y >= len(course) || x >= len(course[0]) {
|
for len(cartMap) > 1 {
|
||||||
return Track(' ')
|
sort.Sort(ByPos(carts))
|
||||||
}
|
for _, c := range carts {
|
||||||
return course[y][x]
|
if *c != 0 {
|
||||||
}
|
cartMap[*c].tick()
|
||||||
|
|
||||||
func findCrash() (Pos, bool) {
|
|
||||||
for _, c1 := range carts {
|
|
||||||
for _, c2 := range carts {
|
|
||||||
if c1 == c2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if c1.x == c2.x && c1.y == c2.y {
|
|
||||||
return Pos{x: c1.x, y: c1.y}, true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Pos{x: -1, y: -1}, false
|
for pos := range cartMap {
|
||||||
|
fmt.Printf("🔵: %0.0f,%0.0f\n", real(pos), imag(pos))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printState() {
|
type Cart struct {
|
||||||
fmt.Print(ClearScreen)
|
pos complex64
|
||||||
for y, v := range course {
|
dir complex64
|
||||||
for x, t := range v {
|
nextTurn complex64
|
||||||
var foundCarts []*Pos
|
}
|
||||||
for _, c := range carts {
|
|
||||||
if c.x == x && c.y == y {
|
// Tick the cart, return if it's still alive
|
||||||
foundCarts = append(foundCarts, c)
|
func (c *Cart) tick() bool {
|
||||||
}
|
// Remove this cart from it's old position
|
||||||
}
|
// and figure out it's new one
|
||||||
if len(foundCarts) == 0 {
|
delete(cartMap, c.pos)
|
||||||
fmt.Print(string(t))
|
c.pos += c.dir
|
||||||
} else if len(foundCarts) == 1 {
|
if cart, ok := cartMap[c.pos]; ok {
|
||||||
fmt.Print(string(foundCarts[0].getCartByte()))
|
fmt.Printf("❌: %0.0f,%0.0f\n", real(c.pos), imag(c.pos))
|
||||||
} else {
|
// Remove the cart we crashed into from the map
|
||||||
fmt.Print("X")
|
delete(cartMap, c.pos)
|
||||||
for _, c := range foundCarts {
|
// And clear the cart's pos, we can ignore them now
|
||||||
c.dir = DIR_ERR
|
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
|
||||||
}
|
}
|
||||||
fmt.Println("")
|
} 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
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pos struct {
|
// We have to sort the carts on each tick by y,x position
|
||||||
x, y int
|
// y is the imaginary part, x is the real part
|
||||||
dir int
|
type ByPos []*complex64
|
||||||
nextTurn int
|
|
||||||
|
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]))
|
||||||
}
|
}
|
||||||
|
|
||||||
type ByPos []*Pos
|
// getByte pulls a byte from the given position in the input
|
||||||
|
func getByte(pos complex64) byte {
|
||||||
func (b ByPos) Len() int { return len(b) }
|
return input[int(real(pos))+int(imag(pos))*width]
|
||||||
func (b ByPos) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
|
||||||
func (b ByPos) Less(i, j int) bool {
|
|
||||||
return b[i].y < b[j].y || (b[i].y == b[j].y && b[i].x < b[j].x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose a turn based on nextTurn and execute it
|
|
||||||
func (p *Pos) chooseTurn() {
|
|
||||||
if p.nextTurn == TURN_S {
|
|
||||||
p.nextTurn = TURN_R
|
|
||||||
} else if p.nextTurn == TURN_R {
|
|
||||||
p.turnRight()
|
|
||||||
p.nextTurn = TURN_L
|
|
||||||
} else { // Default to turn left
|
|
||||||
p.turnLeft()
|
|
||||||
p.nextTurn = TURN_S
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pos) turnLeft() {
|
|
||||||
p.dir--
|
|
||||||
if p.dir < DIR_N {
|
|
||||||
p.dir = DIR_W
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pos) turnRight() {
|
|
||||||
p.dir++
|
|
||||||
if p.dir > DIR_W {
|
|
||||||
p.dir = DIR_N
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pos) string() string {
|
|
||||||
return fmt.Sprintf("(%2d,%2d: %s)", p.x, p.y, string(p.getCartByte()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pos) getCartByte() byte {
|
|
||||||
switch p.dir {
|
|
||||||
case DIR_N:
|
|
||||||
return '^'
|
|
||||||
case DIR_E:
|
|
||||||
return '>'
|
|
||||||
case DIR_S:
|
|
||||||
return 'v'
|
|
||||||
case DIR_W:
|
|
||||||
return '<'
|
|
||||||
}
|
|
||||||
return ' '
|
|
||||||
}
|
|
||||||
|
|
||||||
type Track byte
|
|
||||||
|
|
||||||
func (t Track) isEmpty() bool {
|
|
||||||
return byte(t) == ' '
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Track) goesUp() bool {
|
|
||||||
return byte(t) == '|' || byte(t) == '/' || byte(t) == '\\' || byte(t) == '+'
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Track) goesDown() bool {
|
|
||||||
return byte(t) == '|' || byte(t) == '/' || byte(t) == '\\' || byte(t) == '+'
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Track) goesRight() bool {
|
|
||||||
return byte(t) == '-' || byte(t) == '\\' || byte(t) == '/' || byte(t) == '+'
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Track) goesLeft() bool {
|
|
||||||
return byte(t) == '-' || byte(t) == '\\' || byte(t) == '/' || byte(t) == '+'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization Functions
|
* Initialization Functions
|
||||||
*/
|
*/
|
||||||
// Scrub the track, return the track, sans carts, and all carts
|
func setupCarts() {
|
||||||
func initScrubTrack(inp []string) ([][]Track, []*Pos) {
|
cartMap = make(map[complex64]*Cart)
|
||||||
var carts []*Pos
|
for i := 0; i < len(input); i++ {
|
||||||
var course [][]Track
|
pos := complex(float32(i%width), float32(i/width))
|
||||||
for y, v := range inp {
|
switch getByte(pos) {
|
||||||
var row []Track
|
case '^':
|
||||||
for x, b := range v {
|
cartMap[pos] = &Cart{pos, DIR_N, TURN_L}
|
||||||
p := &Pos{x: x, y: y}
|
case '>':
|
||||||
switch b {
|
cartMap[pos] = &Cart{pos, DIR_E, TURN_L}
|
||||||
case 'v':
|
case 'v':
|
||||||
p.dir = DIR_S
|
cartMap[pos] = &Cart{pos, DIR_S, TURN_L}
|
||||||
carts = append(carts, p)
|
case '<':
|
||||||
case '^':
|
cartMap[pos] = &Cart{pos, DIR_W, TURN_L}
|
||||||
p.dir = DIR_N
|
default:
|
||||||
carts = append(carts, p)
|
continue // Not a cart
|
||||||
case '>':
|
|
||||||
p.dir = DIR_E
|
|
||||||
carts = append(carts, p)
|
|
||||||
case '<':
|
|
||||||
p.dir = DIR_W
|
|
||||||
carts = append(carts, p)
|
|
||||||
}
|
|
||||||
row = append(row, initGetTrack(inp, *p))
|
|
||||||
}
|
}
|
||||||
course = append(course, row)
|
carts = append(carts, &cartMap[pos].pos)
|
||||||
}
|
}
|
||||||
return course, carts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a track position
|
func stdinToByteSlice() {
|
||||||
func initGetTrack(inp []string, p Pos) Track {
|
|
||||||
if p.y < 0 || p.x < 0 || p.x > len(inp[0]) || p.y > len(inp) {
|
|
||||||
return Track(' ')
|
|
||||||
}
|
|
||||||
var bTop, bBot, bLft, bRgt Track
|
|
||||||
if initIsCart(inp, p) {
|
|
||||||
bTop = initGetTrack(inp, Pos{x: p.x, y: p.y - 1})
|
|
||||||
bBot = initGetTrack(inp, Pos{x: p.x, y: p.y + 1})
|
|
||||||
bLft = initGetTrack(inp, Pos{x: p.x - 1, y: p.y})
|
|
||||||
bRgt = initGetTrack(inp, Pos{x: p.x + 1, y: p.y})
|
|
||||||
if bTop.goesDown() && bLft.goesRight() && bRgt.goesLeft() && bBot.goesUp() {
|
|
||||||
return Track('+')
|
|
||||||
}
|
|
||||||
if (bTop.isEmpty() || bBot.isEmpty()) && bRgt.goesLeft() && bLft.goesRight() {
|
|
||||||
return Track('-')
|
|
||||||
}
|
|
||||||
if (bLft.isEmpty() || bRgt.isEmpty()) && bTop.goesDown() && bBot.goesUp() {
|
|
||||||
return Track('|')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Track(inp[p.y][p.x])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return if this position is a cart
|
|
||||||
func initIsCart(inp []string, p Pos) bool {
|
|
||||||
switch inp[p.y][p.x] {
|
|
||||||
case 'v', '^', '<', '>':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func StdinToStringSlice() []string {
|
|
||||||
var input []string
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
input = append(input, scanner.Text())
|
data := scanner.Bytes()
|
||||||
|
if width == 0 {
|
||||||
|
width = len(data)
|
||||||
|
}
|
||||||
|
input = append(input, data...)
|
||||||
}
|
}
|
||||||
return input
|
|
||||||
}
|
}
|
||||||
|
251
2018/day13/problem
Normal file
251
2018/day13/problem
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
Advent of Code
|
||||||
|
|
||||||
|
--- Day 13: Mine Cart Madness ---
|
||||||
|
|
||||||
|
A crop of this size requires significant logistics to transport produce, soil, fertilizer, and so on. The Elves are very busy pushing
|
||||||
|
things around in carts on some kind of rudimentary system of tracks they've come up with.
|
||||||
|
|
||||||
|
Seeing as how cart-and-track systems don't appear in recorded history for another 1000 years, the Elves seem to be making this up as
|
||||||
|
they go along. They haven't even figured out how to avoid collisions yet.
|
||||||
|
|
||||||
|
You map out the tracks (your puzzle input) and see where you can help.
|
||||||
|
|
||||||
|
Tracks consist of straight paths (| and -), curves (/ and \), and intersections (+). Curves connect exactly two perpendicular pieces
|
||||||
|
of track; for example, this is a closed loop:
|
||||||
|
|
||||||
|
/----\
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
\----/
|
||||||
|
|
||||||
|
Intersections occur when two perpendicular paths cross. At an intersection, a cart is capable of turning left, turning right, or
|
||||||
|
continuing straight. Here are two loops connected by two intersections:
|
||||||
|
|
||||||
|
/-----\
|
||||||
|
| |
|
||||||
|
| /--+--\
|
||||||
|
| | | |
|
||||||
|
\--+--/ |
|
||||||
|
| |
|
||||||
|
\-----/
|
||||||
|
|
||||||
|
Several carts are also on the tracks. Carts always face either up (^), down (v), left (<), or right (>). (On your initial map, the
|
||||||
|
track under each cart is a straight path matching the direction the cart is facing.)
|
||||||
|
|
||||||
|
Each time a cart has the option to turn (by arriving at any intersection), it turns left the first time, goes straight the second
|
||||||
|
time, turns right the third time, and then repeats those directions starting again with left the fourth time, straight the fifth
|
||||||
|
time, and so on. This process is independent of the particular intersection at which the cart has arrived - that is, the cart has no
|
||||||
|
per-intersection memory.
|
||||||
|
|
||||||
|
Carts all move at the same speed; they take turns moving a single step at a time. They do this based on their current location: carts
|
||||||
|
on the top row move first (acting from left to right), then carts on the second row move (again from left to right), then carts on
|
||||||
|
the third row, and so on. Once each cart has moved one step, the process repeats; each of these loops is called a tick.
|
||||||
|
|
||||||
|
For example, suppose there are two carts on a straight track:
|
||||||
|
|
||||||
|
| | | | |
|
||||||
|
v | | | |
|
||||||
|
| v v | |
|
||||||
|
| | | v X
|
||||||
|
| | ^ ^ |
|
||||||
|
^ ^ | | |
|
||||||
|
| | | | |
|
||||||
|
|
||||||
|
First, the top cart moves. It is facing down (v), so it moves down one square. Second, the bottom cart moves. It is facing up (^), so
|
||||||
|
it moves up one square. Because all carts have moved, the first tick ends. Then, the process repeats, starting with the first cart.
|
||||||
|
The first cart moves down, then the second cart moves up - right into the first cart, colliding with it! (The location of the crash
|
||||||
|
is marked with an X.) This ends the second and last tick.
|
||||||
|
|
||||||
|
Here is a longer example:
|
||||||
|
|
||||||
|
/->-\
|
||||||
|
| | /----\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | | v |
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/-->\
|
||||||
|
| | /----\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \->--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---v
|
||||||
|
| | /----\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-+>-/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| v /----\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-+->/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /----\
|
||||||
|
| /->--+-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-+--^
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /----\
|
||||||
|
| /-+>-+-\ |
|
||||||
|
| | | | | ^
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /----\
|
||||||
|
| /-+->+-\ ^
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /----<
|
||||||
|
| /-+-->-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /---<\
|
||||||
|
| /-+--+>\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /--<-\
|
||||||
|
| /-+--+-v |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /-<--\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | | v |
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /<---\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \-<--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | v----\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ \<+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /----\
|
||||||
|
| /-+--v-\ |
|
||||||
|
| | | | | |
|
||||||
|
\-+-/ ^-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| | /----\
|
||||||
|
| /-+--+-\ |
|
||||||
|
| | | X | |
|
||||||
|
\-+-/ \-+--/
|
||||||
|
\------/
|
||||||
|
|
||||||
|
After following their respective paths for a while, the carts eventually crash. To help prevent crashes, you'd like to know the
|
||||||
|
location of the first crash. Locations are given in X,Y coordinates, where the furthest left column is X=0 and the furthest top row
|
||||||
|
is Y=0:
|
||||||
|
|
||||||
|
111
|
||||||
|
0123456789012
|
||||||
|
0/---\
|
||||||
|
1| | /----\
|
||||||
|
2| /-+--+-\ |
|
||||||
|
3| | | X | |
|
||||||
|
4\-+-/ \-+--/
|
||||||
|
5 \------/
|
||||||
|
|
||||||
|
In this example, the location of the first crash is 7,3.
|
||||||
|
|
||||||
|
Your puzzle answer was 83,106.
|
||||||
|
|
||||||
|
--- Part Two ---
|
||||||
|
|
||||||
|
There isn't much you can do to prevent crashes in this ridiculous system. However, by predicting the crashes, the Elves know where to
|
||||||
|
be in advance and instantly remove the two crashing carts the moment any crash occurs.
|
||||||
|
|
||||||
|
They can proceed like this for a while, but eventually, they're going to run out of carts. It could be useful to figure out where the
|
||||||
|
last cart that hasn't crashed will end up.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
/>-<\
|
||||||
|
| |
|
||||||
|
| /<+-\
|
||||||
|
| | | v
|
||||||
|
\>+</ |
|
||||||
|
| ^
|
||||||
|
\<->/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| |
|
||||||
|
| v-+-\
|
||||||
|
| | | |
|
||||||
|
\-+-/ |
|
||||||
|
| |
|
||||||
|
^---^
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| |
|
||||||
|
| /-+-\
|
||||||
|
| v | |
|
||||||
|
\-+-/ |
|
||||||
|
^ ^
|
||||||
|
\---/
|
||||||
|
|
||||||
|
/---\
|
||||||
|
| |
|
||||||
|
| /-+-\
|
||||||
|
| | | |
|
||||||
|
\-+-/ ^
|
||||||
|
| |
|
||||||
|
\---/
|
||||||
|
|
||||||
|
After four very expensive crashes, a tick ends with only one cart remaining; its final location is 6,4.
|
||||||
|
|
||||||
|
What is the location of the last cart at the end of the first tick where it is the only cart left?
|
||||||
|
|
||||||
|
Your puzzle answer was 132,26.
|
||||||
|
|
||||||
|
Both parts of this puzzle are complete! They provide two gold stars: **
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links
|
||||||
|
. https://adventofcode.com/
|
||||||
|
. https://adventofcode.com/2018/about
|
||||||
|
. https://adventofcode.com/2018/events
|
||||||
|
. https://adventofcode.com/2018/settings
|
||||||
|
. https://adventofcode.com/2018/auth/logout
|
||||||
|
. Advent of Code Supporter
|
||||||
|
https://adventofcode.com/2018/support
|
||||||
|
. https://adventofcode.com/2018
|
||||||
|
. https://adventofcode.com/2018
|
||||||
|
. https://adventofcode.com/2018/support
|
||||||
|
. https://adventofcode.com/2018/sponsors
|
||||||
|
. https://adventofcode.com/2018/leaderboard
|
||||||
|
. https://adventofcode.com/2018/stats
|
||||||
|
. https://adventofcode.com/2018/sponsors
|
||||||
|
. https://adventofcode.com/2018
|
||||||
|
. https://adventofcode.com/2018/day/13/input
|
Loading…
Reference in New Issue
Block a user