|
@@ -8,9 +8,10 @@ import (
|
|
)
|
|
)
|
|
|
|
|
|
type Point struct {
|
|
type Point struct {
|
|
- y, x int
|
|
|
|
- cost int
|
|
|
|
- cheats int
|
|
|
|
|
|
+ y, x int
|
|
|
|
+ cost int
|
|
|
|
+ cheats int
|
|
|
|
+ cheatedAt *Point
|
|
}
|
|
}
|
|
|
|
|
|
func (p *Point) key() string {
|
|
func (p *Point) key() string {
|
|
@@ -58,16 +59,20 @@ var directions [][]int = [][]int{
|
|
{0, -1}, {1, 0}, {0, 1}, {-1, 0},
|
|
{0, -1}, {1, 0}, {0, 1}, {-1, 0},
|
|
}
|
|
}
|
|
|
|
|
|
-func getMoves(current Point, matrix [][]byte, xMax, yMax int, cheat bool) []Point {
|
|
|
|
|
|
+func getMoves(current Point, matrix [][]byte, xMax, yMax int, cheat bool, cheats map[string]bool) []Point {
|
|
var moves []Point
|
|
var moves []Point
|
|
for _, direction := range directions {
|
|
for _, direction := range directions {
|
|
- move := Point{x: current.x + direction[0], y: current.y + direction[1], cost: current.cost + 1, cheats: current.cheats}
|
|
|
|
|
|
+ move := Point{x: current.x + direction[0], y: current.y + direction[1], cost: current.cost + 1, cheats: current.cheats, cheatedAt: current.cheatedAt}
|
|
if move.x <= 0 || move.y <= 0 || move.x >= xMax || move.y >= yMax {
|
|
if move.x <= 0 || move.y <= 0 || move.x >= xMax || move.y >= yMax {
|
|
continue
|
|
continue
|
|
}
|
|
}
|
|
|
|
|
|
if matrix[move.y][move.x] == '#' {
|
|
if matrix[move.y][move.x] == '#' {
|
|
- if cheat && move.cheats > 0 {
|
|
|
|
|
|
+ if cheat && !cheats[move.key()] && move.cheats > 0 {
|
|
|
|
+ if move.cheatedAt == nil {
|
|
|
|
+ move.cheatedAt = &move
|
|
|
|
+ }
|
|
|
|
+
|
|
move.cheats--
|
|
move.cheats--
|
|
moves = append(moves, move)
|
|
moves = append(moves, move)
|
|
}
|
|
}
|
|
@@ -85,7 +90,7 @@ func getMoves(current Point, matrix [][]byte, xMax, yMax int, cheat bool) []Poin
|
|
return moves
|
|
return moves
|
|
}
|
|
}
|
|
|
|
|
|
-func hike(start *Point, matrix [][]byte, xMax, yMax int, cheat bool) int {
|
|
|
|
|
|
+func hike(start *Point, matrix [][]byte, xMax, yMax int, cheat bool, cheats map[string]bool) int {
|
|
cost := 1000000000
|
|
cost := 1000000000
|
|
visited := make(map[string]int)
|
|
visited := make(map[string]int)
|
|
visited[start.key()] = start.cost
|
|
visited[start.key()] = start.cost
|
|
@@ -96,9 +101,12 @@ func hike(start *Point, matrix [][]byte, xMax, yMax int, cheat bool) int {
|
|
moves = moves[1:]
|
|
moves = moves[1:]
|
|
if matrix[current.y][current.x] == 'E' && current.cost < cost {
|
|
if matrix[current.y][current.x] == 'E' && current.cost < cost {
|
|
cost = current.cost
|
|
cost = current.cost
|
|
|
|
+ if cheat && current.cheatedAt != nil {
|
|
|
|
+ cheats[current.cheatedAt.key()] = true
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- newMoves := getMoves(current, matrix, xMax, yMax, cheat)
|
|
|
|
|
|
+ newMoves := getMoves(current, matrix, xMax, yMax, cheat, cheats)
|
|
for _, newMove := range newMoves {
|
|
for _, newMove := range newMoves {
|
|
if visited[newMove.key()] == 0 || visited[newMove.key()] > newMove.cost {
|
|
if visited[newMove.key()] == 0 || visited[newMove.key()] > newMove.cost {
|
|
moves = append(moves, newMove)
|
|
moves = append(moves, newMove)
|
|
@@ -114,8 +122,20 @@ func part1(start *Point, matrix [][]byte) int {
|
|
xMax := len(matrix[0]) - 1
|
|
xMax := len(matrix[0]) - 1
|
|
yMax := len(matrix) - 1
|
|
yMax := len(matrix) - 1
|
|
|
|
|
|
- bestWithoutCheating := hike(start, matrix, xMax, yMax, false)
|
|
|
|
- fmt.Println(bestWithoutCheating)
|
|
|
|
|
|
+ cheats := make(map[string]bool)
|
|
|
|
+ bestWithoutCheating := hike(start, matrix, xMax, yMax, false, cheats)
|
|
|
|
+ for {
|
|
|
|
+ score := hike(start, matrix, xMax, yMax, true, cheats)
|
|
|
|
+ if score >= 1000000000 {
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ saving := bestWithoutCheating - score
|
|
|
|
+ if saving == 0 {
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+ fmt.Println(saving, cheats)
|
|
|
|
+ }
|
|
|
|
|
|
return 0
|
|
return 0
|
|
}
|
|
}
|