partial d15
This commit is contained in:
parent
6a046fdb1c
commit
99242d53d7
6 changed files with 227 additions and 0 deletions
44
d15/common.go
Normal file
44
d15/common.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package d15
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func weightNeighbors(in string) (weights, neighbors) {
|
||||||
|
weights := make(weights)
|
||||||
|
neighbors := make(neighbors)
|
||||||
|
lines := strings.Split(strings.TrimSpace(in), "\n")
|
||||||
|
height := len(lines)
|
||||||
|
width := len(lines[0])
|
||||||
|
for y, line := range lines {
|
||||||
|
for x, weight := range strings.Split(line, "") {
|
||||||
|
weight, _ := strconv.Atoi(weight)
|
||||||
|
weights[node(x+y*height)] = weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
maxX := width
|
||||||
|
maxY := height
|
||||||
|
for height >= 0 {
|
||||||
|
width = maxX
|
||||||
|
for width >= 0 {
|
||||||
|
current := node(width + height*maxY)
|
||||||
|
if height > 0 {
|
||||||
|
neighbors[current] = append(neighbors[current], node(width+(height-1)*maxY))
|
||||||
|
}
|
||||||
|
if height < maxY {
|
||||||
|
neighbors[current] = append(neighbors[current], node(width+(height+1)*maxY))
|
||||||
|
}
|
||||||
|
if width > 0 {
|
||||||
|
neighbors[current] = append(neighbors[current], node(width+height*maxY-1))
|
||||||
|
}
|
||||||
|
if width < maxX {
|
||||||
|
neighbors[current] = append(neighbors[current], node(width+height*maxY+1))
|
||||||
|
|
||||||
|
}
|
||||||
|
width--
|
||||||
|
}
|
||||||
|
height--
|
||||||
|
}
|
||||||
|
return weights, neighbors
|
||||||
|
}
|
51
d15/d15_test.go
Normal file
51
d15/d15_test.go
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package d15
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestP1(t *testing.T) {
|
||||||
|
result := P1(`1163751742
|
||||||
|
1381373672
|
||||||
|
2136511328
|
||||||
|
3694931569
|
||||||
|
7463417111
|
||||||
|
1319128137
|
||||||
|
1359912421
|
||||||
|
3125421639
|
||||||
|
1293138521
|
||||||
|
2311944581`)
|
||||||
|
|
||||||
|
assert.EqualValues(t, 40, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestP2(t *testing.T) {
|
||||||
|
result := P2(`1163751742
|
||||||
|
1381373672
|
||||||
|
2136511328
|
||||||
|
3694931569
|
||||||
|
7463417111
|
||||||
|
1319128137
|
||||||
|
1359912421
|
||||||
|
3125421639
|
||||||
|
1293138521
|
||||||
|
2311944581`)
|
||||||
|
|
||||||
|
assert.EqualValues(t, 315, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkP2(t *testing.B) {
|
||||||
|
P2(`1163751742
|
||||||
|
1381373672
|
||||||
|
2136511328
|
||||||
|
3694931569
|
||||||
|
7463417111
|
||||||
|
1319128137
|
||||||
|
1359912421
|
||||||
|
3125421639
|
||||||
|
1293138521
|
||||||
|
2311944581`)
|
||||||
|
|
||||||
|
}
|
58
d15/dijkstra.go
Normal file
58
d15/dijkstra.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package d15
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type node int
|
||||||
|
|
||||||
|
type weights map[node]int
|
||||||
|
|
||||||
|
type neighbors map[node][]node
|
||||||
|
|
||||||
|
func minDistance(unvisited weights, distances weights) node {
|
||||||
|
var min node
|
||||||
|
var minDistance = math.MaxInt64
|
||||||
|
for current := range unvisited {
|
||||||
|
if distances[current] < minDistance {
|
||||||
|
min = current
|
||||||
|
minDistance = distances[current]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
func assignMap[M ~map[K]V, K comparable, V any](m M, v V) M {
|
||||||
|
n := make(M, len(m))
|
||||||
|
for k := range m {
|
||||||
|
n[k] = v
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func dijkstra(start node, end node, weights weights, neighbors neighbors) int {
|
||||||
|
distances := assignMap(weights, math.MaxInt64)
|
||||||
|
unvisited := maps.Clone(weights)
|
||||||
|
|
||||||
|
distances[start] = 0
|
||||||
|
|
||||||
|
for len(unvisited) != 0 {
|
||||||
|
current := minDistance(unvisited, distances)
|
||||||
|
|
||||||
|
delete(unvisited, current)
|
||||||
|
|
||||||
|
for _, neighbor := range neighbors[current] {
|
||||||
|
oldDistance := distances[neighbor]
|
||||||
|
newDistance := weights[neighbor] + distances[current]
|
||||||
|
if newDistance < oldDistance {
|
||||||
|
distances[neighbor] = newDistance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return distances[end]
|
||||||
|
}
|
7
d15/dijkstra_test.go
Normal file
7
d15/dijkstra_test.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package d15
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestDijkstra(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
6
d15/p1.go
Normal file
6
d15/p1.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package d15
|
||||||
|
|
||||||
|
func P1(in string) int {
|
||||||
|
weights, neighbors := weightNeighbors(in)
|
||||||
|
return dijkstra(0, node(len(weights)-1), weights, neighbors)
|
||||||
|
}
|
61
d15/p2.go
Normal file
61
d15/p2.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package d15
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func expand(in [][]int) [][]int {
|
||||||
|
height := len(in)
|
||||||
|
width := len(in[0])
|
||||||
|
|
||||||
|
expanded := make([][]int, height*5)
|
||||||
|
|
||||||
|
for y := range expanded {
|
||||||
|
expanded[y] = make([]int, width*5)
|
||||||
|
}
|
||||||
|
|
||||||
|
for y, line := range in {
|
||||||
|
for x, num := range line {
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
for j := 0; j < 5; j++ {
|
||||||
|
expanded[y+(height*i)][x+(width*j)] = (num + i + j) % 9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return expanded
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandMap(in string) string {
|
||||||
|
lines := make([][]int, 0)
|
||||||
|
for _, line := range strings.Split(strings.TrimSpace(in), "\n") {
|
||||||
|
nums := make([]int, 0)
|
||||||
|
for _, weight := range strings.Split(line, "") {
|
||||||
|
weight, _ := strconv.Atoi(weight)
|
||||||
|
nums = append(nums, weight)
|
||||||
|
}
|
||||||
|
lines = append(lines, nums)
|
||||||
|
}
|
||||||
|
|
||||||
|
expanded := expand(lines)
|
||||||
|
|
||||||
|
newMap := ""
|
||||||
|
|
||||||
|
for _, line := range expanded {
|
||||||
|
for _, num := range line {
|
||||||
|
newMap = newMap + fmt.Sprint(num)
|
||||||
|
}
|
||||||
|
|
||||||
|
newMap += "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func P2(in string) int {
|
||||||
|
weights, neighbors := weightNeighbors(expandMap(in))
|
||||||
|
return dijkstra(0, node(len(weights)-1), weights, neighbors)
|
||||||
|
}
|
Loading…
Reference in a new issue