2022 Day 16 Part 1
This commit is contained in:
parent
14c4697ad0
commit
fe486098a2
122
2022/16/README.md
Normal file
122
2022/16/README.md
Normal file
@ -0,0 +1,122 @@
|
||||
# 2022 Day 15: Beacon Exclusion Zone
|
||||
Copyright (c) Eric Wastl
|
||||
#### [Direct Link](https://adventofcode.com/2022/day/15)
|
||||
|
||||
## Part 1
|
||||
|
||||
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](https://en.wikipedia.org/wiki/Taxicab_geometry). (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?**
|
||||
|
||||
## Part 2
|
||||
|
||||
Your handheld device indicates that the distress signal is coming from a beacon nearby. The distress beacon is not detected by any sensor, but the distress beacon must have `x` and `y` coordinates each no lower than `0` and no larger than `4000000`.
|
||||
|
||||
To isolate the distress beacon's signal, you need to determine its **tuning frequency**, which can be found by multiplying its `x` coordinate by `4000000` and then adding its `y` coordinate.
|
||||
|
||||
In the example above, the search space is smaller: instead, the `x` and `y` coordinates can each be at most `20`. With this reduced search area, there is only a single position that could have a beacon: `x=14, y=11`. The tuning frequency for this distress beacon is **`56000011`**.
|
||||
|
||||
Find the only possible position for the distress beacon. **What is its tuning frequency?**
|
51
2022/16/code.py
Normal file
51
2022/16/code.py
Normal file
@ -0,0 +1,51 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2022/day/16
|
||||
|
||||
from re import findall
|
||||
|
||||
def read_file(filename: str = "input.txt") -> dict:
|
||||
pattern = "Valve (\w\w) has flow rate=(\d+); tunnels? leads? to valves? ([A-Z, ]+)"
|
||||
with open(f"{__file__.rstrip('code.py')}{filename}", "r") as f:
|
||||
values = [findall(pattern, line)[0] for line in f.readlines()]
|
||||
return {v[0]: {"flow": int(v[1]), "paths": v[2].split(", ")} for v in values}
|
||||
|
||||
def dijkstra(valves: dict, start: str) -> dict:
|
||||
d = {valve: float("inf") for valve in valves}
|
||||
d[start] = 0
|
||||
to_process = [valve for valve in valves]
|
||||
while to_process:
|
||||
cur = sorted([(d[valve], valve) for valve in to_process])[0][1]
|
||||
to_process.remove(cur)
|
||||
for neighbor in valves[cur]["paths"]:
|
||||
if neighbor in to_process and d[cur] + 1 < d[neighbor]:
|
||||
d[neighbor] = d[cur] + 1
|
||||
return d
|
||||
|
||||
def calc_flow(valves: dict, distances: dict, closed: list, cur_v: str,
|
||||
time: int = 30, released: int = 0, flow: int = 0) -> int:
|
||||
if time < 0:
|
||||
return released
|
||||
if not closed:
|
||||
return released + flow * time
|
||||
outcomes = list()
|
||||
for valve in closed:
|
||||
time_needed = (distances[cur_v][valve] + 1)
|
||||
predicted_flow = calc_flow(valves, distances, [v for v in closed if v != valve], valve,
|
||||
time - time_needed, released + flow * time_needed, flow + valves[valve]["flow"])
|
||||
outcomes.append(released + flow * time if time_needed > time else predicted_flow)
|
||||
return max(outcomes)
|
||||
|
||||
def part1(vals: dict) -> int:
|
||||
dist = {valve: dijkstra(vals, valve) for valve in vals}
|
||||
closed = [valve for valve in vals if vals[valve]["flow"]]
|
||||
return calc_flow(vals, dist, closed, "AA")
|
||||
|
||||
def part2(vals: dict) -> int:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
vals = read_file()
|
||||
print(f"Part 1: {part1(vals)}")
|
||||
print(f"Part 2: {part2(vals)}")
|
59
2022/16/input.txt
Normal file
59
2022/16/input.txt
Normal file
@ -0,0 +1,59 @@
|
||||
Valve AW has flow rate=0; tunnels lead to valves LG, TL
|
||||
Valve OM has flow rate=0; tunnels lead to valves XK, IM
|
||||
Valve BG has flow rate=0; tunnels lead to valves MP, SB
|
||||
Valve XB has flow rate=0; tunnels lead to valves MA, TL
|
||||
Valve CD has flow rate=0; tunnels lead to valves VL, OF
|
||||
Valve VF has flow rate=0; tunnels lead to valves CS, XK
|
||||
Valve HK has flow rate=0; tunnels lead to valves RL, QB
|
||||
Valve QN has flow rate=0; tunnels lead to valves IV, QR
|
||||
Valve OF has flow rate=4; tunnels lead to valves TQ, CD, IR, IM, JE
|
||||
Valve QB has flow rate=14; tunnels lead to valves HK, XE, CS, VO
|
||||
Valve ZE has flow rate=7; tunnels lead to valves JB, NC, SE, OI
|
||||
Valve OW has flow rate=0; tunnels lead to valves MB, JB
|
||||
Valve MA has flow rate=0; tunnels lead to valves XB, MB
|
||||
Valve MP has flow rate=0; tunnels lead to valves VK, BG
|
||||
Valve UE has flow rate=9; tunnels lead to valves ZM, RZ, WI, HO, FO
|
||||
Valve QR has flow rate=24; tunnel leads to valve QN
|
||||
Valve TQ has flow rate=0; tunnels lead to valves OF, AA
|
||||
Valve SE has flow rate=0; tunnels lead to valves ZE, ZZ
|
||||
Valve AQ has flow rate=20; tunnel leads to valve CX
|
||||
Valve XE has flow rate=0; tunnels lead to valves JQ, QB
|
||||
Valve DC has flow rate=8; tunnels lead to valves ZD, MJ, RZ
|
||||
Valve ZM has flow rate=0; tunnels lead to valves YJ, UE
|
||||
Valve VK has flow rate=21; tunnel leads to valve MP
|
||||
Valve VR has flow rate=0; tunnels lead to valves WV, PS
|
||||
Valve BH has flow rate=0; tunnels lead to valves AA, MB
|
||||
Valve ZR has flow rate=0; tunnels lead to valves LG, AI
|
||||
Valve JE has flow rate=0; tunnels lead to valves OF, HO
|
||||
Valve IR has flow rate=0; tunnels lead to valves IV, OF
|
||||
Valve FO has flow rate=0; tunnels lead to valves XQ, UE
|
||||
Valve AA has flow rate=0; tunnels lead to valves NC, VY, BH, TQ, YJ
|
||||
Valve ZZ has flow rate=0; tunnels lead to valves SE, TL
|
||||
Valve XQ has flow rate=0; tunnels lead to valves IV, FO
|
||||
Valve WI has flow rate=0; tunnels lead to valves UE, VO
|
||||
Valve VY has flow rate=0; tunnels lead to valves AA, LG
|
||||
Valve XK has flow rate=15; tunnels lead to valves VF, OM, ZD
|
||||
Valve CX has flow rate=0; tunnels lead to valves AQ, MB
|
||||
Valve JQ has flow rate=0; tunnels lead to valves XE, IV
|
||||
Valve LG has flow rate=3; tunnels lead to valves VY, PS, ZR, AW, OI
|
||||
Valve JB has flow rate=0; tunnels lead to valves ZE, OW
|
||||
Valve OI has flow rate=0; tunnels lead to valves ZE, LG
|
||||
Valve YJ has flow rate=0; tunnels lead to valves ZM, AA
|
||||
Valve NC has flow rate=0; tunnels lead to valves AA, ZE
|
||||
Valve KR has flow rate=0; tunnels lead to valves SB, MJ
|
||||
Valve MB has flow rate=17; tunnels lead to valves CX, BH, AI, OW, MA
|
||||
Valve AI has flow rate=0; tunnels lead to valves ZR, MB
|
||||
Valve TL has flow rate=16; tunnels lead to valves ZZ, XB, AW
|
||||
Valve RL has flow rate=0; tunnels lead to valves WV, HK
|
||||
Valve CS has flow rate=0; tunnels lead to valves VF, QB
|
||||
Valve WV has flow rate=25; tunnels lead to valves RL, VL, VR
|
||||
Valve ZD has flow rate=0; tunnels lead to valves XK, DC
|
||||
Valve IV has flow rate=23; tunnels lead to valves XQ, IR, JQ, QN
|
||||
Valve PS has flow rate=0; tunnels lead to valves VR, LG
|
||||
Valve RZ has flow rate=0; tunnels lead to valves DC, UE
|
||||
Valve VO has flow rate=0; tunnels lead to valves WI, QB
|
||||
Valve MJ has flow rate=0; tunnels lead to valves DC, KR
|
||||
Valve IM has flow rate=0; tunnels lead to valves OM, OF
|
||||
Valve VL has flow rate=0; tunnels lead to valves CD, WV
|
||||
Valve SB has flow rate=18; tunnels lead to valves BG, KR
|
||||
Valve HO has flow rate=0; tunnels lead to valves JE, UE
|
2
2022/16/solution.txt
Normal file
2
2022/16/solution.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Part 1: 1789
|
||||
Part 2: None
|
14
2022/16/test_code.py
Normal file
14
2022/16/test_code.py
Normal file
@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 Akumatic
|
||||
|
||||
from code import read_file, part1, part2
|
||||
|
||||
def test():
|
||||
vals = read_file("test_input.txt")
|
||||
assert part1(vals) == 1651
|
||||
print("Passed Part 1")
|
||||
assert part2(vals) == 1707
|
||||
print("Passed Part 2")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
10
2022/16/test_input.txt
Normal file
10
2022/16/test_input.txt
Normal file
@ -0,0 +1,10 @@
|
||||
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
|
||||
Valve BB has flow rate=13; tunnels lead to valves CC, AA
|
||||
Valve CC has flow rate=2; tunnels lead to valves DD, BB
|
||||
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
|
||||
Valve EE has flow rate=3; tunnels lead to valves FF, DD
|
||||
Valve FF has flow rate=0; tunnels lead to valves EE, GG
|
||||
Valve GG has flow rate=0; tunnels lead to valves FF, HH
|
||||
Valve HH has flow rate=22; tunnel leads to valve GG
|
||||
Valve II has flow rate=0; tunnels lead to valves AA, JJ
|
||||
Valve JJ has flow rate=21; tunnel leads to valve II
|
@ -30,7 +30,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day
|
||||
| 13 | :white_check_mark: | :white_check_mark: | [Solution](13/code.py) | [Day 13](https://adventofcode.com/2022/day/13) |
|
||||
| 14 | :white_check_mark: | :white_check_mark: | [Solution](14/code.py) | [Day 14](https://adventofcode.com/2022/day/14) |
|
||||
| 15 | :white_check_mark: | :white_check_mark: | [Solution](15/code.py) | [Day 15](https://adventofcode.com/2022/day/15) |
|
||||
| 16 | | | | [Day 16](https://adventofcode.com/2022/day/16) |
|
||||
| 16 | :white_check_mark: | | [Solution](16/code.py) | [Day 16](https://adventofcode.com/2022/day/16) |
|
||||
| 17 | | | | [Day 17](https://adventofcode.com/2022/day/17) |
|
||||
| 18 | | | | [Day 18](https://adventofcode.com/2022/day/18) |
|
||||
| 19 | | | | [Day 19](https://adventofcode.com/2022/day/19) |
|
||||
|
Loading…
x
Reference in New Issue
Block a user