code.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. )
  8. type Point struct {
  9. y, x int
  10. steps int
  11. }
  12. func (p Point) key() string {
  13. return fmt.Sprintf("%d_%d", p.y, p.x)
  14. }
  15. func readInput(file *os.File) []Point {
  16. scanner := bufio.NewScanner(file)
  17. var points []Point
  18. for scanner.Scan() {
  19. line := scanner.Text()
  20. if line == "" {
  21. break
  22. }
  23. var point Point
  24. n, err := fmt.Sscanf(line, "%d,%d", &point.x, &point.y)
  25. if n != 2 || err != nil {
  26. log.Fatalf("Not able to parse byte '%s': %s", line, err)
  27. }
  28. points = append(points, point)
  29. }
  30. return points
  31. }
  32. var directions [][]int = [][]int{
  33. {0, -1}, {1, 0}, {0, 1}, {-1, 0},
  34. }
  35. func getObstaclesMap(obstacles []Point, howMany, xMax, yMax int) map[string]bool {
  36. obstaclesMap := make(map[string]bool)
  37. for i := 0; i < howMany; i++ {
  38. if obstacles[i].x < xMax && obstacles[i].y < yMax {
  39. obstaclesMap[obstacles[i].key()] = true
  40. }
  41. }
  42. return obstaclesMap
  43. }
  44. func getMoves(current Point, obstaclesMap map[string]bool, xMax, yMax int) []Point {
  45. var moves []Point
  46. for _, direction := range directions {
  47. move := Point{x: current.x + direction[0], y: current.y + direction[1], steps: current.steps + 1}
  48. if move.x < 0 || move.y < 0 || move.x > xMax || move.y > yMax {
  49. continue
  50. }
  51. if !obstaclesMap[move.key()] {
  52. moves = append(moves, move)
  53. }
  54. }
  55. return moves
  56. }
  57. func hike(obstaclesMap map[string]bool, xMax, yMax int) int {
  58. steps := 1000000000
  59. visited := make(map[string]int)
  60. goal := Point{x: xMax, y: yMax}
  61. moves := []Point{Point{x: 0, y: 0}}
  62. for len(moves) > 0 {
  63. current := moves[0]
  64. moves = moves[1:]
  65. if current.x == goal.x && current.y == goal.y && current.steps < steps {
  66. steps = current.steps
  67. }
  68. newMoves := getMoves(current, obstaclesMap, xMax, yMax)
  69. for _, newMove := range newMoves {
  70. if visited[newMove.key()] == 0 || visited[newMove.key()] > newMove.steps {
  71. moves = append(moves, newMove)
  72. visited[newMove.key()] = newMove.steps
  73. }
  74. }
  75. }
  76. return steps
  77. }
  78. func part1(obstacles []Point, howMany, xMax, yMax int) int {
  79. obstaclesMap := getObstaclesMap(obstacles, howMany, xMax+1, yMax+1)
  80. return hike(obstaclesMap, xMax, yMax)
  81. }
  82. func main() {
  83. if len(os.Args) < 2 {
  84. log.Fatal("You need to specify a file!")
  85. }
  86. filePath := os.Args[1]
  87. file, err := os.Open(filePath)
  88. if err != nil {
  89. log.Fatalf("Failed to open %s!\n", filePath)
  90. }
  91. obstacles := readInput(file)
  92. fmt.Println("Part1:", part1(obstacles, 1024, 70, 70))
  93. }