From c23342023b11ea8ea893f37043c0e5370e9671ad Mon Sep 17 00:00:00 2001 From: Brian Buller Date: Thu, 15 Dec 2022 10:57:33 -0600 Subject: [PATCH] 2022 Day 15, part 1 complete Going home from C&C --- 2022/day09/main.go | 56 +++++++++++--- 2022/day15/input | 34 +++++++++ 2022/day15/main.go | 127 +++++++++++++++++++++++++++++++ 2022/day15/problem | 171 ++++++++++++++++++++++++++++++++++++++++++ 2022/day15/testinput | 14 ++++ helpers/coordinate.go | 2 +- helpers/helpers.go | 4 + 7 files changed, 397 insertions(+), 11 deletions(-) create mode 100644 2022/day15/input create mode 100644 2022/day15/main.go create mode 100644 2022/day15/problem create mode 100644 2022/day15/testinput diff --git a/2022/day09/main.go b/2022/day09/main.go index e98a001..fc8e306 100644 --- a/2022/day09/main.go +++ b/2022/day09/main.go @@ -13,17 +13,55 @@ var sleepTime = (time.Second / 5) var minx, miny, maxx, maxy int +var part = -1 +var knots = 2 + func main() { inp := h.StdinToStringSlice() - - watch := len(os.Args) > 1 && strings.HasPrefix(os.Args[1], "-w") - if watch { - if strings.Contains(os.Args[1], "=") { - pts := strings.Split(os.Args[1], "=") - sleepTime = (time.Second / time.Duration(h.Atoi(pts[1]))) + var watch bool + var partSet bool + if len(os.Args) > 1 { + for _, arg := range os.Args[1:] { + if strings.HasPrefix(arg, "-w") { + watch = true + if strings.Contains(arg, "=") { + pts := strings.Split(arg, "=") + sleepTime = (time.Second / time.Duration(h.Atoi(pts[1]))) + } + } else if strings.HasPrefix(arg, "-k") { + if strings.Contains(arg, "=") { + pts := strings.Split(arg, "=") + knots = h.Atoi(pts[1]) + } + } else if strings.HasPrefix(arg, "-p") { + partSet = true + if strings.Contains(arg, "=") { + pts := strings.Split(arg, "=") + part = h.Atoi(pts[1]) + } + } } } - simulate(inp, 10, watch) + if part == 1 { + knots = 2 + } else if part == 2 { + knots = 10 + } + if !watch && !partSet { + // Run both parts + fmt.Println("# Part 1") + simulate(inp, 2, watch) + fmt.Println() + fmt.Println("# Part 2") + simulate(inp, 10, watch) + } else { + if part > 0 && part <= 2 { + fmt.Println("# Part", part) + } else { + fmt.Println("# Simulation with", knots, "knots") + } + simulate(inp, knots, watch) + } } func buildInstructions(inp []string) []byte { @@ -48,7 +86,6 @@ func simulate(inp []string, knotCount int, watch bool) { knots = append(knots, h.Coordinate{X: 0, Y: 0}) } if watch { - fmt.Println("# Part 1") printVisits(visited, knots) } for i, dir := range inst { @@ -57,7 +94,7 @@ func simulate(inp []string, knotCount int, watch bool) { if watch { time.Sleep(sleepTime) fmt.Print(h.CLEAR_SCREEN) - fmt.Printf("# Part 1 (%d/%d)\n", i, len(inst)) + fmt.Printf("# Knots %d (%d/%d)\n", knots, i, len(inst)) printVisits(visited, knots) } } @@ -65,7 +102,6 @@ func simulate(inp []string, knotCount int, watch bool) { time.Sleep(sleepTime) fmt.Print(h.CLEAR_SCREEN) } - fmt.Println("# Part 1") if watch { printVisits(visited, knots) } diff --git a/2022/day15/input b/2022/day15/input new file mode 100644 index 0000000..1999197 --- /dev/null +++ b/2022/day15/input @@ -0,0 +1,34 @@ +Sensor at x=3842919, y=126080: closest beacon is at x=3943893, y=1918172 +Sensor at x=406527, y=2094318: closest beacon is at x=-1066, y=1333278 +Sensor at x=2208821, y=3683408: closest beacon is at x=2914373, y=3062268 +Sensor at x=39441, y=1251806: closest beacon is at x=-1066, y=1333278 +Sensor at x=3093352, y=2404566: closest beacon is at x=2810772, y=2699609 +Sensor at x=3645473, y=2234498: closest beacon is at x=3943893, y=1918172 +Sensor at x=3645012, y=2995540: closest beacon is at x=4001806, y=2787325 +Sensor at x=18039, y=3083937: closest beacon is at x=103421, y=3007511 +Sensor at x=2375680, y=551123: closest beacon is at x=2761373, y=2000000 +Sensor at x=776553, y=123250: closest beacon is at x=-1066, y=1333278 +Sensor at x=2884996, y=2022644: closest beacon is at x=2761373, y=2000000 +Sensor at x=1886537, y=2659379: closest beacon is at x=2810772, y=2699609 +Sensor at x=3980015, y=3987237: closest beacon is at x=3844688, y=3570059 +Sensor at x=3426483, y=3353349: closest beacon is at x=3844688, y=3570059 +Sensor at x=999596, y=1165648: closest beacon is at x=-1066, y=1333278 +Sensor at x=2518209, y=2287271: closest beacon is at x=2761373, y=2000000 +Sensor at x=3982110, y=3262128: closest beacon is at x=3844688, y=3570059 +Sensor at x=3412896, y=3999288: closest beacon is at x=3844688, y=3570059 +Sensor at x=2716180, y=2798731: closest beacon is at x=2810772, y=2699609 +Sensor at x=3575486, y=1273265: closest beacon is at x=3943893, y=1918172 +Sensor at x=7606, y=2926795: closest beacon is at x=103421, y=3007511 +Sensor at x=2719370, y=2062251: closest beacon is at x=2761373, y=2000000 +Sensor at x=1603268, y=1771299: closest beacon is at x=2761373, y=2000000 +Sensor at x=3999678, y=1864727: closest beacon is at x=3943893, y=1918172 +Sensor at x=3157947, y=2833781: closest beacon is at x=2914373, y=3062268 +Sensor at x=3904662, y=2601010: closest beacon is at x=4001806, y=2787325 +Sensor at x=3846359, y=1608423: closest beacon is at x=3943893, y=1918172 +Sensor at x=2831842, y=3562642: closest beacon is at x=2914373, y=3062268 +Sensor at x=3157592, y=1874755: closest beacon is at x=2761373, y=2000000 +Sensor at x=934300, y=2824967: closest beacon is at x=103421, y=3007511 +Sensor at x=3986911, y=1907590: closest beacon is at x=3943893, y=1918172 +Sensor at x=200888, y=3579976: closest beacon is at x=103421, y=3007511 +Sensor at x=967209, y=3837958: closest beacon is at x=103421, y=3007511 +Sensor at x=3998480, y=1972726: closest beacon is at x=3943893, y=1918172 diff --git a/2022/day15/main.go b/2022/day15/main.go new file mode 100644 index 0000000..12d17ca --- /dev/null +++ b/2022/day15/main.go @@ -0,0 +1,127 @@ +package main + +import ( + "fmt" + "math" + "os" + "strings" + + h "git.bullercodeworks.com/brian/adventofcode/helpers" +) + +var part = -1 +var testRow = 2000000 +var watch bool +var watchRows = 1 + +func main() { + inp := h.StdinToStringSlice() + if len(os.Args) > 1 { + for _, arg := range os.Args[1:] { + if strings.HasPrefix(arg, "--part") || strings.HasPrefix(arg, "-p") { + if strings.Contains(arg, "=") { + pts := strings.Split(arg, "=") + part = h.Atoi(pts[1]) + } + } else if strings.HasPrefix(arg, "--row") || strings.HasPrefix(arg, "-r") { + if strings.Contains(arg, "=") { + pts := strings.Split(arg, "=") + testRow = h.Atoi(pts[1]) + } + } else if strings.HasPrefix(arg, "--watch") || strings.HasPrefix(arg, "-w") { + watch = true + if strings.Contains(arg, "=") { + pts := strings.Split(arg, "=") + if pts[1] == "full" { + watchRows = -1 + } else { + watchRows = h.Atoi(pts[1]) + } + } + } + } + } + + part1(inp) + part2(inp) +} + +func part1(inp []string) { + min_x, max_x := math.MaxInt, math.MinInt + var spots [][]int + for i := range inp { + s, b := strToCoords(inp[i]) + xs, ys, xb, yb := s.X, s.Y, b.X, b.Y + dist := s.Distance(b) + l, r := xs-dist, xs+dist + min_x = h.Min(min_x, l) + max_x = h.Max(max_x, r) + spots = append(spots, []int{xs, ys, xb, yb, dist}) + } + var nopeCount int + for x := min_x; x <= max_x; x++ { + for _, c := range spots { + if x == c[2] && testRow == c[3] { + break + } + if h.ManhattanDistance(x, testRow, c[0], c[1]) <= c[4] { + nopeCount++ + break + } + } + } + fmt.Println("# Part 1") + fmt.Println(nopeCount) +} + +func part2(inp []string) { + min_x, max_x := math.MaxInt, math.MinInt + var spots [][]int + for i := range inp { + s, b := strToCoords(inp[i]) + xs, ys, xb, yb := s.X, s.Y, b.X, b.Y + dist := s.Distance(b) + l, r := xs-dist, xs+dist + min_x = h.Min(min_x, l) + max_x = h.Max(max_x, r) + spots = append(spots, []int{xs, ys, xb, yb, dist}) + } + + max := testRow * 2 + var found h.Coordinate +SEARCH: + for y := 0; y <= max; y++ { + for x := 0; x <= max; x++ { + fmt.Printf("Testing %d,%d...", x, y) + var nope bool + for _, c := range spots { + if x == c[2] && y == c[3] { + break + } + if h.ManhattanDistance(x, y, c[0], c[1]) <= c[4] { + nope = true + break + } + } + if !nope { + fmt.Println("Yup") + found = h.Coordinate{X: x, Y: y} + break SEARCH + } + fmt.Println("Nope") + } + } + fmt.Println("# Part 2") + fmt.Println(found) + fmt.Println((found.X * 4000000) + found.Y) +} + +func printMap(m [][]int) { +} + +func strToCoords(s string) (h.Coordinate, h.Coordinate) { + var sensor, beacon h.Coordinate + r := strings.NewReader(s) + fmt.Fscanf(r, "Sensor at x=%d, y=%d: closest beacon is at x=%d, y=%d", &sensor.X, &sensor.Y, &beacon.X, &beacon.Y) + return sensor, beacon +} diff --git a/2022/day15/problem b/2022/day15/problem new file mode 100644 index 0000000..93d540e --- /dev/null +++ b/2022/day15/problem @@ -0,0 +1,171 @@ + Advent of Code + + • [About] + • [Events] + • [Shop] + • [Settings] + • [Log Out] + + br0xen (AoC++) 28* + +    2022 + + • [Calendar] + • [AoC++] + • [Sponsors] + • [Leaderboard] + • [Stats] + + Our sponsors help make Advent of Code possible: + BJSS - Our people are a team of problem solvers, experienced in evolving technologies and delivering + world-class technology solutions. + +--- Day 15: Beacon Exclusion Zone --- + + You feel the ground rumble again as the distress signal leads you to a large network of subterranean tunnels. + You don't have time to search them all, but you don't need to: your pack contains a set of deployable sensors + that you imagine were originally built to locate lost Elves. + + The sensors aren't very powerful, but that's okay; your handheld device indicates that you're close enough to + the source of the distress signal to use them. You pull the emergency sensor system out of your pack, hit the + big button on top, and the sensors zoom off down the tunnels. + + Once a sensor finds a spot it thinks will give it a good reading, it attaches itself to a hard surface and + begins monitoring for the nearest signal source beacon. Sensors and beacons always exist at integer + coordinates. Each sensor knows its own position and can determine the position of a beacon precisely; however, + sensors can only lock on to the one beacon closest to the sensor as measured by the Manhattan distance. (There + is never a tie where two beacons are the same distance to a sensor.) + + It doesn't take long for the sensors to report back their positions and closest beacons (your puzzle input). + For example: + + Sensor at x=2, y=18: closest beacon is at x=-2, y=15 + Sensor at x=9, y=16: closest beacon is at x=10, y=16 + Sensor at x=13, y=2: closest beacon is at x=15, y=3 + Sensor at x=12, y=14: closest beacon is at x=10, y=16 + Sensor at x=10, y=20: closest beacon is at x=10, y=16 + Sensor at x=14, y=17: closest beacon is at x=10, y=16 + Sensor at x=8, y=7: closest beacon is at x=2, y=10 + Sensor at x=2, y=0: closest beacon is at x=2, y=10 + Sensor at x=0, y=11: closest beacon is at x=2, y=10 + Sensor at x=20, y=14: closest beacon is at x=25, y=17 + Sensor at x=17, y=20: closest beacon is at x=21, y=22 + Sensor at x=16, y=7: closest beacon is at x=15, y=3 + Sensor at x=14, y=3: closest beacon is at x=15, y=3 + Sensor at x=20, y=1: closest beacon is at x=15, y=3 + + So, consider the sensor at 2,18; the closest beacon to it is at -2,15. For the sensor at 9,16, the closest + beacon to it is at 10,16. + + Drawing sensors as S and beacons as B, the above arrangement of sensors and beacons looks like this: + + 1 1 2 2 + 0 5 0 5 0 5 + 0 ....S....................... + 1 ......................S..... + 2 ...............S............ + 3 ................SB.......... + 4 ............................ + 5 ............................ + 6 ............................ + 7 ..........S.......S......... + 8 ............................ + 9 ............................ + 10 ....B....................... + 11 ..S......................... + 12 ............................ + 13 ............................ + 14 ..............S.......S..... + 15 B........................... + 16 ...........SB............... + 17 ................S..........B + 18 ....S....................... + 19 ............................ + 20 ............S......S........ + 21 ............................ + 22 .......................B.... + + This isn't necessarily a comprehensive map of all beacons in the area, though. Because each sensor only + identifies its closest beacon, if a sensor detects a beacon, you know there are no other beacons that close or + closer to that sensor. There could still be beacons that just happen to not be the closest beacon to any + sensor. Consider the sensor at 8,7: + + 1 1 2 2 + 0 5 0 5 0 5 + -2 ..........#................. + -1 .........###................ + 0 ....S...#####............... + 1 .......#######........S..... + 2 ......#########S............ + 3 .....###########SB.......... + 4 ....#############........... + 5 ...###############.......... + 6 ..#################......... + 7 .#########S#######S#........ + 8 ..#################......... + 9 ...###############.......... + 10 ....B############........... + 11 ..S..###########............ + 12 ......#########............. + 13 .......#######.............. + 14 ........#####.S.......S..... + 15 B........###................ + 16 ..........#SB............... + 17 ................S..........B + 18 ....S....................... + 19 ............................ + 20 ............S......S........ + 21 ............................ + 22 .......................B.... + + This sensor's closest beacon is at 2,10, and so you know there are no beacons that close or closer (in any + positions marked #). + + None of the detected beacons seem to be producing the distress signal, so you'll need to work out where the + distress beacon is by working out where it isn't. For now, keep things simple by counting the positions where a + beacon cannot possibly be along just a single row. + + So, suppose you have an arrangement of beacons and sensors like in the example above and, just in the row where + y=10, you'd like to count the number of positions a beacon cannot possibly exist. The coverage from all sensors + near that row looks like this: + + 1 1 2 2 + 0 5 0 5 0 5 + 9 ...#########################... + 10 ..####B######################.. + 11 .###S#############.###########. + + In this example, in the row where y=10, there are 26 positions where a beacon cannot be present. + + Consult the report from the sensors you just deployed. In the row where y=2000000, how many positions cannot + contain a beacon? + + To begin, get your puzzle input. + + Answer: _____________________ [ [Submit] ] + + You can also [Shareon Twitter Mastodon] this puzzle. + +References + + Visible links + . https://adventofcode.com/ + . https://adventofcode.com/2022/about + . https://adventofcode.com/2022/events + . https://teespring.com/stores/advent-of-code + . https://adventofcode.com/2022/settings + . https://adventofcode.com/2022/auth/logout + . Advent of Code Supporter + https://adventofcode.com/2022/support + . https://adventofcode.com/2022 + . https://adventofcode.com/2022 + . https://adventofcode.com/2022/support + . https://adventofcode.com/2022/sponsors + . https://adventofcode.com/2022/leaderboard + . https://adventofcode.com/2022/stats + . https://adventofcode.com/2022/sponsors + . https://www.bjss.com/ + . https://en.wikipedia.org/wiki/Taxicab_geometry + . https://adventofcode.com/2022/day/15/input + . https://twitter.com/intent/tweet?text=%22Beacon+Exclusion+Zone%22+%2D+Day+15+%2D+Advent+of+Code+2022&url=https%3A%2F%2Fadventofcode%2Ecom%2F2022%2Fday%2F15&related=ericwastl&hashtags=AdventOfCode + . javascript:void(0); diff --git a/2022/day15/testinput b/2022/day15/testinput new file mode 100644 index 0000000..a612424 --- /dev/null +++ b/2022/day15/testinput @@ -0,0 +1,14 @@ +Sensor at x=2, y=18: closest beacon is at x=-2, y=15 +Sensor at x=9, y=16: closest beacon is at x=10, y=16 +Sensor at x=13, y=2: closest beacon is at x=15, y=3 +Sensor at x=12, y=14: closest beacon is at x=10, y=16 +Sensor at x=10, y=20: closest beacon is at x=10, y=16 +Sensor at x=14, y=17: closest beacon is at x=10, y=16 +Sensor at x=8, y=7: closest beacon is at x=2, y=10 +Sensor at x=2, y=0: closest beacon is at x=2, y=10 +Sensor at x=0, y=11: closest beacon is at x=2, y=10 +Sensor at x=20, y=14: closest beacon is at x=25, y=17 +Sensor at x=17, y=20: closest beacon is at x=21, y=22 +Sensor at x=16, y=7: closest beacon is at x=15, y=3 +Sensor at x=14, y=3: closest beacon is at x=15, y=3 +Sensor at x=20, y=1: closest beacon is at x=15, y=3 diff --git a/helpers/coordinate.go b/helpers/coordinate.go index df9b8b4..abb8459 100644 --- a/helpers/coordinate.go +++ b/helpers/coordinate.go @@ -118,7 +118,7 @@ func (c Coordinate) String() string { } func (c Coordinate) Distance(t Coordinate) int { - return AbsInt(c.X-t.X) + AbsInt(c.Y-t.Y) + return ManhattanDistance(c.X, c.Y, t.X, t.Y) } func (c Coordinate) Equals(c2 Coordinate) bool { diff --git a/helpers/helpers.go b/helpers/helpers.go index 98a796b..24fa588 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -416,3 +416,7 @@ func Sum(l, h int) int { } return ret } + +func ManhattanDistance(x1, y1, x2, y2 int) int { + return AbsInt(x1-x2) + AbsInt(y1-y2) +}