2025-12-05 07:05:13 +00:00

58 lines
1.8 KiB
Python

def parse(input):
ranges = []
ids = []
with open(input) as f:
for line in f:
line = line.strip()
if line == "":
break
lo, _, hi = line.partition("-")
ranges.append((int(lo), int(hi)))
for line in f:
ids.append(int(line.strip()))
return ranges, ids
def solve(input):
# Part 1: count the number of given ids which are within one of the ranges
ranges, ids = parse(input)
t = 0
for x in ids:
for lo,hi in ranges:
if lo <= x <= hi:
t += 1
break
print(t)
# Part 2: count the number of possible ids which are within one of the ranges --
# in other words, the size of the union of all the ranges.
#
# We start by flattening the ranges so that they don't overlap with each other
flattened = []
queue = list(ranges)
while queue:
lo, hi = queue.pop()
found = False
for i,(x,y) in enumerate(flattened):
if not (hi < x or y < lo):
found = True
break
if found:
#print("collapsing ({:,} {:,}) and ({:,} {:,}) -> ({:,} {:,})".format(x,y,lo,hi,min(x,lo),max(y,hi)))
# if x <= lo <= hi < y then the range is unchanged and we don't need to update flattened[i].
# otherwise we need to add the new range to the queue to see if it can be merged with any other entries.
if lo < x or hi > y:
del flattened[i]
queue.append((min(x,lo), max(y,hi)))
else:
flattened.append((lo,hi))
# Then we sum up their sizes. Ranges are inclusive, so +1.
t = 0
for x,y in flattened:
t += y-x + 1
print(t)
solve("sample")
solve("input")