Created
August 15, 2020 15:16
-
-
Save techieji/4407f6bd7f50ff262b5754b32f6e8f54 to your computer and use it in GitHub Desktop.
Experiments.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import time | |
| import math | |
| import operator | |
| from inspect import signature | |
| import random | |
| class func: | |
| class msg: | |
| ok = True | |
| error = False | |
| def __init__(self, msg, value): | |
| self.msg = msg | |
| self.value = value | |
| def __str__(self): | |
| return (self.msg, self.value).__str__() | |
| def __repr__(self): | |
| return (self.msg, self.value).__repr__() | |
| def nofail(function): | |
| def f(*args, **kwargs): | |
| try: | |
| return func.msg(func.msg.ok, function(*args, **kwargs)) | |
| except Exception as e: | |
| return func.msg(func.msg.error, e) | |
| return f | |
| class thunk: | |
| def __init__(self, func: callable, *args, **kwargs): | |
| self.func = func | |
| self.args = args | |
| self.kwargs = kwargs | |
| self.num = len(signature(func).parameters) | |
| def __call__(self, *args, **kwargs): | |
| num = len(self.args) + len(args) + len(self.kwargs) + len(kwargs) | |
| if num == self.num: | |
| return self.func(*self.args, *args, **self.kwargs, **kwargs) | |
| elif num < self.num: | |
| return func.thunk(self, *self.args, *args, **self.kwargs, **kwargs) | |
| else: | |
| raise TypeError(f"Exactly {self.num} arguments are needed ({num} given)") | |
| class enum(list): | |
| def pipe(self, fn, *args, **kwargs): | |
| return fn(self, *args, **kwargs) | |
| def chunk_by(i, fn): | |
| i = iter(i) | |
| ans = [[next(i)]] | |
| for x in i: | |
| lastres = fn(ans[-1][0]) | |
| if fn(x) != lastres: | |
| ans.append([]) | |
| ans[-1].append(x) | |
| return ans | |
| def dedup_by(i, fn): | |
| i = iter(i) | |
| ans = [next(i)] | |
| for x in i: | |
| if fn(x) != fn(ans[-1]): | |
| ans.append(x) | |
| return ans | |
| def dedup(i): | |
| return func.enum.dedup_by(i, lambda x: x) | |
| def rotate(l: list, shift: int = 1) -> iter: | |
| return (l[-shift:] + l[shift::-1][::-1])[:len(l)] | |
| def find(l: list, index: int) -> object: | |
| l = iter(l) | |
| while index: | |
| next(l) | |
| index -= 1 | |
| return next(l) | |
| def flip(l: list, i1: int, i2: int = None) -> list: | |
| if i2 == None: | |
| i2 = i1 + 1 | |
| i1, i2 = sorted([i1, i2]) | |
| t = type(l) | |
| return l[:i1] + t([l[i2]]) + l[i1 + 1:i2] + t([l[i1]]) + l[i2 + 1:] | |
| def map(l: iter, fn: callable) -> iter: | |
| return type(ls[0])([fn(x) for x in l]) | |
| def flatmap(fn: callable, *ls) -> iter: | |
| ret = [] | |
| for x in zip(*ls): | |
| try: | |
| ret += list(fn(*x)) | |
| except TypeError: | |
| ret += [fn(*x)] | |
| return type(ls[0])(ret) | |
| def filter(fn: callable, l: iter) -> iter: | |
| return type(l)([x for x in l if fn(x)]) | |
| def flatten(l) -> iter: | |
| return func.flatmap(lambda x: x, l) | |
| def foldr(f: callable, acc: object, l: iter) -> object: | |
| for x in l: | |
| acc = f(acc, x) | |
| return acc | |
| def foldl(f: callable, acc: object, l: iter) -> object: | |
| for x in l[::-1]: | |
| acc = f(acc, x) | |
| return acc | |
| def reject(fn: callable, l: iter) -> iter: | |
| return func.enum.filter(lambda x: not(fn(x)), l) | |
| def scanr(f: callable, acc: object, l: iter) -> iter: | |
| def fn(acc, x): | |
| return acc + [f(acc, x)] | |
| l = list(l) | |
| return func.enum.foldr(fn, acc, l) | |
| def scanl(f: callable, acc: object, l: iter) -> iter: | |
| def fn(x, acc): | |
| return acc + [f(x, acc)] | |
| l = list(l) | |
| return func.enum.foldl(fn, acc, l) | |
| def zip(*ls): | |
| return type(ls[0])(zip(*ls)) | |
| def unzip(e: iter): | |
| e = list(e) | |
| ret = [[] for x in range(len(e[0]))] | |
| for x in e: | |
| for i in range(0, len(x)): | |
| ret[i].append(x[i]) | |
| return ret | |
| def take(e: iter, num: int): | |
| e = iter(e) | |
| i = 0 | |
| l = [] | |
| for x in e: | |
| if i == num: | |
| break | |
| l.append(x) | |
| i += 1 | |
| return l | |
| class stream: | |
| def __init__(self, rule: callable): | |
| self.rule = rule | |
| self.i = -1 | |
| self.iter = self | |
| def __next__(self): | |
| self.i += 1 | |
| return self.rule(self.i) | |
| def __iter__(self): | |
| self.i = -1 | |
| return self | |
| def pipe(self, fun, *args, **kwargs): | |
| return fun(self, *args, **kwargs) | |
| def find(s, i): | |
| return s.rule(i) | |
| def from_iter(it: iter): | |
| def f(i): | |
| x = list(it) | |
| index = 0 | |
| try: | |
| return x[i] | |
| except IndexError: | |
| return None | |
| ret = func.stream(f) | |
| ret.iter = it | |
| return ret | |
| def chunk_by(s: iter, fn: callable): | |
| def f(i): | |
| enumed = [] | |
| index = 1 | |
| while len(enumed) < i + 1: | |
| enumed = func.enum.chunk_by(func.enum.take(s, index), fn) | |
| index += 1 | |
| return enumed[-2] | |
| return func.stream(f) | |
| def concat(s1, s2): | |
| def f(i): | |
| if func.stream.find(s1, i) == None: | |
| return func.stream.find(s2, i) | |
| else: | |
| return func.stream.find(s1, i) | |
| return func.stream(f) | |
| def cycle(it): | |
| it = func.stream.from_iter(it) | |
| def f(i): | |
| return func.stream.find(it, i % len(it.iter)) | |
| return func.stream(f) | |
| def dedup_by(it, fn): | |
| last = None | |
| offset = 0 | |
| def f(i): | |
| while fn(func.stream.find(it, i + offset)) == last: | |
| offset += 1 | |
| ret = func.stream.find(it, i + offset) | |
| last = fn(ret) | |
| return ret | |
| return func.stream(f) | |
| def dedup(it): | |
| return func.stream.dedup_by(it, lambda x: x) | |
| def map(s, fn): | |
| def f(i): | |
| return fn(s.rule(i)) | |
| return func.stream(f) | |
| def iterate(start, fn): | |
| def f(i): | |
| start = fn(start) | |
| return start | |
| return stream(f) | |
| class IO: | |
| PORT = "STDIN" | |
| def write(msg): | |
| print(msg) | |
| return msg | |
| def _read1(): | |
| print(f"Using {func.IO.PORT}") | |
| def _read2(filename): | |
| print(f"Reading from {filename}") | |
| def _read3(start, next, close): | |
| print(f"Using {start} to init") | |
| #@func.argoverload(func.IO._read1, func.IO._read2, func.IO._read3) | |
| def read(*args): | |
| print("Incorrect num of args") | |
| def protocol(*functions) -> callable: | |
| def dec(function) -> callable: | |
| def f(*args): | |
| types = list(map(type, args)) | |
| for func in functions: | |
| if list(func.__annotations__.values()) == types: | |
| return func(*args) | |
| return function(*args) | |
| return f | |
| return dec | |
| def guard(condition: callable, default = None) -> callable: | |
| def dec(f: callable) -> callable: | |
| class F: | |
| guardcon = condition | |
| def __call__(self, *args, **kwargs): | |
| if condition(*args, **kwargs): | |
| return f(*args, **kwargs) | |
| else: | |
| return default | |
| return F() | |
| return dec | |
| def patmatch(*functions) -> callable: | |
| def dec(func: callable) -> callable: | |
| def f(*args, **kwargs): | |
| for function in functions: | |
| if type(function).guardcon(*args, **kwargs): | |
| return function(*args, **kwargs) | |
| return func(*args, **kwargs) | |
| return f | |
| return dec | |
| def compose(*functions) -> callable: | |
| def f(*args, **kwargs): | |
| if len(functions) == 1: | |
| return functions[0](*args, **kwargs) | |
| else: | |
| return functions[0](func.compose(*functions[1:])(*args, **kwargs)) | |
| return f | |
| def argoverload(*functions) -> callable: | |
| def dec(function) -> callable: | |
| def f(*args, **kwargs): | |
| for x in functions: | |
| if len(signature(x).parameters) == len(args) + len(kwargs): | |
| return x(*args) | |
| return function(*args) | |
| return f | |
| return dec | |
| def memoize(size: int = None) -> callable: | |
| def dec(function: callable) -> callable: | |
| d = {} | |
| def f(*args, **kwargs): | |
| if size and len(d) > size - 1: | |
| del d[random.choice(d)] | |
| if args not in d.keys(): | |
| d[args] = function(*args, **kwargs) | |
| return d[args] | |
| return f | |
| return dec | |
| def rotateargs(function: callable, shift: int = 1): | |
| def f(*args, **kwargs): | |
| return function(*func.enum.rotate(args, shift), **kwargs) | |
| return f | |
| def flipargs(function: callable, i1: int = 0, i2: int = None) -> callable: | |
| def f(*args, **kwargs): | |
| return function(*func.enum.flip(args, i1, i2), **kwargs) | |
| return f | |
| def match(tree: list, values: list) -> dict: | |
| d = {} | |
| for t, v in zip(tree, values): | |
| if hasattr(t, '__iter__') and type(t) == type(v): | |
| d.update(func.match(t, v)) | |
| else: | |
| d[t] = v | |
| return d | |
| sumofnum = func.thunk(func.enum.foldl, operator.add, 0) | |
| # func.enum.foldr(operator.add, 0, [1, 2, 3]) | |
| print(sumofnum([1, 2, 3])) | |
| # f(0, 3) = 3 | |
| # f(3, 2) = 5 | |
| # f(5, 1) = 6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment