code.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "sort"
  8. "strings"
  9. )
  10. type Dig struct {
  11. direction string
  12. length int
  13. color string
  14. }
  15. func readInput(file *os.File) []Dig {
  16. scanner := bufio.NewScanner(file)
  17. var plan []Dig
  18. for scanner.Scan() {
  19. line := scanner.Text()
  20. if line == "" {
  21. break
  22. }
  23. var current Dig
  24. n, err := fmt.Sscanf(line, "%s %d %s", &current.direction, &current.length, &current.color)
  25. if n != 3 || err != nil {
  26. log.Fatalf("Wrong input: %s\n%s", line, err)
  27. }
  28. current.color = strings.Trim(current.color, "()")
  29. plan = append(plan, current)
  30. }
  31. return plan
  32. }
  33. type Point struct {
  34. y, x int
  35. }
  36. const (
  37. Up = "U"
  38. Down = "D"
  39. Left = "L"
  40. Right = "R"
  41. )
  42. func (p *Point) getPoints(dig Dig, wasHere map[Point]bool) []Point {
  43. var points []Point
  44. for i := 0; i < dig.length; i++ {
  45. switch dig.direction {
  46. case Up:
  47. p.y--
  48. case Down:
  49. p.y++
  50. case Left:
  51. p.x--
  52. case Right:
  53. p.x++
  54. }
  55. if !wasHere[*p] {
  56. wasHere[*p] = true
  57. points = append(points, *p)
  58. }
  59. }
  60. return points
  61. }
  62. func plot(plan []Dig) []Point {
  63. var current Point
  64. result := []Point{current}
  65. wasHere := make(map[Point]bool)
  66. wasHere[current] = true
  67. for i := range plan {
  68. result = append(result, current.getPoints(plan[i], wasHere)...)
  69. }
  70. sort.Slice(result, func(i, j int) bool {
  71. if result[i].y == result[j].y {
  72. return result[i].x < result[j].x
  73. }
  74. return result[i].y < result[j].y
  75. })
  76. return result
  77. }
  78. func countBetween(plot []Point) int {
  79. var count int
  80. edge := len(plot)
  81. prev := plot[0]
  82. for i := 1; i < edge; i++ {
  83. if prev.y == plot[i].y {
  84. if prev.x == plot[i].x {
  85. continue
  86. }
  87. c := plot[i].x - prev.x - 1
  88. count += c
  89. if c > 0 && i+1 < edge {
  90. prev = plot[i+1]
  91. continue
  92. }
  93. }
  94. prev = plot[i]
  95. }
  96. return count
  97. }
  98. func main() {
  99. if len(os.Args) < 2 {
  100. log.Fatal("You need to specify a file!")
  101. }
  102. filePath := os.Args[1]
  103. file, err := os.Open(filePath)
  104. if err != nil {
  105. log.Fatalf("Failed to open %s!\n", filePath)
  106. }
  107. plan := readInput(file)
  108. plot := plot(plan)
  109. fmt.Println("Part1:", countBetween(plot)+len(plot))
  110. }