You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
2.8 KiB
Go
145 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
)
|
|
|
|
type Graph struct {
|
|
nodes map[Node]int
|
|
neighbours map[Node]map[Node]bool
|
|
}
|
|
|
|
type Node struct {
|
|
x, y int
|
|
}
|
|
|
|
const expansions = 1
|
|
|
|
func main() {
|
|
file, err := os.Open("input.txt")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
var grid [][]int
|
|
graph := Graph{make(map[Node]int), make(map[Node]map[Node]bool)}
|
|
|
|
var y int
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if y == 0 {
|
|
grid = make([][]int, len(line)*expansions)
|
|
for i := range grid {
|
|
grid[i] = make([]int, len(line)*expansions)
|
|
}
|
|
}
|
|
for x, char := range line {
|
|
num, _ := strconv.Atoi(string(char))
|
|
|
|
for expandY := 0; expandY < expansions; expandY++ {
|
|
for expandX := 0; expandX < expansions; expandX++ {
|
|
expandNum := num + expandX + expandY
|
|
if expandNum >= 10 {
|
|
expandNum = (expandNum % 10) + 1
|
|
}
|
|
yPoint, xPoint := y+len(line)*expandY, x+len(line)*expandX
|
|
grid[yPoint][xPoint] = expandNum
|
|
node := Node{xPoint, yPoint}
|
|
graph.nodes[node] = grid[yPoint][xPoint]
|
|
}
|
|
}
|
|
}
|
|
y++
|
|
}
|
|
|
|
for y := 0; y < len(grid); y++ {
|
|
for x := 0; x < len(grid[0]); x++ {
|
|
node := Node{x, y}
|
|
if graph.neighbours[node] == nil {
|
|
graph.neighbours[node] = make(map[Node]bool)
|
|
}
|
|
|
|
if x+1 < len(grid[0]) {
|
|
nextXNode := Node{x + 1, y}
|
|
if graph.neighbours[nextXNode] == nil {
|
|
graph.neighbours[nextXNode] = make(map[Node]bool)
|
|
}
|
|
graph.neighbours[node][nextXNode] = true
|
|
graph.neighbours[nextXNode][node] = true
|
|
}
|
|
|
|
if y+1 < len(grid) {
|
|
nextYNode := Node{x, y + 1}
|
|
if graph.neighbours[nextYNode] == nil {
|
|
graph.neighbours[nextYNode] = make(map[Node]bool)
|
|
}
|
|
graph.neighbours[node][nextYNode] = true
|
|
graph.neighbours[nextYNode][node] = true
|
|
}
|
|
}
|
|
}
|
|
|
|
target := Node{len(grid) - 1, len(grid) - 1}
|
|
dist := dijkstra(graph, Node{0, 0}, target)
|
|
|
|
fmt.Println(dist[target])
|
|
}
|
|
|
|
func dijkstra(g Graph, source Node, target Node) (dist map[Node]int) {
|
|
Q := make(map[Node]bool)
|
|
dist = make(map[Node]int)
|
|
prev := make(map[Node]Node)
|
|
|
|
for v := range g.nodes {
|
|
dist[v] = 0x7fffffffffffffff
|
|
Q[v] = true
|
|
}
|
|
dist[source] = 0
|
|
|
|
for len(Q) > 0 {
|
|
|
|
minInQ := 0x7fffffffffffffff
|
|
var v Node
|
|
for node := range Q {
|
|
if dist[node] < minInQ {
|
|
v = node
|
|
minInQ = dist[node]
|
|
}
|
|
}
|
|
delete(Q, v)
|
|
|
|
if v == target {
|
|
S := make([]Node, 0)
|
|
u := target
|
|
|
|
if _, ok := prev[u]; ok || u == source {
|
|
for u != (Node{}) {
|
|
S = append([]Node{u}, S...)
|
|
u = prev[u]
|
|
}
|
|
fmt.Println()
|
|
}
|
|
}
|
|
|
|
for u := range g.neighbours[v] {
|
|
if _, ok := Q[u]; !ok {
|
|
continue
|
|
}
|
|
alt := dist[v] + g.nodes[u]
|
|
if alt < dist[u] {
|
|
dist[u] = alt
|
|
prev[v] = u
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|