Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // solution to adventofcode.com day 3 part 1
- package main
- import (
- "bufio"
- "fmt"
- "math"
- "os"
- "strconv"
- "strings"
- )
- const X = 0
- const Y = 1
- const S = 0 // Start of interval
- const E = 1 // End of interval
- type Caple struct {
- 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
- change []int // record which variable changed since either x or y will change with every move to make things simple
- }
- func (s *Caple) Add(x float64, y float64) {
- s.points = append(s.points, []float64{x, y})
- }
- func (s *Caple) Intersect(s2 *Caple) map[float64]float64 {
- // the keys will be the x values while the values will be the y values
- result := make(map[float64]float64)
- for i := range s.points {
- next := i + 1
- // break if next is out of range
- if next >= len(s.points) {
- break
- }
- A := make(map[int][]float64)
- // which variable is changing
- chg := s.change[i]
- // x interval (x1, x2]
- x1, x2 := s.points[i][X], s.points[next][X]
- // y interval (y1, y2]
- y1, y2 := s.points[i][Y], s.points[next][Y]
- // sort the values like what you expect in an interval
- if x1 < x2 {
- A[X] = append(A[X], x1, x2)
- } else {
- A[X] = append(A[X], x2, x1)
- }
- if y1 < y2 {
- A[Y] = append(A[Y], y1, y2)
- } else {
- A[Y] = append(A[Y], y2, y1)
- }
- for i2 := range s2.points {
- next := i2 + 1
- // break if next is out of range
- if next >= len(s2.points) {
- break
- }
- B := make(map[int][]float64)
- // which variable is changing
- chg2 := s2.change[i2]
- // x interval (x1, x2]
- x1, x2 := s2.points[i2][X], s2.points[next][X]
- // y interval (y1, y2]
- y1, y2 := s2.points[i2][Y], s2.points[next][Y]
- // sort the values like what you expect in an interval
- if x1 < x2 {
- B[X] = append(B[X], x1, x2)
- } else {
- B[X] = append(B[X], x2, x1)
- }
- if y1 < y2 {
- B[Y] = append(B[Y], y1, y2)
- } else {
- B[Y] = append(B[Y], y2, y1)
- }
- // if both caples are moving along the same axis
- // (if the same variable is changing)
- // let's say for instance that x is changing
- if chg == chg2 {
- notChg := 1 - chg
- // check if the constant (start or end) value (y) is the same otherwise they can't intercept
- if A[notChg][S] == B[notChg][S] {
- // check if the can intercept
- // for example [7,10], [4,6], 7 > 6 that means that they can't intercept
- if !(A[chg][S] >= B[chg][E] || B[chg][S] >= A[chg][E]) {
- // the intersection interval is basicly the bigger value between the two starts and the smaller one between the two ends
- I := []float64{math.Max(A[chg][S], B[chg][S]), math.Min(A[chg][E], B[chg][E])}
- // + 1 to open the left side of the interval
- // <= to close the right side of the interval
- if chg == Y {
- for y := I[S] + 1; y <= I[E]; y++ {
- result[A[X][S]] = y
- }
- } else {
- for x := I[S] + 1; x <= I[E]; x++ {
- result[x] = A[Y][S]
- }
- }
- }
- }
- // if each caple is moving along different axis
- // (if x is changing in the first caple and y is changing in the second caple)
- } else {
- // 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
- // l1 x1(5,10], y1=1 l2 x2=6, y2(0,5]
- // because the constant value y1 is in the interval y2 and
- // the constant value x2 is in the interval x1 they intercept in the point (6,1)
- 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]) {
- // 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
- // since they should be constants
- if chg == Y {
- result[A[X][S]] = B[Y][S]
- } else {
- result[B[X][S]] = A[Y][S]
- }
- }
- }
- }
- }
- return result
- }
- func parse(caple []string) *Caple {
- points := new(Caple)
- var x, y float64
- points.Add(x, y)
- for _, value := range caple {
- num, _ := strconv.ParseFloat(value[1:], 64)
- switch value[0] {
- case 'U':
- y += num
- points.change = append(points.change, Y)
- case 'R':
- x += num
- points.change = append(points.change, X)
- case 'D':
- y -= num
- points.change = append(points.change, Y)
- case 'L':
- x -= num
- points.change = append(points.change, X)
- }
- points.Add(x, y)
- }
- return points
- }
- func main() {
- file, _ := os.Open("input_3.txt")
- defer file.Close()
- scanner := bufio.NewScanner(file)
- var caples []string
- for scanner.Scan() {
- caples = append(caples, scanner.Text())
- }
- caple1 := parse(strings.Split(caples[0], ","))
- caple2 := parse(strings.Split(caples[1], ","))
- I := caple1.Intersect(caple2)
- var smallest float64
- first := true // because smallest is initialized to 0
- for x, y := range I {
- x = math.Abs(x)
- y = math.Abs(y)
- if x+y < smallest || first {
- smallest = x + y
- }
- if first {
- first = false
- }
- }
- fmt.Printf("result: %.0f\n", smallest)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement