You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

83 lines
2.2 KiB

import array, sys, random
from fmd import *
DEBUG_RESTARTS = False
def to_byte_quad(n):
return bytes(ENC[(n >> (6*i)) & 0x3f] for i in range(3, -1, -1))
def from_byte_quad(b):
accum = 0
for v in b:
accum = (accum | ENC_D[v]) << 6
return accum >> 6
def falling_power(base, hi, lo):
res = 0
for i in range(hi, lo, -1):
res += base ** i
return res
print('Loading file...', file=sys.stderr)
frq = array.array('I')
frq.fromfile(open(sys.argv[1], 'rb'), falling_power(64, 4, 0))
print('Calculating totals...', file=sys.stderr)
tot = sum(frq)
print('Total characters:', tot, file=sys.stderr)
gen = int(sys.argv[2])
nz = [idx for idx, i in enumerate(frq) if i > 0]
print(len(nz), 'nonzero entries', file=sys.stderr)
sti = random.choice(nz)
buf = to_byte_quad(sti)
sm = 0
its = 0
hits = [0] * 4
for idx in range(gen):
sys.stdout.buffer.write(buf[0:1])
basebuf = buf[1:] + b'a'
for radix in range(4, 0, -1):
rbase = falling_power(64, 4, radix)
base = rbase + from_byte_quad(basebuf)
nlf = frq[base:base + 64]
#print('NLF @', base, hex(base), ':', nlf)
nznl = [idx for idx, i in enumerate(nlf) if i > 0]
if nznl:
hits[radix - 1] += 1
break
if DEBUG_RESTARTS:
print('Wedge', 5 - radix, ', not found with', basebuf, 'at base', base, '(', hex(base), ') from', rbase, '(', hex(rbase), ')', file=sys.stderr)
sys.stdout.buffer.write(b'~')
basebuf = basebuf[1:]
else:
print('Wedged, no out branch from', buf, file=sys.stderr)
break
sm += len(nznl)
its += 1
nzrg = sum(nlf[i] for i in nznl)
rn = random.randrange(nzrg)
#print()
#print('SEL:', rn, '/', nzrg)
ridx = 63
for idx, f in enumerate(nlf):
rn -= f
if rn <= 0:
ridx = idx
break
else:
print('Bugged, selected out of range rn', rn, 'out of', nzrg)
break
cp = ENC[ridx]
bcp = bytes((cp,))
#print('CP:', ridx, cp, bcp)
buf = buf[1:] + bcp
print()
sys.stdout.flush()
print('Average', sm, '/', its, '=', sm / its, 'branches', file=sys.stderr)
print('Hits:', hits, file=sys.stderr)