Example #1
0
def pythagorean_triples(n=None):
    """Generate n Pythagorean triples ordered by the value of c ascending. If n
    is None or not given, generate infinitly. Default is None.
    Examples:
    >>> list(pythagorean_triples(5))
    [(3, 4, 5), (5, 12, 13), (15, 8, 17), (7, 24, 25), (21, 20, 29)]
    """
    iterator = _count() if n is None else range(n)
    iterator = iter(iterator)

    base_mat = ((1, 2, 2),
            (2, 1, 2),
            (2, 2, 3))
    multiplier = ((1, -1, 1), (1, 1, 1), (-1, 1, 1))
    matrices = []
    for multip in multiplier:
        mat = []
        for row, elem in zip(base_mat, multip):
            mat.append(tuple(map(lambda e: e * elem, row)))
        matrices.append(tuple(mat))
    matrices = tuple(matrices)

    heap = [(5, (3, 4, 5))]
    for i in iterator:
        _, triple = _heappop(heap)
        yield triple
        for matrix in matrices:
            next_triple = tuple(map(lambda col: sum(_starmap(_mul,
                zip(triple, col))), zip(*matrix)))
            _heappush(heap, (next_triple[2], next_triple))
Example #2
0
    def schedule_interval_soft(self, func, interval, *args, **kwargs):
        """Schedule a function to be called every ``interval`` seconds.

        This method is similar to `schedule_interval`, except that the
        clock will move the interval out of phase with other scheduled
        functions so as to distribute CPU more load evenly over time.

        This is useful for functions that need to be called regularly,
        but not relative to the initial start time.  :py:mod:`pyglet.media`
        does this for scheduling audio buffer updates, which need to occur
        regularly -- if all audio updates are scheduled at the same time
        (for example, mixing several tracks of a music score, or playing
        multiple videos back simultaneously), the resulting load on the
        CPU is excessive for those intervals but idle outside.  Using
        the soft interval scheduling, the load is more evenly distributed.

        Soft interval scheduling can also be used as an easy way to schedule
        graphics animations out of phase; for example, multiple flags
        waving in the wind.

        .. versionadded:: 1.1

        :Parameters:
            `func` : callable
                The function to call when the timer lapses.
            `interval` : float
                The number of seconds to wait between each call.

        """
        next_ts = self._get_soft_next_ts(self._get_nearest_ts(), interval)
        last_ts = next_ts - interval
        item = _ScheduledIntervalItem(func, interval, last_ts, next_ts, args,
                                      kwargs)
        _heappush(self._schedule_interval_items, item)
Example #3
0
 def _n_nearest_items(self, n: int, point: _Point) -> _List[_Item]:
     candidates = []  # type: _List[_Tuple[_Scalar, _Item]]
     queue = [self._root]
     push, pop = queue.append, queue.pop
     while queue:
         node = pop()  # type: _Node
         distance_to_point = node.distance_to_point(point)
         candidate = -distance_to_point, node.item
         if len(candidates) < n:
             _heappush(candidates, candidate)
         elif distance_to_point < -candidates[0][0]:
             _heapreplace(candidates, candidate)
         coordinate = node.projector(point)
         point_is_on_the_left = coordinate < node.projection
         if point_is_on_the_left:
             if node.left is not _NIL:
                 push(node.left)
         elif node.right is not _NIL:
             push(node.right)
         if (len(candidates) < n
                 or (node.distance_to_coordinate(coordinate)
                     < -candidates[0][0])):
             if point_is_on_the_left:
                 if node.right is not _NIL:
                     push(node.right)
             elif node.left is not _NIL:
                 push(node.left)
     return [item for _, item in candidates]
Example #4
0
 def _n_nearest_items(self, n: int, point: _Point) -> _Iterator[_Item]:
     queue = [(0, 0, self._root)]
     while n and queue:
         _, _, node = _heappop(queue)
         for child in node.children:
             _heappush(queue,
                       (child.distance_to_point(point), -child.index -
                        1 if child.is_leaf else child.index, child))
         while n and queue and queue[0][1] < 0:
             _, _, node = _heappop(queue)
             yield node.item
             n -= 1
Example #5
0
    def schedule_once(self, func, delay, *args, **kwargs):
        """Schedule a function to be called once after `delay` seconds.

        The callback function prototype is the same as for `schedule`.

        :Parameters:
            `func` : callable
                The function to call when the timer lapses.
            `delay` : float
                The number of seconds to wait before the timer lapses.
        """
        last_ts = self._get_nearest_ts()
        next_ts = last_ts + delay
        item = _ScheduledIntervalItem(func, 0, last_ts, next_ts, args, kwargs)
        _heappush(self._schedule_interval_items, item)
Example #6
0
    def nearest_item(self, point: _Point) -> _Item:
        """
        Searches for index with box in the tree
        the nearest to the given point.

        Time complexity:
            ``O(max_children * log size)``
        Memory complexity:
            ``O(max_children * log size)``

        where ``size = len(self.boxes)``,
        ``max_children = self.max_children``.

        :param point: input point.
        :returns:
            index with box in the tree the nearest to the input point.

        >>> from ground.base import get_context
        >>> context = get_context()
        >>> Box, Point = context.box_cls, context.point_cls
        >>> boxes = [Box(-index, index, 0, index) for index in range(1, 11)]
        >>> tree = Tree(boxes)
        >>> tree.nearest_item(Point(0, 0)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(-10, 0)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(-10, 10)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(10, 0)) == (9, Box(-10, 10, 0, 10))
        True
        >>> tree.nearest_item(Point(10, 10)) == (9, Box(-10, 10, 0, 10))
        True
        """
        queue = [(0, 0, self._root)]
        while queue:
            _, _, node = _heappop(queue)
            for child in node.children:
                _heappush(queue,
                          (child.distance_to_point(point), -child.index -
                           1 if child.is_leaf else child.index, child))
            if queue and queue[0][1] < 0:
                _, _, node = _heappop(queue)
                return node.item
