Browse Source

Day 3

master
Chris Smith 4 years ago
parent
commit
d11b4fecce
Signed by: Chris Smith <chris@chameth.com> GPG Key ID: 3A2D4BBDC4A3C9A9
6 changed files with 165 additions and 0 deletions
  1. 2
    0
      03/answers.txt
  2. 2
    0
      03/input.txt
  3. 91
    0
      03/main.go
  4. 28
    0
      common/geometry.go
  5. 35
    0
      common/io.go
  6. 7
    0
      common/math.go

+ 2
- 0
03/answers.txt View File

@@ -0,0 +1,2 @@
1
+4981
2
+164012

+ 2
- 0
03/input.txt View File

@@ -0,0 +1,2 @@
1
+R1007,D949,R640,D225,R390,D41,R257,D180,L372,U62,L454,U594,L427,U561,R844,D435,L730,U964,L164,U342,R293,D490,L246,U323,L14,D366,L549,U312,L851,U959,L255,U947,L179,U109,R850,D703,L310,U175,L665,U515,R23,D633,L212,U650,R477,U131,L838,D445,R999,D229,L772,U716,L137,U355,R51,D565,L410,D493,L312,U623,L846,D283,R980,U804,L791,U918,L641,U258,R301,U727,L307,U970,L748,U229,L225,U997,L134,D707,L655,D168,L931,D6,R36,D617,L211,D453,L969,U577,R299,D804,R910,D898,R553,U298,L309,D912,R757,U581,R228,U586,L331,D865,R606,D163,R425,U670,R156,U814,L168,D777,R674,D970,L64,U840,L688,U144,L101,U281,L615,D393,R277,U990,L9,U619,L904,D967,L166,U839,L132,U216,R988,U834,R342,U197,L717,U167,L524,U747,L222,U736,L149,D156,L265,U657,L72,D728,L966,U896,R45,D985,R297,U38,R6,D390,L65,D367,R806,U999,L840,D583,R646,U43,L731,D929,L941,D165,R663,U645,L753,U619,R60,D14,L811,D622,L835,U127,L475,D494,R466,U695,R809,U446,R523,D403,R843,U715,L486,D661,L584,U818,L377,D857,L220,U309,R192,U601,R253,D13,L95,U32,L646,D983,R13,U821,L1,U309,L425,U993,L785,U804,L663,U699,L286,U280,R237,U388,L170,D222,L900,U204,R68,D453,R721,U326,L629,D44,R925,D347,R264,D767,L785,U249,R989,D469,L446,D384,L914,U444,R741,U90,R424,U107,R98,U20,R302,U464,L808,D615,R837,U405,L191,D26,R661,D758,L866,D640,L675,U135,R288,D357,R316,D127,R599,U411,R664,D584,L979,D432,R887,D104,R275,D825,L338,D739,R568,D625,L829,D393,L997,D291,L448,D947,L728,U181,L137,D572,L16,U358,R331,D966,R887,D122,L334,D560,R938,D159,R178,D29,L832,D58,R374
2
+L993,U121,L882,U500,L740,D222,R574,U947,L541,U949,L219,D492,R108,D621,L875,D715,R274,D858,R510,U668,R677,U327,L284,U537,L371,U810,L360,U333,L926,D144,R162,U750,L741,D360,R792,D256,L44,D893,R969,D996,L905,D524,R538,U141,R70,U347,L383,U74,R893,D560,L39,U447,L205,D783,L244,D40,R374,U507,L946,D934,R962,D138,L584,U562,L624,U69,L77,D137,L441,U671,L849,D283,L742,D459,R105,D265,R312,D734,R47,D369,R676,D429,R160,D814,L881,D830,R395,U598,L413,U817,R855,D377,L338,D413,L294,U321,L714,D217,L15,U341,R342,D480,R660,D11,L192,U518,L654,U13,L984,D866,R877,U801,R413,U66,R269,D750,R294,D143,R929,D786,R606,U816,L562,U938,R484,U32,R136,U30,L393,U209,L838,U451,L387,U413,R518,D9,L847,D605,L8,D805,R348,D174,R865,U962,R926,U401,R445,U720,L843,U785,R287,D656,L489,D465,L192,U68,L738,U962,R384,U288,L517,U396,L955,U556,R707,U329,L589,U604,L583,U457,R545,D504,L521,U711,L232,D329,L110,U167,R311,D234,R284,D984,L778,D295,R603,U349,R942,U81,R972,D505,L301,U422,R840,U689,R225,D780,R379,D200,R57,D781,R166,U245,L865,U790,R654,D127,R125,D363,L989,D976,R993,U702,L461,U165,L747,U656,R617,D115,L783,U187,L462,U838,R854,D516,L978,U846,R203,D46,R833,U393,L322,D17,L160,D278,R919,U611,L59,U709,L472,U871,L377,U111,L612,D177,R712,U628,R858,D54,L612,D303,R205,U430,R494,D306,L474,U848,R816,D104,L967,U886,L866,D366,L120,D735,R694,D335,R399,D198,R132,D787,L749,D612,R525,U163,R660,U316,R482,D412,L376,U170,R891,D202,R408,D333,R842,U965,R955,U440,L26,U747,R447,D8,R319,D188,L532,D39,L863,D599,R307,U253,R22

