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

6 years ago
  1. import array, sys, random
  2. from fmd import *
  3. DEBUG_RESTARTS = False
  4. def to_byte_quad(n):
  5. return bytes(ENC[(n >> (6*i)) & 0x3f] for i in range(3, -1, -1))
  6. def from_byte_quad(b):
  7. accum = 0
  8. for v in b:
  9. accum = (accum | ENC_D[v]) << 6
  10. return accum >> 6
  11. def falling_power(base, hi, lo):
  12. res = 0
  13. for i in range(hi, lo, -1):
  14. res += base ** i
  15. return res
  16. print('Loading file...', file=sys.stderr)
  17. frq = array.array('I')
  18. frq.fromfile(open(sys.argv[1], 'rb'), falling_power(64, 4, 0))
  19. print('Calculating totals...', file=sys.stderr)
  20. tot = sum(frq)
  21. print('Total characters:', tot, file=sys.stderr)
  22. gen = int(sys.argv[2])
  23. nz = [idx for idx, i in enumerate(frq) if i > 0]
  24. print(len(nz), 'nonzero entries', file=sys.stderr)
  25. sti = random.choice(nz)
  26. buf = to_byte_quad(sti)
  27. sm = 0
  28. its = 0
  29. hits = [0] * 4
  30. for idx in range(gen):
  31. sys.stdout.buffer.write(buf[0:1])
  32. basebuf = buf[1:] + b'a'
  33. for radix in range(4, 0, -1):
  34. rbase = falling_power(64, 4, radix)
  35. base = rbase + from_byte_quad(basebuf)
  36. nlf = frq[base:base + 64]
  37. #print('NLF @', base, hex(base), ':', nlf)
  38. nznl = [idx for idx, i in enumerate(nlf) if i > 0]
  39. if nznl:
  40. hits[radix - 1] += 1
  41. break
  42. if DEBUG_RESTARTS:
  43. print('Wedge', 5 - radix, ', not found with', basebuf, 'at base', base, '(', hex(base), ') from', rbase, '(', hex(rbase), ')', file=sys.stderr)
  44. sys.stdout.buffer.write(b'~')
  45. basebuf = basebuf[1:]
  46. else:
  47. print('Wedged, no out branch from', buf, file=sys.stderr)
  48. break
  49. sm += len(nznl)
  50. its += 1
  51. nzrg = sum(nlf[i] for i in nznl)
  52. rn = random.randrange(nzrg)
  53. #print()
  54. #print('SEL:', rn, '/', nzrg)
  55. ridx = 63
  56. for idx, f in enumerate(nlf):
  57. rn -= f
  58. if rn <= 0:
  59. ridx = idx
  60. break
  61. else:
  62. print('Bugged, selected out of range rn', rn, 'out of', nzrg)
  63. break
  64. cp = ENC[ridx]
  65. bcp = bytes((cp,))
  66. #print('CP:', ridx, cp, bcp)
  67. buf = buf[1:] + bcp
  68. print()
  69. sys.stdout.flush()
  70. print('Average', sm, '/', its, '=', sm / its, 'branches', file=sys.stderr)
  71. print('Hits:', hits, file=sys.stderr)