Example #7
0
    def schedule_interval(self, func, interval, *args, **kwargs):
        """Schedule a function to be called every `interval` seconds.

        Specifying an interval of 0 prevents the function from being
        called again (see `schedule` to call a function as often as possible).

        The callback function prototype is the same as for `schedule`.

        :Parameters:
            `func` : callable
                The function to call when the timer lapses.
            `interval` : float
                The number of seconds to wait between each call.

        """
        last_ts = self._get_nearest_ts()
        next_ts = last_ts + interval
        item = _ScheduledIntervalItem(func, interval, last_ts, next_ts, args, kwargs)
        _heappush(self._schedule_interval_items, item)
Example #8
0
    def nearest_to_point_item(self, point: _Point) -> _Item:
        """
        Searches for index with segment in the tree
        the nearest to the given point.

        Time complexity:
            ``O(max_children * log size)``
        Memory complexity:
            ``O(max_children * log size)``

        where ``size = len(self.segments)``,
        ``max_children = self.max_children``.

        :param point: input point.
        :returns:
            index with segment in the tree the nearest to the input point.

        >>> from ground.base import get_context
        >>> context = get_context()
        >>> Point, Segment = context.point_cls, context.segment_cls
        >>> segments = [Segment(Point(0, index), Point(index, index))
        ...             for index in range(1, 11)]
        >>> tree = Tree(segments)
        >>> (tree.nearest_to_point_item(Point(0, 0))
        ...  == (0, Segment(Point(0, 1), Point(1, 1))))
        True
        """
        queue = [(0, 0, self._root)]
        while queue:
            _, _, node = _heappop(queue)
            for child in node.children:
                _heappush(queue,
                          (child.distance_to_point(point),
                           child.index if child.is_leaf else -child.index - 1,
                           child))
            if queue and queue[0][1] >= 0:
                _, _, node = _heappop(queue)
                return node.item
Example #9
0
 def _put(self, item):
     _heappush(self.queue, item)
Example #10
0
    def call_scheduled_functions(self, dt):
        """Call scheduled functions that elapsed on the last `update_time`.

        .. versionadded:: 1.2

        :Parameters:
            dt : float
                The elapsed time since the last update to pass to each
                scheduled function.  This is *not* used to calculate which
                functions have elapsed.

        :rtype: bool
        :return: True if any functions were called, otherwise False.
        """
        now = self.last_ts
        result = False  # flag indicates if any function was called

        # handle items scheduled for every tick
        if self._schedule_items:
            result = True
            # duplicate list in case event unschedules itself
            for item in list(self._schedule_items):
                item.func(dt, *item.args, **item.kwargs)

        # check the next scheduled item that is not called each tick
        # if it is scheduled in the future, then exit
        interval_items = self._schedule_interval_items
        try:
            if interval_items[0].next_ts > now:
                return result

        # raised when the interval_items list is empty
        except IndexError:
            return result

        # NOTE: there is no special handling required to manage things
        #       that are scheduled during this loop, due to the heap
        self._current_interval_item = item = None
        get_soft_next_ts = self._get_soft_next_ts
        while interval_items:

            # the scheduler will hold onto a reference to an item in
            # case it needs to be rescheduled.  it is more efficient
            # to push and pop the heap at once rather than two operations
            if item is None:
                item = _heappop(interval_items)
            else:
                item = _heappushpop(interval_items, item)

            # a scheduled function may try and unschedule itself
            # so we need to keep a reference to the current
            # item no longer on heap to be able to check
            self._current_interval_item = item

            # if next item is scheduled in the future then break
            if item.next_ts > now:
                break

            # execute the callback
            try:
                item.func(now - item.last_ts, *item.args, **item.kwargs)
            except ReferenceError:
                pass  # weakly-referenced object no longer exists.

            if item.interval:

                # Try to keep timing regular, even if overslept this time;
                # but don't schedule in the past (which could lead to
                # infinitely-worsening error).
                item.next_ts = item.last_ts + item.interval
                item.last_ts = now

                # test the schedule for the next execution
                if item.next_ts <= now:
                    # the scheduled time of this item has already passed
                    # so it must be rescheduled
                    if now - item.next_ts < 0.05:
                        # missed execution time by 'reasonable' amount, so
                        # reschedule at normal interval
                        item.next_ts = now + item.interval
                    else:
                        # missed by significant amount, now many events have
                        # likely missed execution. do a soft reschedule to
                        # avoid lumping many events together.
                        # in this case, the next dt will not be accurate
                        item.next_ts = get_soft_next_ts(now, item.interval)
                        item.last_ts = item.next_ts - item.interval
            else:
                # not an interval, so this item will not be rescheduled
                self._current_interval_item = item = None

        if item is not None:
            _heappush(interval_items, item)

        return True
Example #11
0
 def _put(self, item):
     _heappush(self.queue, item)