Watch
1
0
Fork
You've already forked advent-of-code
0

Compare commits

..
Author SHA1 Message Date
db081bed30 2017 Day 13 Part 2 2026-08-08 14:08:51 -04:00
3421534adb 2017 Day 13 Part 1 2026-07-31 16:28:58 -04:00
c282317273 2017 Day 12 Part 2 2026-07-31 16:09:49 -04:00
405f8bf533 2017 Day 12 Part 1 2026-07-31 16:05:30 -04:00
2 changed files with 141 additions and 0 deletions

42
2017/day12.py Normal file
View file

@ -0,0 +1,42 @@
from collections import defaultdict
with open("input/day12.txt") as f:
input = f.read()
neighbors = defaultdict(set)
for line in input.splitlines():
a, bs = line.split(" <-> ")
for b in bs.split(", "):
neighbors[a].add(b)
neighbors[b].add(a)
def connected(start, neighbors):
queue = [start]
seen = set()
while queue:
node = queue.pop(0)
if node in seen:
continue
seen.add(node)
queue.extend(neighbors[node])
return seen
def groups(neighbors) -> int:
seeds = set(neighbors.keys())
count = 0
while seeds:
start = seeds.pop()
seen = connected(start, neighbors)
seeds.difference_update(seen)
count += 1
return count
print(len(connected("0", neighbors)))
print(groups(neighbors))

99
2017/day13.py Normal file
View file

@ -0,0 +1,99 @@
from math import lcm
from dataclasses import dataclass
with open("input/day13.txt") as f:
input = f.read()
scanners: dict[int, int] = {}
for line in input.splitlines():
parts = line.split(": ")
d, r = int(parts[0]), int(parts[1])
assert d not in scanners, "no overlapping scanners"
scanners[d] = r
def part1(scanners):
severity = 0
for d in range(max(scanners.keys()) + 1):
r = scanners.get(d)
if r is None:
continue
assert r > 1, r
cycle = (r - 1) * 2
pos = d % cycle
if pos == 0:
severity += d * r
return severity
def is_safe(scanners, delay):
for depth in range(max(scanners.keys()) + 1):
r = scanners.get(depth)
if r is None:
continue
assert r > 1, r
cycle = (r - 1) * 2
pos = (delay + depth) % cycle
if pos == 0:
return False
return True
@dataclass
class Scanner:
depth: int
cycle: int
@dataclass(order=True)
class Candidate:
delay: int
increment: int
def __init__(self, delay: int, increment: int):
self.delay = delay % increment
self.increment = increment
def __hash__(self):
return hash((self.delay % self.increment, self.increment))
def scale(self, scalar: int) -> set["Candidate"]:
res = set()
increment = self.increment * scalar
for i in range(scalar + 1):
res.add(Candidate(self.delay + i * self.increment, increment))
return res
def __str__(self):
return f"{self.delay} + k * {self.increment}"
def part2(scanner_map: dict[int, int]):
scanners: list[Scanner] = []
for depth in range(max(scanner_map.keys()) + 1):
r = scanner_map.get(depth)
if r is None:
continue
cycle = (r - 1) * 2
scanners.append(Scanner(depth, cycle))
candidates = {Candidate(0, 1)}
for s in scanners:
next: set[Candidate] = set()
for c in candidates:
scalar = lcm(c.increment, s.cycle) // c.increment
for n in c.scale(scalar):
if (n.delay + s.depth) % s.cycle:
next.add(n)
candidates = next
return min(c.delay for c in candidates)
print(part1(scanners))
print(part2(scanners))