2024 Day 16 Complete!
This commit is contained in:
parent
5cfe4e1b65
commit
5ae4d0ca9b
@ -1,276 +1,124 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
inp := h.StdinToStringSlice()
|
inp := h.StdinToCoordMap()
|
||||||
part1(inp)
|
|
||||||
// fmt.Println()
|
|
||||||
// part2(inp)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
N = h.Coordinate{X: 0, Y: -1}
|
|
||||||
E = h.Coordinate{X: 1, Y: 0}
|
|
||||||
S = h.Coordinate{X: 0, Y: 1}
|
|
||||||
W = h.Coordinate{X: -1, Y: 0}
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
scoreTrack map[h.Coordinate]int
|
|
||||||
bestCostToEnd map[h.Coordinate]int
|
|
||||||
)
|
|
||||||
|
|
||||||
func part1(inpS []string) {
|
|
||||||
inp := h.StringSliceToCoordByteMap(inpS)
|
|
||||||
scoreTrack = make(map[h.Coordinate]int)
|
|
||||||
bestCostToEnd = make(map[h.Coordinate]int)
|
|
||||||
|
|
||||||
start, _ := inp.FindFirst('S')
|
start, _ := inp.FindFirst('S')
|
||||||
end, _ := inp.FindFirst('E')
|
end, _ := inp.FindFirst('E')
|
||||||
inp.Put(start, '.')
|
|
||||||
bestCostToEnd[end] = 0
|
|
||||||
|
|
||||||
cd := CD{c: start, d: E}
|
score, seats := bfs(inp, start, end)
|
||||||
solve(inp, cd, end, 0, []h.Coordinate{cd.c})
|
fmt.Println("# Part 1")
|
||||||
best, ok := scoreTrack[end]
|
fmt.Println("Minimum Score:", score)
|
||||||
if !ok {
|
fmt.Println("# Part 2")
|
||||||
panic(errors.New("no path to end found"))
|
fmt.Println("Best Seats:", seats)
|
||||||
}
|
|
||||||
fmt.Println("Best Score:", best)
|
|
||||||
|
|
||||||
bestSeats := make(map[h.Coordinate]byte)
|
|
||||||
for i := range bestPaths {
|
|
||||||
for j := range bestPaths[i] {
|
|
||||||
bestSeats[bestPaths[i][j]] = byte('0' + i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printBestSeats(inp, bestSeats)
|
|
||||||
fmt.Println("Seats:", len(bestSeats))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var bestPaths [][]h.Coordinate
|
func bfs(inp h.CoordByteMap, s, e h.Coordinate) (int, int) {
|
||||||
|
start := CD{c: s, d: E}
|
||||||
|
minScore := math.MaxInt
|
||||||
|
queue := []State{
|
||||||
|
{
|
||||||
|
pos: start,
|
||||||
|
path: []h.Coordinate{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
visited := make(map[CD]int)
|
||||||
|
sizeToC := make(map[int][]h.Coordinate)
|
||||||
|
|
||||||
func solve(inp h.CoordByteMap, start CD, end h.Coordinate, score int, currPath []h.Coordinate) int {
|
for len(queue) > 0 {
|
||||||
// tryMove takes the cd that we're moving to and the cost to move there
|
currState := queue[0]
|
||||||
// and returns the cost to get from that cd to the end
|
queue = queue[1:]
|
||||||
tryMove := func(c CD, cost int) int {
|
|
||||||
if inp.ContainsCoord(c.c) && inp.Get(c.c) != '#' {
|
|
||||||
// printPathMap(inp, c, end, currPath)
|
|
||||||
// poi := h.Coordinate{X: 3, Y: 10}
|
|
||||||
// time.Sleep(time.Second / 20)
|
|
||||||
nextScore := score + cost
|
|
||||||
v, ok := bestCostToEnd[c.c]
|
|
||||||
//if c.c.Equals(poi) {
|
|
||||||
// fmt.Println("Current Scoretrack[poi] =", v)
|
|
||||||
// fmt.Println("Next Score =", nextScore)
|
|
||||||
// time.Sleep(time.Second * 5)
|
|
||||||
//}
|
|
||||||
if !ok || v >= nextScore {
|
|
||||||
nxtPath := make([]h.Coordinate, len(currPath))
|
|
||||||
copy(nxtPath, currPath)
|
|
||||||
nxtPath = append(nxtPath, c.c)
|
|
||||||
|
|
||||||
// Check end conditions
|
if currState.score > minScore {
|
||||||
if c.c.Equals(end) {
|
continue
|
||||||
if !ok || v > nextScore { // New Best
|
}
|
||||||
fmt.Println("New Best Path")
|
|
||||||
scoreTrack[end] = nextScore
|
if currState.pos.c.Equals(e) {
|
||||||
bestPaths = [][]h.Coordinate{nxtPath}
|
if currState.score <= minScore {
|
||||||
} else if v == nextScore { // Another Best Path
|
minScore = currState.score
|
||||||
fmt.Println("Adding path to best paths")
|
sizeToC[minScore] = append(sizeToC[minScore], currState.path...)
|
||||||
bestPaths = append(bestPaths, nxtPath)
|
}
|
||||||
}
|
continue
|
||||||
return cost
|
}
|
||||||
|
|
||||||
|
for _, n := range currState.pos.GetNeighbors() {
|
||||||
|
if inp.Get(n.c) == '#' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
score := currState.score + 1
|
||||||
|
if currState.pos.d != n.d {
|
||||||
|
score += 1000
|
||||||
|
}
|
||||||
|
if prev, ok := visited[n]; ok {
|
||||||
|
if prev < score {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
// Not the end, but keep going
|
|
||||||
scoreTrack[c.c] = nextScore
|
|
||||||
solve(inp, c, end, nextScore, nxtPath)
|
|
||||||
}
|
}
|
||||||
}
|
visited[n] = score
|
||||||
return h.MAX_INT
|
|
||||||
}
|
|
||||||
// Test forward
|
|
||||||
cost := tryMove(start.move(), 1)
|
|
||||||
// Test CW
|
|
||||||
if wrk := tryMove(start.turnCW().move(), 1001); wrk < cost {
|
|
||||||
cost = wrk
|
|
||||||
}
|
|
||||||
// Test CCW
|
|
||||||
if wrk := tryMove(start.turnCCW().move(), 1001); wrk < cost {
|
|
||||||
cost = wrk
|
|
||||||
}
|
|
||||||
bestCostToEnd[start.c] = cost
|
|
||||||
return cost
|
|
||||||
}
|
|
||||||
|
|
||||||
func printPathMap(inp h.CoordByteMap, loc CD, end h.Coordinate, path []h.Coordinate) {
|
np := make([]h.Coordinate, len(currState.path))
|
||||||
fmt.Print(h.CLEAR_SCREEN)
|
copy(np, currState.path)
|
||||||
wrk := inp.Copy()
|
queue = append(queue, State{
|
||||||
wrk.ReplaceAll('.', ' ')
|
pos: n,
|
||||||
for i := range path {
|
path: append(np, n.c),
|
||||||
wrk.Put(path[i], 'o')
|
score: score,
|
||||||
}
|
})
|
||||||
wrk.Put(loc.c, loc.Byte())
|
|
||||||
fmt.Println(wrk)
|
|
||||||
if v, ok := scoreTrack[end]; ok {
|
|
||||||
fmt.Printf("Best Score: %v (Paths: %d)\n", v, len(bestPaths))
|
|
||||||
} else {
|
|
||||||
fmt.Println("Waiting on best score...")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printBestSeats(inp h.CoordByteMap, seats map[h.Coordinate]byte) {
|
|
||||||
fmt.Print(h.CLEAR_SCREEN)
|
|
||||||
wrk := inp.Copy()
|
|
||||||
wrk.ReplaceAll('.', ' ')
|
|
||||||
for k, v := range seats {
|
|
||||||
wrk.Put(k, byte(0+v))
|
|
||||||
}
|
|
||||||
fmt.Println(wrk)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func part2(inpS []string) {
|
|
||||||
inp := h.StringSliceToCoordByteMap(inpS)
|
|
||||||
scoreTrack = make(map[h.Coordinate]int)
|
|
||||||
start, _ := inp.FindFirst('S')
|
|
||||||
end, _ := inp.FindFirst('E')
|
|
||||||
inp.Put(start, '.')
|
|
||||||
cd := CD{c: start, d: E}
|
|
||||||
lookForSeats(inp, cd, end, 0, []h.Coordinate{cd.c})
|
|
||||||
_, ok := scoreTrack[end]
|
|
||||||
if !ok {
|
|
||||||
panic(errors.New("no path to end found"))
|
|
||||||
}
|
|
||||||
bestSeats := make(map[h.Coordinate]int)
|
|
||||||
for i := range bestPaths {
|
|
||||||
for j := range bestPaths[i] {
|
|
||||||
bestSeats[bestPaths[i][j]] = i
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("Number of Seats:", len(bestSeats))
|
seatMap := make(map[h.Coordinate]bool)
|
||||||
}
|
for _, p := range sizeToC[minScore] {
|
||||||
|
seatMap[p] = true
|
||||||
|
|
||||||
|
|
||||||
func coordInPath(c h.Coordinate, path []h.Coordinate) bool {
|
|
||||||
for i := range path {
|
|
||||||
if path[i].Equals(c) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false
|
/*
|
||||||
}
|
for y := inp.TLY; y <= inp.BRY; y++ {
|
||||||
|
for x := inp.TLX; x <= inp.BRX; x++ {
|
||||||
func lookForSeats(inp h.CoordByteMap, start CD, end h.Coordinate, score int, path []h.Coordinate) int {
|
c := h.Coordinate{X: x, Y: y}
|
||||||
// Check for finished:
|
if _, ok := seatMap[c]; ok {
|
||||||
if start.c.Equals(end) {
|
fmt.Print("O")
|
||||||
v, ok := scoreTrack[end]
|
} else {
|
||||||
if !ok || v > score {
|
fmt.Print(string(inp.Get(c)))
|
||||||
// We have a new best path
|
}
|
||||||
bestPaths = [][]h.Coordinate{path}
|
|
||||||
scoreTrack[end] = score
|
|
||||||
} else if scoreTrack[end] == score {
|
|
||||||
bestPaths = append(bestPaths, path)
|
|
||||||
}
|
|
||||||
return score
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper func
|
|
||||||
canMoveTo := func(p h.Coordinate) bool {
|
|
||||||
return inp.ContainsCoord(p) && inp.Get(p) != '#'
|
|
||||||
}
|
|
||||||
// Keep moving:
|
|
||||||
tryMove := func(c CD, cost int) {
|
|
||||||
if canMoveTo(c.c) {
|
|
||||||
// Check if this path has alread gone through this spot
|
|
||||||
nxtPath := make([]h.Coordinate, len(path))
|
|
||||||
copy(nxtPath, path)
|
|
||||||
if coordInPath(c.c, nxtPath) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Ok, now what's the best score we end up if we make this move?
|
|
||||||
nextScore := score + cost
|
|
||||||
n, ok := scoreTrack[c.c]
|
|
||||||
if !ok || n > nextScore {
|
|
||||||
lookForSeats(inp, c, end, nextScore, append(nxtPath, c.c))
|
|
||||||
}
|
}
|
||||||
|
fmt.Println()
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
// Test forward
|
return minScore, len(seatMap) + 1
|
||||||
tryMove(start.move(), 1)
|
|
||||||
// Test CW
|
|
||||||
tryMove(start.turnCW().move(), 1001)
|
|
||||||
// Test CCW
|
|
||||||
tryMove(start.turnCCW().move(), 1001)
|
|
||||||
return scoreTrack[start.c]
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
var (
|
||||||
|
N = h.Coordinate{X: 0, Y: -1}
|
||||||
|
E = h.Coordinate{X: 1, Y: 0}
|
||||||
|
S = h.Coordinate{X: 0, Y: 1}
|
||||||
|
W = h.Coordinate{X: -1, Y: 0}
|
||||||
|
Dirs = []h.Coordinate{N, E, S, W}
|
||||||
|
)
|
||||||
|
|
||||||
type CD struct {
|
type CD struct {
|
||||||
c h.Coordinate
|
c, d h.Coordinate
|
||||||
d h.Coordinate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cd CD) move() CD {
|
func (cd CD) GetNeighbors() []CD {
|
||||||
return CD{
|
var ret []CD
|
||||||
c: cd.c.Add(cd.d),
|
opp := h.Coordinate{X: -cd.d.X, Y: -cd.d.Y}
|
||||||
d: cd.d,
|
for _, dir := range Dirs {
|
||||||
|
if !dir.Equals(opp) {
|
||||||
|
ret = append(ret, CD{
|
||||||
|
c: cd.c.Add(dir),
|
||||||
|
d: dir,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cd CD) turnCW() CD {
|
type State struct {
|
||||||
var newD h.Coordinate
|
pos CD
|
||||||
switch cd.d {
|
path []h.Coordinate
|
||||||
case N:
|
score int
|
||||||
newD = E
|
|
||||||
case E:
|
|
||||||
newD = S
|
|
||||||
case S:
|
|
||||||
newD = W
|
|
||||||
case W:
|
|
||||||
newD = N
|
|
||||||
}
|
|
||||||
return CD{
|
|
||||||
c: cd.c,
|
|
||||||
d: newD,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cd CD) turnCCW() CD {
|
|
||||||
var newD h.Coordinate
|
|
||||||
switch cd.d {
|
|
||||||
case N:
|
|
||||||
newD = W
|
|
||||||
case E:
|
|
||||||
newD = N
|
|
||||||
case S:
|
|
||||||
newD = E
|
|
||||||
case W:
|
|
||||||
newD = S
|
|
||||||
}
|
|
||||||
return CD{
|
|
||||||
c: cd.c,
|
|
||||||
d: newD,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cd CD) Byte() byte {
|
|
||||||
switch cd.d {
|
|
||||||
case N:
|
|
||||||
return '^'
|
|
||||||
case E:
|
|
||||||
return '>'
|
|
||||||
case S:
|
|
||||||
return 'v'
|
|
||||||
case W:
|
|
||||||
return '<'
|
|
||||||
}
|
|
||||||
return '?'
|
|
||||||
}
|
}
|
||||||
|
276
2024/day16/main.go.bk
Normal file
276
2024/day16/main.go.bk
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
part1(inp)
|
||||||
|
// fmt.Println()
|
||||||
|
// part2(inp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
N = h.Coordinate{X: 0, Y: -1}
|
||||||
|
E = h.Coordinate{X: 1, Y: 0}
|
||||||
|
S = h.Coordinate{X: 0, Y: 1}
|
||||||
|
W = h.Coordinate{X: -1, Y: 0}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
scoreTrack map[h.Coordinate]int
|
||||||
|
bestCostToEnd map[h.Coordinate]int
|
||||||
|
)
|
||||||
|
|
||||||
|
func part1(inpS []string) {
|
||||||
|
inp := h.StringSliceToCoordByteMap(inpS)
|
||||||
|
scoreTrack = make(map[h.Coordinate]int)
|
||||||
|
bestCostToEnd = make(map[h.Coordinate]int)
|
||||||
|
|
||||||
|
start, _ := inp.FindFirst('S')
|
||||||
|
end, _ := inp.FindFirst('E')
|
||||||
|
inp.Put(start, '.')
|
||||||
|
bestCostToEnd[end] = 0
|
||||||
|
|
||||||
|
cd := CD{c: start, d: E}
|
||||||
|
solve(inp, cd, end, 0, []h.Coordinate{cd.c})
|
||||||
|
best, ok := scoreTrack[end]
|
||||||
|
if !ok {
|
||||||
|
panic(errors.New("no path to end found"))
|
||||||
|
}
|
||||||
|
fmt.Println("Best Score:", best)
|
||||||
|
|
||||||
|
bestSeats := make(map[h.Coordinate]byte)
|
||||||
|
for i := range bestPaths {
|
||||||
|
for j := range bestPaths[i] {
|
||||||
|
bestSeats[bestPaths[i][j]] = byte('0' + i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printBestSeats(inp, bestSeats)
|
||||||
|
fmt.Println("Seats:", len(bestSeats))
|
||||||
|
}
|
||||||
|
|
||||||
|
var bestPaths [][]h.Coordinate
|
||||||
|
|
||||||
|
func solve(inp h.CoordByteMap, start CD, end h.Coordinate, score int, currPath []h.Coordinate) int {
|
||||||
|
// tryMove takes the cd that we're moving to and the cost to move there
|
||||||
|
// and returns the cost to get from that cd to the end
|
||||||
|
tryMove := func(c CD, cost int) int {
|
||||||
|
if inp.ContainsCoord(c.c) && inp.Get(c.c) != '#' {
|
||||||
|
// printPathMap(inp, c, end, currPath)
|
||||||
|
// poi := h.Coordinate{X: 3, Y: 10}
|
||||||
|
// time.Sleep(time.Second / 20)
|
||||||
|
nextScore := score + cost
|
||||||
|
v, ok := bestCostToEnd[c.c]
|
||||||
|
//if c.c.Equals(poi) {
|
||||||
|
// fmt.Println("Current Scoretrack[poi] =", v)
|
||||||
|
// fmt.Println("Next Score =", nextScore)
|
||||||
|
// time.Sleep(time.Second * 5)
|
||||||
|
//}
|
||||||
|
if !ok || v >= nextScore {
|
||||||
|
nxtPath := make([]h.Coordinate, len(currPath))
|
||||||
|
copy(nxtPath, currPath)
|
||||||
|
nxtPath = append(nxtPath, c.c)
|
||||||
|
|
||||||
|
// Check end conditions
|
||||||
|
if c.c.Equals(end) {
|
||||||
|
if !ok || v > nextScore { // New Best
|
||||||
|
fmt.Println("New Best Path")
|
||||||
|
scoreTrack[end] = nextScore
|
||||||
|
bestPaths = [][]h.Coordinate{nxtPath}
|
||||||
|
} else if v == nextScore { // Another Best Path
|
||||||
|
fmt.Println("Adding path to best paths")
|
||||||
|
bestPaths = append(bestPaths, nxtPath)
|
||||||
|
}
|
||||||
|
return cost
|
||||||
|
}
|
||||||
|
// Not the end, but keep going
|
||||||
|
scoreTrack[c.c] = nextScore
|
||||||
|
solve(inp, c, end, nextScore, nxtPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h.MAX_INT
|
||||||
|
}
|
||||||
|
// Test forward
|
||||||
|
cost := tryMove(start.move(), 1)
|
||||||
|
// Test CW
|
||||||
|
if wrk := tryMove(start.turnCW().move(), 1001); wrk < cost {
|
||||||
|
cost = wrk
|
||||||
|
}
|
||||||
|
// Test CCW
|
||||||
|
if wrk := tryMove(start.turnCCW().move(), 1001); wrk < cost {
|
||||||
|
cost = wrk
|
||||||
|
}
|
||||||
|
bestCostToEnd[start.c] = cost
|
||||||
|
return cost
|
||||||
|
}
|
||||||
|
|
||||||
|
func printPathMap(inp h.CoordByteMap, loc CD, end h.Coordinate, path []h.Coordinate) {
|
||||||
|
fmt.Print(h.CLEAR_SCREEN)
|
||||||
|
wrk := inp.Copy()
|
||||||
|
wrk.ReplaceAll('.', ' ')
|
||||||
|
for i := range path {
|
||||||
|
wrk.Put(path[i], 'o')
|
||||||
|
}
|
||||||
|
wrk.Put(loc.c, loc.Byte())
|
||||||
|
fmt.Println(wrk)
|
||||||
|
if v, ok := scoreTrack[end]; ok {
|
||||||
|
fmt.Printf("Best Score: %v (Paths: %d)\n", v, len(bestPaths))
|
||||||
|
} else {
|
||||||
|
fmt.Println("Waiting on best score...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printBestSeats(inp h.CoordByteMap, seats map[h.Coordinate]byte) {
|
||||||
|
fmt.Print(h.CLEAR_SCREEN)
|
||||||
|
wrk := inp.Copy()
|
||||||
|
wrk.ReplaceAll('.', ' ')
|
||||||
|
for k, v := range seats {
|
||||||
|
wrk.Put(k, byte(0+v))
|
||||||
|
}
|
||||||
|
fmt.Println(wrk)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func part2(inpS []string) {
|
||||||
|
inp := h.StringSliceToCoordByteMap(inpS)
|
||||||
|
scoreTrack = make(map[h.Coordinate]int)
|
||||||
|
start, _ := inp.FindFirst('S')
|
||||||
|
end, _ := inp.FindFirst('E')
|
||||||
|
inp.Put(start, '.')
|
||||||
|
cd := CD{c: start, d: E}
|
||||||
|
lookForSeats(inp, cd, end, 0, []h.Coordinate{cd.c})
|
||||||
|
_, ok := scoreTrack[end]
|
||||||
|
if !ok {
|
||||||
|
panic(errors.New("no path to end found"))
|
||||||
|
}
|
||||||
|
bestSeats := make(map[h.Coordinate]int)
|
||||||
|
for i := range bestPaths {
|
||||||
|
for j := range bestPaths[i] {
|
||||||
|
bestSeats[bestPaths[i][j]] = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Number of Seats:", len(bestSeats))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func coordInPath(c h.Coordinate, path []h.Coordinate) bool {
|
||||||
|
for i := range path {
|
||||||
|
if path[i].Equals(c) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func lookForSeats(inp h.CoordByteMap, start CD, end h.Coordinate, score int, path []h.Coordinate) int {
|
||||||
|
// Check for finished:
|
||||||
|
if start.c.Equals(end) {
|
||||||
|
v, ok := scoreTrack[end]
|
||||||
|
if !ok || v > score {
|
||||||
|
// We have a new best path
|
||||||
|
bestPaths = [][]h.Coordinate{path}
|
||||||
|
scoreTrack[end] = score
|
||||||
|
} else if scoreTrack[end] == score {
|
||||||
|
bestPaths = append(bestPaths, path)
|
||||||
|
}
|
||||||
|
return score
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper func
|
||||||
|
canMoveTo := func(p h.Coordinate) bool {
|
||||||
|
return inp.ContainsCoord(p) && inp.Get(p) != '#'
|
||||||
|
}
|
||||||
|
// Keep moving:
|
||||||
|
tryMove := func(c CD, cost int) {
|
||||||
|
if canMoveTo(c.c) {
|
||||||
|
// Check if this path has alread gone through this spot
|
||||||
|
nxtPath := make([]h.Coordinate, len(path))
|
||||||
|
copy(nxtPath, path)
|
||||||
|
if coordInPath(c.c, nxtPath) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Ok, now what's the best score we end up if we make this move?
|
||||||
|
nextScore := score + cost
|
||||||
|
n, ok := scoreTrack[c.c]
|
||||||
|
if !ok || n > nextScore {
|
||||||
|
lookForSeats(inp, c, end, nextScore, append(nxtPath, c.c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test forward
|
||||||
|
tryMove(start.move(), 1)
|
||||||
|
// Test CW
|
||||||
|
tryMove(start.turnCW().move(), 1001)
|
||||||
|
// Test CCW
|
||||||
|
tryMove(start.turnCCW().move(), 1001)
|
||||||
|
return scoreTrack[start.c]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
type CD struct {
|
||||||
|
c h.Coordinate
|
||||||
|
d h.Coordinate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cd CD) move() CD {
|
||||||
|
return CD{
|
||||||
|
c: cd.c.Add(cd.d),
|
||||||
|
d: cd.d,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cd CD) turnCW() CD {
|
||||||
|
var newD h.Coordinate
|
||||||
|
switch cd.d {
|
||||||
|
case N:
|
||||||
|
newD = E
|
||||||
|
case E:
|
||||||
|
newD = S
|
||||||
|
case S:
|
||||||
|
newD = W
|
||||||
|
case W:
|
||||||
|
newD = N
|
||||||
|
}
|
||||||
|
return CD{
|
||||||
|
c: cd.c,
|
||||||
|
d: newD,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cd CD) turnCCW() CD {
|
||||||
|
var newD h.Coordinate
|
||||||
|
switch cd.d {
|
||||||
|
case N:
|
||||||
|
newD = W
|
||||||
|
case E:
|
||||||
|
newD = N
|
||||||
|
case S:
|
||||||
|
newD = E
|
||||||
|
case W:
|
||||||
|
newD = S
|
||||||
|
}
|
||||||
|
return CD{
|
||||||
|
c: cd.c,
|
||||||
|
d: newD,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cd CD) Byte() byte {
|
||||||
|
switch cd.d {
|
||||||
|
case N:
|
||||||
|
return '^'
|
||||||
|
case E:
|
||||||
|
return '>'
|
||||||
|
case S:
|
||||||
|
return 'v'
|
||||||
|
case W:
|
||||||
|
return '<'
|
||||||
|
}
|
||||||
|
return '?'
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user