Skip to content

Commit

Permalink
add refactored part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
devries committed Dec 17, 2023
1 parent 891d10e commit 342b951
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 1 deletion.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,15 @@ the third run of my solution after compilation on my Raspberry Pi.
directions, but that seems like it would have been tricky with the requirement
that energized tiles only be counted once.
- [Day 17: Clumsy Crucible](https://adventofcode.com/2023/day/17) - [⭐ part 1](day17p1/solution.go), [⭐ part 2](day17p2/solution.go)
- [Day 17: Clumsy Crucible](https://adventofcode.com/2023/day/17) - [⭐ part 1](day17p1/solution.go), [⭐ part 2](day17p2/solution.go), [⭐ part 2b](day17p2b/solution.go)
First use of Dijkstra! It was fairly easy to adapt the conditions of the
problem to the Graph routines in my code. I think memory allocation may be
the bottleneck in my implementation, but it seems fast enough.
After submitting my solution and reading other people's suggestions on reddit
I refactored my solution for part 2 to part 2b. In this example, rather than
use the position, direction, and number of steps as a state, I reduce the
state to position and direction. For neighboring states, I assume I will turn
90 degrees and find all states 4 to 10 steps away in each direction. This runs
much faster as shown above.
96 changes: 96 additions & 0 deletions day17p2b/solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package day17p2b

import (
"io"

"aoc/utils"
)

func Solve(r io.Reader) any {
lines := utils.ReadLines(r)

m := NewMaze(lines)

dij := utils.NewDijkstra[State]()

finalState, err := dij.Run(m)
utils.Check(err, "error in search")

return dij.Distance[finalState]
}

type Maze struct {
HeatLoss map[utils.Point]uint64
BottomRight utils.Point
}

func NewMaze(lines []string) *Maze {
m := Maze{HeatLoss: make(map[utils.Point]uint64)}

for j, ln := range lines {
for i, r := range ln {
p := utils.Point{X: i, Y: -j}
v := uint64(r - '0')
m.HeatLoss[p] = v
m.BottomRight = p
}
}

return &m
}

type State struct {
Position utils.Point
Direction utils.Point
}

var zero = utils.Point{X: 0, Y: 0}

func (m *Maze) GetInitial() State {
// special starting direction from which we will go East to South
return State{zero, zero}
}

func (m *Maze) GetEdges(s State) []utils.Edge[State] {
ret := []utils.Edge[State]{}

nextDirections := make([]utils.Point, 2)

switch s.Direction {
case zero:
// This is the special starting state
nextDirections[0] = utils.East
nextDirections[1] = utils.South
case utils.East, utils.West:
nextDirections[0] = utils.South
nextDirections[1] = utils.North
case utils.North, utils.South:
nextDirections[0] = utils.East
nextDirections[1] = utils.West
}

// Left and Right
for _, dir := range nextDirections {
p := s.Position
var length uint64
for step := 1; step <= 10; step++ {
p = p.Add(dir)
if delta, ok := m.HeatLoss[p]; ok {
length += delta
if step >= 4 {
ret = append(ret, utils.Edge[State]{Node: State{p, dir}, Distance: length})
}
}
}
}

return ret
}

func (m *Maze) IsFinal(s State) bool {
if s.Position == m.BottomRight {
return true
}

return false
}
52 changes: 52 additions & 0 deletions day17p2b/solution_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package day17p2b

import (
"strings"
"testing"

"aoc/utils"
)

var testInput = `2413432311323
3215453535623
3255245654254
3446585845452
4546657867536
1438598798454
4457876987766
3637877979653
4654967986887
4564679986453
1224686865563
2546548887735
4322674655533`

var testInput2 = `111111111111
999999999991
999999999991
999999999991
999999999991`

func TestSolve(t *testing.T) {
tests := []struct {
input string
answer uint64
}{
{testInput, 94},
{testInput2, 71},
}

if testing.Verbose() {
utils.Verbose = true
}

for _, test := range tests {
r := strings.NewReader(test.input)

result := Solve(r).(uint64)

if result != test.answer {
t.Errorf("Expected %d, got %d", test.answer, result)
}
}
}

0 comments on commit 342b951

Please # to comment.