Skip to content

Instantly share code, notes, and snippets.

@techieji
Created August 15, 2020 15:16
Show Gist options
  • Select an option

  • Save techieji/4407f6bd7f50ff262b5754b32f6e8f54 to your computer and use it in GitHub Desktop.

Select an option

Save techieji/4407f6bd7f50ff262b5754b32f6e8f54 to your computer and use it in GitHub Desktop.
Experiments.py
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