You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.go 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package main
  2. import (
  3. "fmt"
  4. "github.com/csmith/aoc-2019/common"
  5. "math"
  6. "strings"
  7. )
  8. type line struct {
  9. from int64
  10. to int64
  11. perp int64
  12. steps int64
  13. }
  14. // readWire reads the instructions for a wire and populates the given slices with the horizontal and vertical lines
  15. // that make up the wire's path.
  16. func readWire(wire string, horizontal *[]line, vertical *[]line) {
  17. moves := strings.Split(wire, ",")
  18. x := int64(0)
  19. y := int64(0)
  20. steps := int64(0)
  21. for _, move := range moves {
  22. length := int64(common.MustAtoi(move[1:]))
  23. switch move[0] {
  24. case 'U':
  25. *vertical = append(*vertical, line{from: y, to: y - length, perp: x, steps: steps})
  26. y -= length
  27. case 'D':
  28. *vertical = append(*vertical, line{from: y, to: y + length, perp: x, steps: steps})
  29. y += length
  30. case 'L':
  31. *horizontal = append(*horizontal, line{from: x, to: x - length, perp: y, steps: steps})
  32. x -= length
  33. case 'R':
  34. *horizontal = append(*horizontal, line{from: x, to: x + length, perp: y, steps: steps})
  35. x += length
  36. }
  37. steps += length
  38. }
  39. }
  40. // checkCrosses checks if any of the given sets of perpendicular lines cross, and returns the
  41. // smallest Manhattan distance to the origin, and the smallest number of combined steps, of
  42. // those crosses.
  43. func checkCrosses(horizontal *[]line, vertical *[]line) (int64, int64) {
  44. var (
  45. bestDistance int64 = math.MaxInt64
  46. bestSteps int64 = math.MaxInt64
  47. )
  48. for _, h := range *horizontal {
  49. for _, v := range *vertical {
  50. var steps int64 = math.MaxInt64
  51. if h.from <= v.perp && v.perp <= h.to {
  52. // If the horizontal line goes left-to-right
  53. if v.from <= h.perp && h.perp <= v.to {
  54. // If the vertical line goes top-to-bottom
  55. steps = (h.steps + v.perp - h.from) + (v.steps + h.perp - v.from)
  56. } else if v.to <= h.perp && h.perp <= v.from {
  57. // If the vertical line goes bottom-to-top
  58. steps = (h.steps + v.perp - h.from) + (v.steps + v.from - h.perp)
  59. } else {
  60. continue
  61. }
  62. } else if h.to <= v.perp && v.perp <= h.from {
  63. // If the horizontal line goes right-to-left
  64. if v.from <= h.perp && h.perp <= v.to {
  65. // If the vertical line goes top-to-bottom
  66. steps = (h.steps + h.from - v.perp) + (v.steps + h.perp - v.from)
  67. } else if v.to <= h.perp && h.perp <= v.from {
  68. // If the vertical line goes bottom-to-top
  69. steps = (h.steps + h.from - v.perp) + (v.steps + v.from - h.perp)
  70. } else {
  71. continue
  72. }
  73. } else {
  74. continue
  75. }
  76. distance := common.Abs(v.perp) + common.Abs(h.perp)
  77. if distance < bestDistance {
  78. bestDistance = distance
  79. }
  80. if steps < bestSteps {
  81. bestSteps = steps
  82. }
  83. }
  84. }
  85. return bestDistance, bestSteps
  86. }
  87. func traceWires() (int64, int64) {
  88. var (
  89. horiz1 []line
  90. horiz2 []line
  91. vert1 []line
  92. vert2 []line
  93. )
  94. wires := common.ReadFileAsStrings("03/input.txt")
  95. readWire(wires[0], &horiz1, &vert1)
  96. readWire(wires[1], &horiz2, &vert2)
  97. d1, s1 := checkCrosses(&horiz1, &vert2)
  98. d2, s2 := checkCrosses(&horiz2, &vert1)
  99. return min(d1, d2), min(s1, s2)
  100. }
  101. func main() {
  102. part1, part2 := traceWires()
  103. fmt.Println(part1)
  104. fmt.Println(part2)
  105. }
  106. func min(a, b int64) int64 {
  107. if a < b {
  108. return a
  109. } else {
  110. return b
  111. }
  112. }