def delaunay(cls, points: Sequence[Point], *, context: Context) -> 'Triangulation': """ Constructs Delaunay triangulation of given points. Based on divide-and-conquer algorithm by L. Guibas & J. Stolfi. Time complexity: ``O(len(points) * log len(points))`` Memory complexity: ``O(len(points))`` Reference: http://www.sccg.sk/~samuelcik/dgs/quad_edge.pdf :param points: 3 or more points to triangulate. :param context: geometric context. :returns: triangulation of the points. """ points = sorted(to_distinct(points)) lengths = coin_change(len(points), base_cases) result = [ cls._initialize_triangulation(points[start:stop], context) for start, stop in pairwise(accumulate((0, ) + lengths)) ] for _ in repeat(None, ceil_log2(len(result))): parts_to_merge_count = len(result) // 2 * 2 result = ([ merge(result[offset], result[offset + 1]) for offset in range(0, parts_to_merge_count, 2) ] + result[parts_to_merge_count:]) return result[0]
def from_points(cls, points: Iterable[Point]) -> 'Triangulation': points = sorted(to_unique_objects(points)) lengths = coin_change(len(points), _initializers) result = [ _initialize_triangulation(points[start:stop]) for start, stop in pairwise(accumulate(chain((0, ), lengths))) ] for _ in repeat(None, ceil_log2(len(result))): parts_to_merge_count = len(result) // 2 * 2 result = ([ result[offset]._merge_with(result[offset + 1]) for offset in range(0, parts_to_merge_count, 2) ] + result[parts_to_merge_count:]) return result[0]
def delaunay(cls, points: Sequence[Point], context: Context) -> 'Triangulation': """Constructs Delaunay triangulation from given points.""" points = sorted(points) result = [ cls._initialize_triangulation(points[start:stop], context) for start, stop in pairwise( accumulate(chain(( 0, ), coin_change(len(points), _base_cases)))) ] for _ in repeat(None, ceil_log2(len(result))): parts_to_merge_count = len(result) // 2 * 2 result = ([ result[offset]._merge(result[offset + 1]) for offset in range(0, parts_to_merge_count, 2) ] + result[parts_to_merge_count:]) return result[0]
def test_invalid_denominations(amount: int, denominations: List[int]) -> None: with pytest.raises(ValueError): coin_change(amount, denominations)
def test_properties(amount: int, denominations: List[int]) -> None: result = coin_change(amount, denominations) assert sum(result) >= amount assert len(result) <= ceil_division(amount, min(denominations))
def test_elements(amount: int, denominations: List[int]) -> None: result = coin_change(amount, denominations) assert all(element in denominations for element in result)
def test_basic(amount: int, denominations: List[int]) -> None: result = coin_change(amount, denominations) assert isinstance(result, tuple) assert all(isinstance(element, int) for element in result)