Compare commits
2 changed files with 0 additions and 141 deletions
|
|
@ -1,42 +0,0 @@
|
||||||
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))
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
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))
|
|
||||||
Loading…
Reference in a new issue