aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAn0nSaiko <porfeas12@gmail.com>2022-12-15 17:49:09 +0200
committerAn0nSaiko <porfeas12@gmail.com>2022-12-15 17:49:09 +0200
commitf18f1e47ff95e036c119734b7b792042cbb9246d (patch)
treefee46c655506c7f6e7a573469380c2a6d79a2741
parentDay 14 (diff)
downloadaoc22-f18f1e47ff95e036c119734b7b792042cbb9246d.tar.gz
aoc22-f18f1e47ff95e036c119734b7b792042cbb9246d.zip
Day 15
-rw-r--r--day15/example.txt14
-rw-r--r--day15/input.txt32
-rw-r--r--day15/solution.nim117
3 files changed, 163 insertions, 0 deletions
diff --git a/day15/example.txt b/day15/example.txt
new file mode 100644
index 0000000..a612424
--- /dev/null
+++ b/day15/example.txt
@@ -0,0 +1,14 @@
1Sensor at x=2, y=18: closest beacon is at x=-2, y=15
2Sensor at x=9, y=16: closest beacon is at x=10, y=16
3Sensor at x=13, y=2: closest beacon is at x=15, y=3
4Sensor at x=12, y=14: closest beacon is at x=10, y=16
5Sensor at x=10, y=20: closest beacon is at x=10, y=16
6Sensor at x=14, y=17: closest beacon is at x=10, y=16
7Sensor at x=8, y=7: closest beacon is at x=2, y=10
8Sensor at x=2, y=0: closest beacon is at x=2, y=10
9Sensor at x=0, y=11: closest beacon is at x=2, y=10
10Sensor at x=20, y=14: closest beacon is at x=25, y=17
11Sensor at x=17, y=20: closest beacon is at x=21, y=22
12Sensor at x=16, y=7: closest beacon is at x=15, y=3
13Sensor at x=14, y=3: closest beacon is at x=15, y=3
14Sensor at x=20, y=1: closest beacon is at x=15, y=3
diff --git a/day15/input.txt b/day15/input.txt
new file mode 100644
index 0000000..ec728e8
--- /dev/null
+++ b/day15/input.txt
@@ -0,0 +1,32 @@
1Sensor at x=3428425, y=2345067: closest beacon is at x=3431988, y=2379841
2Sensor at x=928237, y=25774: closest beacon is at x=1212315, y=-161555
3Sensor at x=2061220, y=2396791: closest beacon is at x=2038311, y=2495160
4Sensor at x=1830400, y=2994568: closest beacon is at x=1910058, y=3117415
5Sensor at x=2485733, y=2625804: closest beacon is at x=2038311, y=2495160
6Sensor at x=1855873, y=3971916: closest beacon is at x=1910058, y=3117415
7Sensor at x=119582, y=3929652: closest beacon is at x=311197, y=4221202
8Sensor at x=1069031, y=3509672: closest beacon is at x=1910058, y=3117415
9Sensor at x=3368023, y=2213635: closest beacon is at x=3431988, y=2379841
10Sensor at x=3713877, y=2460862: closest beacon is at x=3431988, y=2379841
11Sensor at x=3593503, y=2174008: closest beacon is at x=3507689, y=2000000
12Sensor at x=501760, y=93436: closest beacon is at x=1212315, y=-161555
13Sensor at x=3712703, y=214999: closest beacon is at x=3507689, y=2000000
14Sensor at x=1594824, y=2790273: closest beacon is at x=1910058, y=3117415
15Sensor at x=2539549, y=3190814: closest beacon is at x=1910058, y=3117415
16Sensor at x=3522790, y=2671548: closest beacon is at x=3431988, y=2379841
17Sensor at x=1001452, y=1327490: closest beacon is at x=1212315, y=-161555
18Sensor at x=629209, y=2451628: closest beacon is at x=-416149, y=2226089
19Sensor at x=2636827, y=1146266: closest beacon is at x=3507689, y=2000000
20Sensor at x=3909, y=625124: closest beacon is at x=1212315, y=-161555
21Sensor at x=3950231, y=3688780: closest beacon is at x=3888160, y=3226725
22Sensor at x=3449978, y=2328058: closest beacon is at x=3431988, y=2379841
23Sensor at x=3974214, y=2582925: closest beacon is at x=3888160, y=3226725
24Sensor at x=82663, y=3225533: closest beacon is at x=311197, y=4221202
25Sensor at x=1958305, y=2292045: closest beacon is at x=2038311, y=2495160
26Sensor at x=3465738, y=2123353: closest beacon is at x=3507689, y=2000000
27Sensor at x=2940758, y=3884337: closest beacon is at x=2746166, y=4800483
28Sensor at x=3429173, y=2275591: closest beacon is at x=3431988, y=2379841
29Sensor at x=1527349, y=38565: closest beacon is at x=1212315, y=-161555
30Sensor at x=3049925, y=2498038: closest beacon is at x=3431988, y=2379841
31Sensor at x=1593202, y=3335178: closest beacon is at x=1910058, y=3117415
32Sensor at x=3175520, y=3230234: closest beacon is at x=3888160, y=3226725
diff --git a/day15/solution.nim b/day15/solution.nim
new file mode 100644
index 0000000..58e2aab
--- /dev/null
+++ b/day15/solution.nim
@@ -0,0 +1,117 @@
1import strutils
2import sequtils
3import re
4import sugar
5import algorithm
6import sets
7
8type
9 Point = tuple
10 x: int
11 y: int
12
13 Range = tuple
14 b: int
15 l: int
16
17 Entry = tuple
18 sensor: Point
19 beacon: Point
20 distance: int
21
22proc distance(A, B: Point): int =
23 result = abs(A.x - B.x) + abs(A.y - B.y)
24
25proc disjoinWith(A, B: Range): bool =
26 return A.b + A.l < B.b
27
28proc rangeContains(r: Range, y: int, p: Point): bool =
29 p.y == y and r.b <= p.x and p.x <= r.b + r.l - 1
30
31proc unite(A, B: Range): Range =
32 assert(A.b <= B.b)
33 assert(not A.disjoinWith(B))
34 result = (A.b, max(A.l, B.b - A.b + B.l))
35
36proc rangeComparator(A, B: Range): int =
37 if A.b < B.b or (A.b == B.b and A.l <= B.l):
38 return -1
39 else:
40 return 1
41
42proc parsePoint(strPoint: string): Point =
43 let tokens = strPoint.split(",")
44 Point((tokens[0].parseInt(), tokens[1].parseInt()))
45
46proc parseEntry(strEntry: string): Entry =
47 let tokens = strEntry.split(":")
48 let points = @[tokens[0].parsePoint(), tokens[1].parsePoint()]
49 Entry((points[0], points[1], distance(points[0], points[1])))
50
51proc parseFile(content: string): seq[Entry] =
52 let lines = content.strip().splitLines()
53
54 let strEntries = map(
55 lines,
56 (line) => line.replace(re"[^0-9\-,:]")
57 )
58
59 result = map(
60 strEntries,
61 parseEntry
62 )
63
64proc emptyRanges(entries: seq[Entry], criticalLine: int): seq[Range] =
65 var emptyRanges: seq[Range]
66 for entry in entries:
67 let
68 distFromLine = abs(entry.sensor.y - criticalLine)
69 rangeFromMid = entry.distance - distFromLine
70 b = entry.sensor.x - rangeFromMid
71 e = entry.sensor.x + rangeFromMid
72 l = e - b + 1
73 if l > 0:
74 emptyRanges.add((b, l))
75
76 emptyRanges.sort(rangeComparator)
77 var
78 curr = emptyRanges[0]
79 lastPushed = true
80
81 for other in emptyRanges[1..^1]:
82 lastPushed = false
83 if curr.disjoinWith(other):
84 result.add(curr)
85 lastPushed = true
86 curr = other
87 else:
88 curr = curr.unite(other)
89
90 if not lastPushed:
91 result.add(curr)
92
93proc part1(entries: seq[Entry], criticalLine = 2_000_000): int =
94 # List of all beacons
95 var beacons: HashSet[Point]
96 for entry in entries:
97 beacons.incl(entry.beacon)
98
99 let empty = emptyRanges(entries, criticalLine)
100 for r in empty:
101 result += r.l
102 for b in beacons:
103 if r.rangeContains(criticalLine, b):
104 result -= 1
105
106proc part2(entries: seq[Entry], criticalLength = 4_000_000): int =
107 for y in 0 .. criticalLength:
108 let empty = emptyRanges(entries, y)
109 if empty.len() == 2:
110 let x = empty[0].b + empty[0].l
111 return x * 4_000_000 + y
112
113let content = readFile("./input.txt")
114let entries = parseFile(content)
115
116echo part1(entries)
117echo part2(entries)