Upgrade of >>11 to adaptive sliding window predictor, still alpha. The adapt parameter controls how many window sizes are considered, starting from the full window.
import collections as co
import sys
class Oracle:
def __init__ (self, source):
with open (source, "r") as f:
text = f.read ()
self.text = text
def length (self):
return len (self.text)
def guess (self, index, char):
c = self.text [index]
return True if c == char else c
class Acolyte:
def __init__ (self, oracle):
self.oracle = oracle
self.index = 0
self.score = 0
def length (self):
return self.oracle.length ()
def guess (self, char):
index = self.index
prophecy = self.oracle.guess (index, char)
if prophecy is True:
self.score += 1
self.index = index + 1
return prophecy
def status (self):
length = self.oracle.length ()
index = self.index
score = self.score
return "{}={} {}={} {}={:.6f} {}={} {}={:.6f}".format (
"length", length,
"index", index,
"cover", index / length,
"score", score,
"ratio", score / index if index else 0)
class Temple:
def __init__ (self, argv):
pass
def preach (self, acolyte):
pass
class TempleOfSpace (Temple):
def preach (self, acolyte):
guess = acolyte.guess
for k in range (acolyte.length ()):
guess (' ')
class TempleOfSlidingWindow (Temple):
def __init__ (self, argv):
self.window = int (argv [0])
def preach (self, acolyte):
window = self.window
length = acolyte.length ()
if length < window: return
guess = acolyte.guess
predict = {}
start = ' '
key = ''.join (
map (lambda charguess: charguess [0] if charguess [1] is True else charguess [1],
map (lambda k: (start, guess (start)),
range (window))))
for k in range (window, length):
counts = predict.get (key)
if counts is None:
gu = guess (start)
ch = start if gu is True else gu
predict [key] = co.Counter ([ch])
key = key [1:] + ch
else:
pred = counts.most_common (1) [0] [0]
gu = guess (pred)
ch = pred if gu is True else gu
counts [ch] += 1
key = key [1:] + ch
print ("{}={}".format (
"predict", len (predict)))
class TempleOfAdaptiveSW (Temple):
def __init__ (self, argv):
self.window = int (argv [0])
self.adapt = int (argv [1])
def preach (self, acolyte):
window = self.window
adapt = self.adapt
length = acolyte.length ()
if length < window: return
guess = acolyte.guess
ranada = range (adapt)
predict = [{} for k in ranada]
start = ' '
key = ''.join (
map (lambda charguess: charguess [0] if charguess [1] is True else charguess [1],
map (lambda k: (start, guess (start)),
range (window))))
keys = [key [k:] for k in ranada]
counts = [None] * adapt
for j in range (window, length):
pred = start
most = 0
for k in ranada:
countsk = predict [k].get (keys [k])
counts [k] = countsk
if countsk is not None:
chark, mostk = countsk.most_common (1) [0]
if mostk > most:
most = mostk
pred = chark
gu = guess (pred)
char = pred if gu is True else gu
for k in ranada:
keysk = keys [k]
countsk = counts [k]
if countsk is None:
predict [k] [keysk] = co.Counter ([char])
else:
countsk [char] += 1
keys [k] = keysk [1:] + char
print ("{}={}={}".format (
"predict",
sum (len (p) for p in predict),
[len (p) for p in predict]))
def work_temple (src, templar, rest):
temple = globals () ["TempleOf" + templar] (rest)
oracle = Oracle (src)
acolyte = Acolyte (oracle)
temple.preach (acolyte)
print (acolyte.status ())
def main_temple (argv):
src = argv [0]
temple = argv [1]
rest = argv [2:]
work_temple (src, temple, rest)
def main ():
globals () ["main_" + sys.argv [1]] (sys.argv [2:])
if __name__ == "__main__": main ()