This commit is contained in:
2025-02-14 15:14:03 +00:00
parent a529516bab
commit 759b9c9544
23 changed files with 11146 additions and 6 deletions

181
2024/go/day21/day21.go Normal file
View File

@@ -0,0 +1,181 @@
package day21
import (
"adventofcode2024/utils"
"adventofcode2024/utils/dijkstra"
"adventofcode2024/utils/memo"
"fmt"
"math"
"strings"
)
type Pair struct {
s dijkstra.Point
d dijkstra.Point
}
type Path struct {
path []dijkstra.Point
path_str string
cost int
}
type State struct {
code string
depth int
isNumericPad bool
}
var numericPad = map[dijkstra.Point]string{
{X: 0, Y: 0}: "7", {X: 1, Y: 0}: "8", {X: 2, Y: 0}: "9",
{X: 0, Y: 1}: "4", {X: 1, Y: 1}: "5", {X: 2, Y: 1}: "6",
{X: 0, Y: 2}: "1", {X: 1, Y: 2}: "2", {X: 2, Y: 2}: "3",
{X: 1, Y: 3}: "0", {X: 2, Y: 3}: "A",
}
var directionPad = map[dijkstra.Point]string{
{X: 1, Y: 0}: "^", {X: 2, Y: 0}: "A",
{X: 0, Y: 1}: "<", {X: 1, Y: 1}: "v", {X: 2, Y: 1}: ">",
}
var directions = []dijkstra.Point{{X: 0, Y: 1}, {X: 0, Y: -1}, {X: 1, Y: 0}, {X: -1, Y: 0}}
var lookup_np = get_paths(numericPad)
var lookup_dp = get_paths(directionPad)
var m *memo.Memo
func init() {
m = memo.New(get_shortest_path)
}
func Part1(input string) int {
codes := strings.Split(input, "\n")
cost := 0
for _, code := range codes {
initialState := State{
code: code,
depth: 2,
isNumericPad: true,
}
result := m.Get(initialState).(int)
cost += result * utils.MustAtoi(code[:len(code)-1])
}
return cost
}
func Part2(input string) int {
codes := strings.Split(input, "\n")
cost := 0
for _, code := range codes {
initialState := State{
code: code,
depth: 25,
isNumericPad: true,
}
result := m.Get(initialState).(int)
cost += result * utils.MustAtoi(code[:len(code)-1])
}
return cost
}
func get_paths(in map[dijkstra.Point]string) map[Pair][]Path {
lookup := make(map[Pair][]Path)
data := dijkstra.InputGraph{}
for p := range in {
for _, dir := range directions {
np := dijkstra.Point{X: p.X + dir.X, Y: p.Y + dir.Y}
if in[np] != "" {
data.Graph = append(data.Graph, dijkstra.InputData{
Source: p,
Destination: np,
Weight: 1,
})
}
}
}
graph := dijkstra.CreateGraph(data)
for s := range in {
for d := range in {
paths, cost := dijkstra.GetAllShortestPaths(s, d, graph)
for _, path := range paths {
path_str := ""
for x := 1; x < len(path); x++ {
f := path[x-1]
t := path[x]
switch {
case f.X == t.X && f.Y < t.Y:
// Moving verticallY down
path_str += "v"
case f.X == t.X && f.Y > t.Y:
// Moving verticallY up
path_str += "^"
case f.Y == t.Y && f.X < t.X:
// Moving horizontallY right
path_str += ">"
case f.Y == t.Y && f.X > t.X:
// Moving horizontally left
path_str += "<"
default:
// No matching case or invalid input
fmt.Println("Invalid direction")
}
}
lookup[Pair{s, d}] = append(lookup[Pair{s, d}], Path{path, path_str, cost})
}
}
}
return lookup
}
func find_point(in string, lookup map[dijkstra.Point]string) dijkstra.Point {
for k, v := range lookup {
if v == in {
return k
}
}
return dijkstra.Point{}
}
func get_shortest_path(key interface{}) interface{} {
state := key.(State)
if state.depth < 0 {
return len(state.code)
}
// (Optional) If you need to modify the state, work on a copy.
newState := state
newState.code = "A" + state.code
cost := 0
for x := 0; x<len(newState.code)-1; x++ {
pps := shortest_paths(string(newState.code[x]), string(newState.code[x+1]), newState.isNumericPad)
min := math.MaxInt // Start with a very high number not just 65535
for _, pp := range pps {
nextState := State{
code: pp.path_str + "A",
depth: newState.depth - 1,
isNumericPad: false,
}
mm := m.Get(nextState).(int)
if mm < min {
min = mm
}
}
cost += min
}
return cost
}
func shortest_paths(s, d string, isNumericPad bool) []Path {
if isNumericPad {
return lookup_np[Pair{s: find_point(s, numericPad), d: find_point(d, numericPad)}]
} else {
return lookup_dp[Pair{s: find_point(s, directionPad), d: find_point(d, directionPad)}]
}
}

View File

@@ -0,0 +1,25 @@
package day21
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestPart1(t *testing.T) {
r := Part1(`029A
980A
179A
456A
379A`)
require.Equal(t, 126384, r)
}
func TestPart2(t *testing.T) {
r := Part2(`029A
980A
179A
456A
379A`)
require.Equal(t, 126384, r)
}

5
2024/go/day21/input.txt Normal file
View File

@@ -0,0 +1,5 @@
480A
965A
140A
341A
285A

9
2024/go/day21/tt Normal file
View File

@@ -0,0 +1,9 @@
v<A <A A >>^A v<<A>A<A>>^AvAA<^A>AvA<^A>vA^A
<vA <A A >>^A vA A <^A >A <v<A>>^AvA^A<vA>^A<v<A>^A>AAvA^A<v<A>A>^AAAvA<^A>A
v < < A > > ^ A <A>AvA<^AA>A<vAAA>^A
< A ^A>^^AvvvA
0 29A