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

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
}