perf: optimize solution 2025/05
This commit is contained in:
@@ -1,48 +1,6 @@
|
|||||||
from typing import Any, Self
|
from typing import Any, TypeAlias
|
||||||
|
|
||||||
|
Range: TypeAlias = tuple[int, int]
|
||||||
class Range:
|
|
||||||
def __init__(self, start: int, end: int) -> None:
|
|
||||||
self.start = start
|
|
||||||
self.end = end
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
return f"{self.start}..={self.end}"
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
|
||||||
return f"Range({self.start}, {self.end})"
|
|
||||||
|
|
||||||
def __len__(self) -> int:
|
|
||||||
return max(self.end - self.start + 1, 0)
|
|
||||||
|
|
||||||
def __eq__(self, value: object, /) -> bool:
|
|
||||||
if not isinstance(value, Range):
|
|
||||||
return False
|
|
||||||
return self.start == value.start and self.end == value.end
|
|
||||||
|
|
||||||
def __contains__(self, value: int) -> bool:
|
|
||||||
return self.start <= value <= self.end
|
|
||||||
|
|
||||||
def discard(self, other: Self) -> list[Self]:
|
|
||||||
r1, r2 = self.start, self.end
|
|
||||||
d1, d2 = other.start, other.end
|
|
||||||
|
|
||||||
res = []
|
|
||||||
|
|
||||||
if r1 < d1:
|
|
||||||
t = min(r2, d1 - 1)
|
|
||||||
res.append(Range(r1, t))
|
|
||||||
|
|
||||||
if r1 < d1 and r2 > d2:
|
|
||||||
res.append(Range(d2 + 1, r2))
|
|
||||||
|
|
||||||
if d1 <= r1 <= d2:
|
|
||||||
res.append(Range(d2 + 1, r2))
|
|
||||||
|
|
||||||
if r1 > d2:
|
|
||||||
res.append(self)
|
|
||||||
|
|
||||||
return list(filter(len, res))
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_input(input_data) -> tuple[list[Range], list[int]]:
|
def _parse_input(input_data) -> tuple[list[Range], list[int]]:
|
||||||
@@ -51,7 +9,7 @@ def _parse_input(input_data) -> tuple[list[Range], list[int]]:
|
|||||||
ranges = []
|
ranges = []
|
||||||
for r in _ranges.splitlines():
|
for r in _ranges.splitlines():
|
||||||
a, b = r.split("-")
|
a, b = r.split("-")
|
||||||
ranges.append(Range(int(a), int(b)))
|
ranges.append((int(a), int(b)))
|
||||||
|
|
||||||
ids = list(map(int, _ids.splitlines()))
|
ids = list(map(int, _ids.splitlines()))
|
||||||
|
|
||||||
@@ -63,8 +21,8 @@ def part_1(input_data: str) -> Any:
|
|||||||
|
|
||||||
c = 0
|
c = 0
|
||||||
for i in ids:
|
for i in ids:
|
||||||
for r in ranges:
|
for r1, r2 in ranges:
|
||||||
if i in r:
|
if r1 <= i <= r2:
|
||||||
c += 1
|
c += 1
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -73,45 +31,28 @@ def part_1(input_data: str) -> Any:
|
|||||||
|
|
||||||
def part_2(input_data: str) -> Any:
|
def part_2(input_data: str) -> Any:
|
||||||
ranges, _ = _parse_input(input_data)
|
ranges, _ = _parse_input(input_data)
|
||||||
res: list[Range] = []
|
|
||||||
|
|
||||||
for i, r1 in enumerate(ranges):
|
points: list[tuple[int, int]] = []
|
||||||
acc = [r1]
|
for i, (r1, r2) in enumerate(ranges):
|
||||||
|
points.extend(((r1, i), (r2, i)))
|
||||||
|
|
||||||
for r2 in ranges[i + 1 :]:
|
points.sort()
|
||||||
nacc = []
|
|
||||||
for r3 in acc:
|
|
||||||
nacc.extend(r3.discard(r2))
|
|
||||||
acc = nacc
|
|
||||||
res.extend(acc)
|
|
||||||
|
|
||||||
return sum(map(len, res))
|
c = 0
|
||||||
|
opened = set()
|
||||||
|
pp = points[0][0] - 1
|
||||||
|
for p, pid in points:
|
||||||
|
o = pid not in opened
|
||||||
|
opened.add(pid) if o else opened.remove(pid)
|
||||||
|
|
||||||
|
if not o or len(opened) > 1:
|
||||||
|
c += p - pp
|
||||||
|
elif p != pp:
|
||||||
|
c += 1
|
||||||
|
|
||||||
def test_range():
|
pp = p
|
||||||
r1 = Range(1, 3)
|
|
||||||
r2 = Range(1, 0)
|
|
||||||
|
|
||||||
# len
|
return c
|
||||||
assert len(r1) == 3
|
|
||||||
assert len(r2) == 0
|
|
||||||
|
|
||||||
# contains
|
|
||||||
assert 0 not in r1
|
|
||||||
assert 1 in r1
|
|
||||||
assert 2 in r1
|
|
||||||
assert 3 in r1
|
|
||||||
assert 4 not in r1
|
|
||||||
|
|
||||||
# eq
|
|
||||||
assert Range(2, 2) == Range(2, 2)
|
|
||||||
assert Range(300, 1234) == Range(300, 1234)
|
|
||||||
assert Range(2, 3) != Range(2, 2)
|
|
||||||
|
|
||||||
# discard
|
|
||||||
r3 = Range(2, 2)
|
|
||||||
assert r1.discard(r2) == [r1]
|
|
||||||
assert r1.discard(r3) == [Range(1, 1), Range(3, 3)]
|
|
||||||
|
|
||||||
|
|
||||||
def test_part_1(example_data):
|
def test_part_1(example_data):
|
||||||
|
|||||||
Reference in New Issue
Block a user