mirror of
https://github.com/osmarks/random-stuff
synced 2024-12-26 18:10:34 +00:00
79 lines
1.8 KiB
Python
79 lines
1.8 KiB
Python
from fractions import Fraction
|
||
from functools import reduce
|
||
import sys
|
||
from math import floor
|
||
import random
|
||
|
||
def interpolate(points):
|
||
def mul_polys(p1, p2):
|
||
out = [0] * (len(p1) + len(p2) - 1)
|
||
for i1, c1 in enumerate(p1):
|
||
for i2, c2 in enumerate(p2):
|
||
out[i1 + i2] += c1 * c2
|
||
return out
|
||
def sum_polys(ps):
|
||
out = [0] * max(map(len, ps))
|
||
for p in ps:
|
||
for i, c in enumerate(p):
|
||
out[i] += c
|
||
return out
|
||
def basis(j):
|
||
px = points[j][0]
|
||
out = []
|
||
for x, y in points:
|
||
if x != px:
|
||
div = px - x
|
||
out.append([-Fraction(x, div), Fraction(1, div)])
|
||
return reduce(mul_polys, out)
|
||
out = []
|
||
for i, (x, y) in enumerate(points):
|
||
out.append([c * y for c in basis(i)])
|
||
return sum_polys(out)
|
||
|
||
def evaluate(poly, x):
|
||
y = 0
|
||
for c in reversed(poly):
|
||
y *= x
|
||
y += c
|
||
return y
|
||
|
||
indents = {"\t": 8, " ": 1, " ": Fraction(2, 3), " ": 2, " ": 4, " ": Fraction(4, 3), "": 0}
|
||
def get_indent(line):
|
||
i = 0
|
||
e = 0
|
||
for j, c in enumerate(line):
|
||
if c in indents:
|
||
i += indents[c]
|
||
e = j + 1
|
||
else: break
|
||
return i, e
|
||
|
||
with open(sys.argv[1]) as tplfile:
|
||
counts = [ (lnum, get_indent(line)[0]) for lnum, line in enumerate(tplfile.readlines()) ]
|
||
|
||
counts = random.sample(counts, k=4)
|
||
poly = interpolate(counts)
|
||
|
||
lindents = [ (Fraction(size), char) for char, size in indents.items() if size != 0 ]
|
||
lindents.sort()
|
||
def gen_indent(n):
|
||
n = Fraction(abs(n))
|
||
out = ""
|
||
for (csize, cchar), (nsize, _) in zip(lindents, lindents[1:] + [(100000000000000, " ")]):
|
||
nmult = 0
|
||
while True:
|
||
nxt = nmult + nsize
|
||
if nxt <= n:
|
||
nmult = nxt
|
||
else: break
|
||
|
||
dif = floor((n - nmult) / csize)
|
||
n -= dif * csize
|
||
out += cchar * dif
|
||
return out
|
||
|
||
with open(sys.argv[2]) as infile:
|
||
for lnum, line in enumerate(infile.readlines()):
|
||
line = line[get_indent(line)[1]:]
|
||
print(gen_indent(evaluate(poly, lnum)) + line, end="")
|