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 }