+ 91
- 0
03/main.go View File

@@ -0,0 +1,91 @@
1
+package main
2
+
3
+import (
4
+	"fmt"
5
+	"github.com/csmith/aoc-2019/common"
6
+	"math"
7
+	"strings"
8
+)
9
+
10
+var directions = map[byte]common.Point{
11
+	'L': {X: -1, Y: 0},
12
+	'R': {X: +1, Y: 0},
13
+	'U': {X: 0, Y: -1},
14
+	'D': {X: 0, Y: +1},
15
+}
16
+
17
+// buildMap constructs a map of points that one or more wires hit, to a slice
18
+// of ints representing the number of steps each wire takes to reach that point.
19
+// The number of steps is 0 if the point is the origin or if the wire doesn't
20
+// reach that point.
21
+func buildMap(origin common.Point, wires []string) map[common.Point][]int64 {
22
+	points := map[common.Point][]int64{}
23
+
24
+	for n, wire := range wires {
25
+		var (
26
+			pos         = origin
27
+			steps int64 = 0
28
+			moves       = strings.Split(wire, ",")
29
+		)
30
+
31
+		for _, move := range moves {
32
+			dir := directions[move[0]]
33
+			length := common.MustAtoi(move[1:])
34
+
35
+			for i := 0; i < length; i++ {
36
+				pos = pos.Plus(dir)
37
+				steps++
38
+
39
+				val, ok := points[pos]
40
+
41
+				if !ok {
42
+					points[pos] = make([]int64, len(wires))
43
+					val = points[pos]
44
+				}
45
+				val[n] = steps
46
+			}
47
+		}
48
+	}
49
+
50
+	return points
51
+}
52
+
53
+// combinedSteps computes the total number of steps each wire had to take, given a slice of measurements. If not all
54
+// wires have measurement, the second return parameter will be false.
55
+func combinedSteps(steps []int64) (int64, bool) {
56
+	var res int64 = 0
57
+	for _, distance := range steps {
58
+		if distance == 0 {
59
+			return 0, false
60
+		} else {
61
+			res += distance
62
+		}
63
+	}
64
+	return res, true
65
+}
66
+
67
+func main() {
68
+	wires := common.ReadFileAsStrings("03/input.txt")
69
+	origin := common.Point{X: 0, Y: 0}
70
+	points := buildMap(origin, wires)
71
+
72
+	var (
73
+		bestDistance int64 = math.MaxInt64
74
+		bestSteps    int64 = math.MaxInt64
75
+	)
76
+
77
+	for pos, v := range points {
78
+		if combinedSteps, hitAll := combinedSteps(v); hitAll {
79
+			if distance := pos.Manhattan(origin); distance < bestDistance {
80
+				bestDistance = distance
81
+			}
82
+
83
+			if combinedSteps < bestSteps {
84
+				bestSteps = combinedSteps
85
+			}
86
+		}
87
+	}
88
+
89
+	fmt.Println(bestDistance)
90
+	fmt.Println(bestSteps)
91
+}

