Advertisement
Joezak12

Day 3 Part 1

Apr 9th, 2020
925
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 3.10 KB | None | 0 0
  1. // solution to adventofcode.com day 3 part 1
  2. package main
  3.  
  4. import (
  5.     "bufio"
  6.     "fmt"
  7.     "math"
  8.     "os"
  9.     "strconv"
  10.     "strings"
  11. )
  12.  
  13. const X = 0
  14. const Y = 1
  15. const S = 0 // Start of interval
  16. const E = 1 // End of interval
  17.  
  18. type Caple struct {
  19.     points [][]float64 // store the points where the caple changes direction [[x1, y1], [x2, y2]]. it's float64 to avoid type casting when using the math pkg
  20.     change []int       // record which variable changed since either x or y will change with every move to make things simple
  21. }
  22.  
  23. func (s *Caple) Add(x float64, y float64) {
  24.     s.points = append(s.points, []float64{x, y})
  25. }
  26.  
  27. func (s *Caple) Intersect(s2 *Caple) map[float64]float64 {
  28.     // the keys will be the x values while the values will be the y values
  29.     result := make(map[float64]float64)
  30.     for i := range s.points {
  31.         next := i + 1
  32.         // break if next is out of range
  33.         if next >= len(s.points) {
  34.             break
  35.         }
  36.         A := make(map[int][]float64)
  37.         // which variable is changing
  38.         chg := s.change[i]
  39.         // x interval (x1, x2]
  40.         x1, x2 := s.points[i][X], s.points[next][X]
  41.         // y interval (y1, y2]
  42.         y1, y2 := s.points[i][Y], s.points[next][Y]
  43.         // sort the values like what you expect in an interval
  44.         if x1 < x2 {
  45.             A[X] = append(A[X], x1, x2)
  46.         } else {
  47.             A[X] = append(A[X], x2, x1)
  48.         }
  49.         if y1 < y2 {
  50.             A[Y] = append(A[Y], y1, y2)
  51.         } else {
  52.             A[Y] = append(A[Y], y2, y1)
  53.         }
  54.         for i2 := range s2.points {
  55.             next := i2 + 1
  56.             // break if next is out of range
  57.             if next >= len(s2.points) {
  58.                 break
  59.             }
  60.             B := make(map[int][]float64)
  61.             // which variable is changing
  62.             chg2 := s2.change[i2]
  63.             // x interval (x1, x2]
  64.             x1, x2 := s2.points[i2][X], s2.points[next][X]
  65.             // y interval (y1, y2]
  66.             y1, y2 := s2.points[i2][Y], s2.points[next][Y]
  67.             // sort the values like what you expect in an interval
  68.             if x1 < x2 {
  69.                 B[X] = append(B[X], x1, x2)
  70.             } else {
  71.                 B[X] = append(B[X], x2, x1)
  72.             }
  73.             if y1 < y2 {
  74.                 B[Y] = append(B[Y], y1, y2)
  75.             } else {
  76.                 B[Y] = append(B[Y], y2, y1)
  77.             }
  78.             // if both caples are moving along the same axis
  79.             // (if the same variable is changing)
  80.             // let's say for instance that x is changing
  81.             if chg == chg2 {
  82.                 notChg := 1 - chg
  83.                 // check if the constant (start or end) value (y) is the same otherwise they can't intercept
  84.                 if A[notChg][S] == B[notChg][S] {
  85.                     // check if the can intercept
  86.                     // for example [7,10], [4,6], 7 > 6 that means that they can't intercept
  87.                     if !(A[chg][S] >= B[chg][E] || B[chg][S] >= A[chg][E]) {
  88.                         // the intersection interval is basicly the bigger value between the two starts and the smaller one between the two ends
  89.                         I := []float64{math.Max(A[chg][S], B[chg][S]), math.Min(A[chg][E], B[chg][E])}
  90.                         // + 1 to open the left side of the interval
  91.                         // <= to close the right side of the interval
  92.                         if chg == Y {
  93.                             for y := I[S] + 1; y <= I[E]; y++ {
  94.                                 result[A[X][S]] = y
  95.                             }
  96.                         } else {
  97.                             for x := I[S] + 1; x <= I[E]; x++ {
  98.                                 result[x] = A[Y][S]
  99.                             }
  100.                         }
  101.                     }
  102.                 }
  103.             // if each caple is moving along different axis
  104.             // (if x is changing in the first caple and y is changing in the second caple)
  105.             } else {
  106.                 // check if the constant value of each caple is in the interval in the other one for example if x is changing in l1 and y is changing in l2
  107.                 // l1 x1(5,10], y1=1    l2 x2=6, y2(0,5]
  108.                 // because the constant value y1 is in the interval y2 and
  109.                 // the constant value x2 is in the interval x1 they intercept in the point (6,1)
  110.                 if (B[chg][S] > A[chg][S] && B[chg][S] <= A[chg][E]) && (A[chg2][S] > B[chg2][S] && A[chg2][S] <= B[chg2][E]) {
  111.                     // if the first line's y is changing then store the x value of the first line and the y value of the second line
  112.                     // since they should be constants
  113.                     if chg == Y {
  114.                         result[A[X][S]] = B[Y][S]
  115.                     } else {
  116.                         result[B[X][S]] = A[Y][S]
  117.                     }
  118.                 }
  119.             }
  120.         }
  121.     }
  122.     return result
  123. }
  124.  
  125. func parse(caple []string) *Caple {
  126.     points := new(Caple)
  127.     var x, y float64
  128.     points.Add(x, y)
  129.     for _, value := range caple {
  130.         num, _ := strconv.ParseFloat(value[1:], 64)
  131.         switch value[0] {
  132.         case 'U':
  133.             y += num
  134.             points.change = append(points.change, Y)
  135.         case 'R':
  136.             x += num
  137.             points.change = append(points.change, X)
  138.         case 'D':
  139.             y -= num
  140.             points.change = append(points.change, Y)
  141.         case 'L':
  142.             x -= num
  143.             points.change = append(points.change, X)
  144.         }
  145.         points.Add(x, y)
  146.     }
  147.     return points
  148. }
  149.  
  150. func main() {
  151.     file, _ := os.Open("input_3.txt")
  152.     defer file.Close()
  153.     scanner := bufio.NewScanner(file)
  154.     var caples []string
  155.     for scanner.Scan() {
  156.         caples = append(caples, scanner.Text())
  157.     }
  158.     caple1 := parse(strings.Split(caples[0], ","))
  159.     caple2 := parse(strings.Split(caples[1], ","))
  160.     I := caple1.Intersect(caple2)
  161.     var smallest float64
  162.     first := true // because smallest is initialized to 0
  163.     for x, y := range I {
  164.         x = math.Abs(x)
  165.         y = math.Abs(y)
  166.         if x+y < smallest || first {
  167.             smallest = x + y
  168.         }
  169.         if first {
  170.             first = false
  171.         }
  172.     }
  173.     fmt.Printf("result: %.0f\n", smallest)
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement