partial d15

This commit is contained in:
Gregory 2022-12-16 21:36:57 +02:00
parent 6a046fdb1c
commit 99242d53d7
6 changed files with 227 additions and 0 deletions

44
d15/common.go Normal file
View 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
View 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
View 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
View file

@ -0,0 +1,7 @@
package d15
import "testing"
func TestDijkstra(t *testing.T) {
}

6
d15/p1.go Normal file
View 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
View 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)
}