+ 28
- 0
common/geometry.go View File

@@ -0,0 +1,28 @@
1
+package common
2
+
3
+import (
4
+	"fmt"
5
+)
6
+
7
+// Point represents a point on a 2D grid.
8
+type Point struct {
9
+	X, Y int64
10
+}
11
+
12
+// Plus returns a new Point which is the sum of this point and the other point.
13
+func (p Point) Plus(p2 Point) Point {
14
+	return Point{
15
+		X: p.X + p2.X,
16
+		Y: p.Y + p2.Y,
17
+	}
18
+}
19
+
20
+// String returns a user-friendly string for debugging purposes.
21
+func (p Point) String() string {
22
+	return fmt.Sprintf("(%d, %d)", p.X, p.Y)
23
+}
24
+
25
+// Manhattan calculates the Manhattan distance between this point and the other point.
26
+func (p Point) Manhattan(other Point) int64 {
27
+	return Abs(p.X-other.X) + Abs(p.Y-other.Y)
28
+}

+ 35
- 0
common/io.go View File

@@ -13,12 +13,21 @@ func ReadFileAsInts(path string) []int {
13 13
 	return readIntsWithScanner(path, bufio.ScanLines)
14 14
 }
15 15
 
16
+// ReadFileAsStrings reads all lines from the given path and returns them in a slice of strings.
17
+// If an error occurs, the function will panic.
18
+func ReadFileAsStrings(path string) []string {
19
+	return readStringsWithScanner(path, bufio.ScanLines)
20
+}
21
+
16 22
 // ReadCsvAsInts reads all data from the given path and returns an int slice
17 23
 // containing comma-delimited parts.  If an error occurs, the function will panic.
18 24
 func ReadCsvAsInts(path string) []int {
19 25
 	return readIntsWithScanner(path, scanByCommas)
20 26
 }
21 27
 
28
+// readIntsWithScanner uses a bufio.Scanner to read ints from the file at
29
+// the given path, splitting using the given bufio.SplitFunc. If an error
30
+// occurs at any point, the function will panic.
22 31
 func readIntsWithScanner(path string, splitFunc bufio.SplitFunc) []int {
23 32
 	file, err := os.Open(path)
24 33
 	if err != nil {
@@ -42,6 +51,32 @@ func readIntsWithScanner(path string, splitFunc bufio.SplitFunc) []int {
42 51
 	return parts
43 52
 }
44 53
 
54
+// readStringsWithScanner uses a bufio.Scanner to read strings from the file at
55
+// the given path, splitting using the given bufio.SplitFunc. If an error
56
+// occurs at any point, the function will panic.
57
+func readStringsWithScanner(path string, splitFunc bufio.SplitFunc) []string {
58
+	file, err := os.Open(path)
59
+	if err != nil {
60
+		panic(err)
61
+	}
62
+	defer func() {
63
+		_ = file.Close()
64
+	}()
65
+
66
+	var parts []string
67
+	scanner := bufio.NewScanner(file)
68
+	scanner.Split(splitFunc)
69
+	for scanner.Scan() {
70
+		parts = append(parts, scanner.Text())
71
+	}
72
+
73
+	if scanner.Err() != nil {
74
+		panic(scanner.Err())
75
+	}
76
+
77
+	return parts
78
+}
79
+
45 80
 // scanByCommas is a split function for a Scanner that returns each
46 81
 // comma-separated section of text, with surrounding spaces deleted.
47 82
 // The definition of space is set by unicode.IsSpace.

+ 7
- 0
common/math.go View File

@@ -0,0 +1,7 @@
1
+package common
2
+
3
+// Abs returns the absolute value of x.
4
+func Abs(x int64) int64 {
5
+	y := x >> 63
6
+	return (x ^ y) - y
7
+}

Loading…
Cancel
Save