HasteBin0

Branching Generator Module (V2)

Apr 23rd, 2021 (edited)
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.05 KB | None | 0 0
  1. #!/usr/bin/python3
  2. from asyncio import Task, create_task, run, wait
  3. from collections import deque, namedtuple
  4. from random import randint
  5. from statistics import geometric_mean, harmonic_mean, mean, median, median_high, median_low, mode
  6. from typing import *
  7.  
  8. ''' https://pastebin.com/ELzEaSK8 '''
  9.  
  10. int_iterable = Iterable[int]
  11. _T = TypeVar('_T1', int, float)
  12. ENGINE_T = AsyncGenerator[Tuple[_T, bool], int]
  13.  
  14.  
  15. async def injector(engine: ENGINE_T, qid: int) -> AsyncIterator[int]:
  16.     while True:
  17.         try:
  18.             x, try_again = await engine.asend(qid)
  19.         except StopAsyncIteration:
  20.             break
  21.         if try_again:
  22.             continue
  23.         yield x
  24.  
  25.  
  26. WRAPPER_FXN_T = Callable[[int_iterable], _T]
  27.  
  28.  
  29. def wrapper(fxn: WRAPPER_FXN_T, engine: ENGINE_T, qid: int):
  30.     async def i():
  31.         # TypeError: 'async_generator' object is not iterable
  32.         return fxn(iter(x async for x in injector(engine, qid)))
  33.  
  34.     return i
  35.  
  36.  
  37. class BranchedGenerator:
  38.     _it: int_iterable
  39.     _engine: ENGINE_T
  40.     _queue: Union[tuple, deque]
  41.  
  42.     def __init__(self, it: int_iterable):
  43.         self._it = it
  44.         self._engine = self._make_engine()
  45.         # noinspection PyTypeChecker
  46.         wait(self._engine)
  47.         self._queue = deque()
  48.  
  49.     async def _make_engine(self) -> ENGINE_T:  # it's like a server
  50.         lq = len(self._queue)
  51.         result = try_again = 0, True
  52.         for value in self._it:
  53.             waiting = set(range(lq))
  54.             while True:
  55.                 qid = (yield result)
  56.                 if len(waiting) == 0:
  57.                     result = try_again
  58.                     break
  59.                 if qid in waiting:
  60.                     waiting.remove(qid)
  61.                     result = value, False
  62.                 else:
  63.                     result = try_again
  64.  
  65.     def new(self, fxn: WRAPPER_FXN_T) -> int:
  66.         qid = len(self._queue)
  67.         self._queue.append(wrapper(fxn, self._engine, qid)())
  68.         return qid
  69.  
  70.     def finalize(self):
  71.         self._queue = tuple(self._queue)
  72.  
  73.     def get(self, qid: int) -> Task:
  74.         return create_task(self._queue[qid])
  75.  
  76.     @staticmethod
  77.     @(lambda f: (lambda it, fxns: run(f(it, fxns))))
  78.     def make(it: int_iterable, fxns: Iterable[Callable[[int_iterable], _T]]) -> Tuple[_T, ...]:
  79.         tmp = BranchedGenerator(it)
  80.         qid_range = max(map(tmp.new, fxns))
  81.         tmp.finalize()
  82.         return tuple((await tmp.get(qid)) for qid in range(qid_range + 1))
  83.  
  84.  
  85. seq_stats = namedtuple('seq_stats', ('tuple', 'mean', 'harmonic_mean', 'geometric_mean', 'median', 'median_high', 'median_low', 'mode'))
  86.  
  87.  
  88. @(lambda f: (lambda xs: run(f(xs))))
  89. async def bundle_bg(xs: int_iterable) -> seq_stats:
  90.     tmp = BranchedGenerator(xs)
  91.     # noinspection PyTypeChecker
  92.     ys = seq_stats(
  93.         tmp.new(tuple),
  94.         tmp.new(mean),
  95.         tmp.new(harmonic_mean),
  96.         tmp.new(geometric_mean),
  97.         tmp.new(median),
  98.         tmp.new(median_high),
  99.         tmp.new(median_low),
  100.         tmp.new(mode)
  101.     )
  102.     tmp.finalize()
  103.     return seq_stats(
  104.         await tmp.get(ys.tuple),
  105.         await tmp.get(ys.mean),
  106.         await tmp.get(ys.harmonic_mean),
  107.         await tmp.get(ys.geometric_mean),
  108.         await tmp.get(ys.median),
  109.         await tmp.get(ys.median_high),
  110.         await tmp.get(ys.median_low),
  111.         await tmp.get(ys.mode)
  112.     )
  113.  
  114.  
  115. def bundle(xs: int_iterable) -> seq_stats:
  116.     return seq_stats(
  117.         tuple(xs),
  118.         mean(xs),
  119.         harmonic_mean(xs),
  120.         geometric_mean(xs),
  121.         median(xs),
  122.         median_high(xs),
  123.         median_low(xs),
  124.         mode(xs)
  125.     )
  126.  
  127.  
  128. def display(v: seq_stats):
  129.     print(f'Statistics of {v.tuple}:\n'
  130.           f'\tMean: {v.mean}\n'
  131.           f'\tHarmonic Mean: {v.harmonic_mean}\n'
  132.           f'\tGeometric Mean: {v.geometric_mean}\n'
  133.           f'\tMedian: {v.median}\n'
  134.           f'\tMedian High: {v.median_high}\n'
  135.           f'\tMedian Low: {v.median_low}\n'
  136.           f'\tMode: {v.mode};')
  137.  
  138.  
  139. def new(length: int, inclusive_maximum: int) -> int_iterable:
  140.     return (randint(1, inclusive_maximum) for _ in range(length))
  141.  
  142.  
  143. def test1() -> int:
  144.     sample = new(10, 1 << 65)
  145.     struct1 = bundle_bg(sample)
  146.     display(struct1)
  147.     struct2 = bundle(struct1.tuple)
  148.     display(struct2)
  149.     matches = seq_stats(*(a == b for (a, b) in zip(struct1, struct2)))
  150.     display(matches)
  151.     return sum(((1 >> i) * (not e)) for (i, e) in enumerate(matches))
  152.  
  153.  
  154. @(lambda f: (lambda: run(f())))
  155. async def test2():
  156.     sample = new(1000, 1 << 5)
  157.     # noinspection PyTypeChecker
  158.     struct1 = seq_stats(*await BranchedGenerator.make(sample, (tuple, mean, harmonic_mean, geometric_mean, median, median_high, median_low, mode)))
  159.     display(struct1)
  160.     struct2 = bundle(struct1.tuple)
  161.     display(struct2)
  162.     matches = seq_stats(*(a == b for (a, b) in zip(struct1, struct2)))
  163.     display(matches)
  164.     return sum(((1 >> i) * (not e)) for (i, e) in enumerate(matches))
  165.  
  166.  
  167. @(lambda f: (lambda: run(f())))
  168. async def test3():
  169.     pass
  170.  
  171.  
  172. if __name__ == '__main__':
  173.     exit((test1()))
  174.  
Advertisement
Add Comment
Please, Sign In to add comment