mirror of
https://github.com/onyx-and-iris/aoc2023.git
synced 2024-11-15 15:10:49 +00:00
145 lines
3.9 KiB
Go
145 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type coords struct {
|
|
X int
|
|
Y int
|
|
}
|
|
|
|
type points struct {
|
|
points []point
|
|
}
|
|
|
|
type point struct {
|
|
N bool
|
|
S bool
|
|
E bool
|
|
W bool
|
|
coords
|
|
identifier rune
|
|
}
|
|
|
|
var pointsArray = []points{}
|
|
|
|
type tracker struct {
|
|
init point
|
|
point point
|
|
last []coords
|
|
steps int
|
|
}
|
|
|
|
// newTracker stores the starting point
|
|
// it creates a queue for storing past 2 moves
|
|
// returns a tracker struct for counting steps
|
|
func newTracker() tracker {
|
|
tracker := tracker{last: make([]coords, 0)}
|
|
for _, each := range pointsArray {
|
|
for _, point := range each.points {
|
|
if point.identifier == 'S' {
|
|
tracker.init = point
|
|
tracker.point = tracker.init
|
|
tracker.last = make([]coords, 1)
|
|
tracker.last = append(tracker.last, tracker.point.coords)
|
|
}
|
|
}
|
|
}
|
|
return tracker
|
|
}
|
|
|
|
func (t tracker) X() int {
|
|
return t.point.X
|
|
}
|
|
|
|
func (t tracker) Y() int {
|
|
return t.point.Y
|
|
}
|
|
|
|
// mapPoints builds the points array mapping connection types for each coordinate
|
|
func mapPoints(lines []string) {
|
|
pointsArray = make([]points, 0)
|
|
|
|
for i, line := range lines {
|
|
var ps = make([]point, 0)
|
|
for j, r := range line {
|
|
switch r {
|
|
case '|':
|
|
ps = append(ps, point{N: true, S: true, E: false, W: false}) // N,S
|
|
case '-':
|
|
ps = append(ps, point{N: false, S: false, E: true, W: true}) // E, W
|
|
case 'L':
|
|
ps = append(ps, point{N: true, S: false, E: true, W: false}) // N, E
|
|
case 'J':
|
|
ps = append(ps, point{N: true, S: false, E: false, W: true}) // N, W
|
|
case '7':
|
|
ps = append(ps, point{N: false, S: true, E: false, W: true}) // S, W
|
|
case 'F':
|
|
ps = append(ps, point{N: false, S: true, E: true, W: false}) // S, E
|
|
case '.':
|
|
ps = append(ps, point{N: false, S: false, E: false, W: false}) // ground
|
|
case 'S':
|
|
ps = append(ps, point{N: true, S: true, E: true, W: true}) // start
|
|
default:
|
|
log.Debug("ground point")
|
|
}
|
|
ps[j].identifier = r
|
|
ps[j].coords.Y = i
|
|
ps[j].coords.X = j
|
|
}
|
|
pointsArray = append(pointsArray, points{points: ps})
|
|
}
|
|
}
|
|
|
|
// walk moves along the pipes storing poinst that mark loop locations
|
|
// it also keeps a track of last two moves
|
|
// returns the number of steps to traverse all pipes
|
|
func walk(tracker tracker) int {
|
|
for ; tracker.steps == 0 || !comparePoints(tracker.init, tracker.point); tracker.steps++ {
|
|
next := checkSouth(tracker.point)
|
|
if !inLastMoves(tracker.last, next.coords) {
|
|
log.Debug("moving south from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
|
tracker.point = next
|
|
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
|
tracker.last = append(tracker.last[1:], next.coords)
|
|
continue
|
|
}
|
|
next = checkEast(tracker.point)
|
|
if !inLastMoves(tracker.last, next.coords) {
|
|
log.Debug("moving east from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
|
tracker.point = next
|
|
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
|
tracker.last = append(tracker.last[1:], next.coords)
|
|
continue
|
|
}
|
|
next = checkNorth(tracker.point)
|
|
if !inLastMoves(tracker.last, next.coords) {
|
|
log.Debug("moving north from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
|
tracker.point = next
|
|
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
|
tracker.last = append(tracker.last[1:], next.coords)
|
|
continue
|
|
}
|
|
next = checkWest(tracker.point)
|
|
if !inLastMoves(tracker.last, next.coords) {
|
|
log.Debug("moving west from ", string(tracker.point.identifier), " to ", string(next.identifier))
|
|
tracker.point = next
|
|
loop = append(loop, pointsArray[tracker.Y()].points[tracker.X()].coords)
|
|
tracker.last = append(tracker.last[1:], next.coords)
|
|
continue
|
|
}
|
|
tracker.steps++ // the very last move will be back at start
|
|
}
|
|
return tracker.steps
|
|
}
|
|
|
|
// one returns the number of steps to reach the furthest point from the start
|
|
func one(lines []string) int {
|
|
mapPoints(lines)
|
|
|
|
tracker := newTracker()
|
|
|
|
return walk(tracker) / 2
|
|
}
|