Skip to content
This repository has been archived by the owner on Dec 28, 2024. It is now read-only.

Commit

Permalink
Add solution day 18 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
terminalnode committed Dec 18, 2024
1 parent ca5d2a8 commit 5817dbe
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 40 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ automatically rebuilt and redeployed every time the `common` module or their own
| 02 | ⭐ ⭐ | 15 | ⭐ ⭐ |
| 03 | ⭐ ⭐ | 16 | ⭐ 🥸 |
| 04 | ⭐ ⭐ | 17 ||
| 05 | ⭐ ⭐ | 18 | |
| 05 | ⭐ ⭐ | 18 | |
| 06 | ⭐ ⭐ | 19 | |
| 07 | ⭐ ⭐ | 20 | |
| 08 | ⭐ ⭐ | 21 | |
Expand Down
115 changes: 76 additions & 39 deletions solutions/day18/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,68 +7,77 @@ import (
)

func main() {
common.Setup(18, part1, nil)
common.Setup(18, part1, part2)
}

func part1(
input string,
) string {
out, err := run(input, 70, 70, 1024)
m := buildMatrix()
cs, err := parse(input)
if err != nil {
return err.Error()
return fmt.Sprintf("Failed to parse input: %v", err)
}
return fmt.Sprintf("Shortest path is %d steps", out)

for _, c := range cs[:1024] {
m[c.Y][c.X] = true
}

start := util.Coordinate{X: 0, Y: 0}
end := util.Coordinate{X: 70, Y: 70}
visitedSet := buildVisitedSet[int]()
shortestPath(m, start, end, 0, visitedSet)

shortest := visitedSet[70][70]
return fmt.Sprintf("Shortest path is %d steps", shortest)
}

func run(
func part2(
input string,
maxX int,
maxY int,
fallenBytes int,
) (int, error) {
m := buildMatrix(maxX, maxY)
) string {
m := buildMatrix()
cs, err := parse(input)
if err != nil {
return -1, err
return fmt.Sprintf("Failed to parse input: %v", err)
}

if len(cs) > fallenBytes {
cs = cs[:fallenBytes]
}
// Initialize everything
latest := cs[0]
cs = cs[1:]
winningSet := buildVisitedSet[bool]()
m[latest.Y][latest.X] = true
count := 1
start := util.Coordinate{X: 0, Y: 0}
end := util.Coordinate{X: 70, Y: 70}
success := anyPath(m, start, end, buildVisitedSet[bool](), winningSet)

for _, c := range cs {
m[c.Y][c.X] = true
}
for success && len(cs) > 0 {
for !winningSet[latest.Y][latest.X] && len(cs) > 0 {
count++
latest = cs[0]
cs = cs[1:]
m[latest.Y][latest.X] = true
}

visitedSet := buildVisitedSet(maxY)
shortestPath(
m,
util.Coordinate{X: 0, Y: 0},
util.Coordinate{X: maxX, Y: maxY},
0,
visitedSet,
)
winningSet = buildVisitedSet[bool]()
success = anyPath(m, start, end, buildVisitedSet[bool](), winningSet)
}

return visitedSet[maxY][maxX], nil
return fmt.Sprintf("The byte that broke the camel's back was %s", latest)
}

func buildMatrix(
maxX int,
maxY int,
) [][]bool {
out := make([][]bool, maxY+1)
for y := 0; y <= maxY; y++ {
out[y] = make([]bool, maxX+1)
func buildMatrix() [][]bool {
out := make([][]bool, 71)
for y := 0; y <= 70; y++ {
out[y] = make([]bool, 71)
}
return out
}

func buildVisitedSet(
maxY int,
) map[int]map[int]int {
visitedSet := make(map[int]map[int]int)
for y := 0; y <= maxY; y++ {
visitedSet[y] = make(map[int]int)
func buildVisitedSet[T any]() map[int]map[int]T {
visitedSet := make(map[int]map[int]T)
for y := 0; y <= 70; y++ {
visitedSet[y] = make(map[int]T)
}
return visitedSet
}
Expand Down Expand Up @@ -106,3 +115,31 @@ func shortestPath(
shortestPath(m, c.South(), goal, steps+1, visitedSet)
shortestPath(m, c.West(), goal, steps+1, visitedSet)
}

func anyPath(
m [][]bool,
c util.Coordinate,
goal util.Coordinate,
visitedSet map[int]map[int]bool,
winningSet map[int]map[int]bool,
) bool {
if visitedSet[c.Y][c.X] || !util.In2DArray(c, m) || m[c.Y][c.X] {
// Been here, outside matrix or position is impassable
return false
} else if c.Equals(goal) {
// We did it!
winningSet[c.Y][c.X] = true
return true
}

visitedSet[c.Y][c.X] = true
winner := anyPath(m, c.South(), goal, visitedSet, winningSet) ||
anyPath(m, c.East(), goal, visitedSet, winningSet) ||
anyPath(m, c.West(), goal, visitedSet, winningSet) ||
anyPath(m, c.North(), goal, visitedSet, winningSet)
if winner {
winningSet[c.Y][c.X] = true
}

return winner
}

0 comments on commit 5817dbe

Please sign in to comment.